]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-unit.c
Add SPDX license identifiers to source files under the LGPL
[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("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
802 SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), 0),
803 SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), 0),
804
805 SD_BUS_METHOD("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED),
806 SD_BUS_METHOD("Stop", "s", "o", method_stop, SD_BUS_VTABLE_UNPRIVILEGED),
807 SD_BUS_METHOD("Reload", "s", "o", method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
808 SD_BUS_METHOD("Restart", "s", "o", method_restart, SD_BUS_VTABLE_UNPRIVILEGED),
809 SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart, SD_BUS_VTABLE_UNPRIVILEGED),
810 SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart, SD_BUS_VTABLE_UNPRIVILEGED),
811 SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart, SD_BUS_VTABLE_UNPRIVILEGED),
812 SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
813 SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, SD_BUS_VTABLE_UNPRIVILEGED),
814 SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, SD_BUS_VTABLE_UNPRIVILEGED),
815 SD_BUS_METHOD("Ref", NULL, NULL, bus_unit_method_ref, SD_BUS_VTABLE_UNPRIVILEGED),
816 SD_BUS_METHOD("Unref", NULL, NULL, bus_unit_method_unref, SD_BUS_VTABLE_UNPRIVILEGED),
817
818 /* Obsolete properties or obsolete alias names */
819 SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
820 SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
821 SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
822 SD_BUS_PROPERTY("RequisiteOfOverridable", "as", property_get_obsolete_dependencies, 0, SD_BUS_VTABLE_HIDDEN),
823 SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
824 SD_BUS_VTABLE_END
825 };
826
827 static int property_get_slice(
828 sd_bus *bus,
829 const char *path,
830 const char *interface,
831 const char *property,
832 sd_bus_message *reply,
833 void *userdata,
834 sd_bus_error *error) {
835
836 Unit *u = userdata;
837
838 assert(bus);
839 assert(reply);
840 assert(u);
841
842 return sd_bus_message_append(reply, "s", unit_slice_name(u));
843 }
844
845 static int property_get_current_memory(
846 sd_bus *bus,
847 const char *path,
848 const char *interface,
849 const char *property,
850 sd_bus_message *reply,
851 void *userdata,
852 sd_bus_error *error) {
853
854 uint64_t sz = (uint64_t) -1;
855 Unit *u = userdata;
856 int r;
857
858 assert(bus);
859 assert(reply);
860 assert(u);
861
862 r = unit_get_memory_current(u, &sz);
863 if (r < 0 && r != -ENODATA)
864 log_unit_warning_errno(u, r, "Failed to get memory.usage_in_bytes attribute: %m");
865
866 return sd_bus_message_append(reply, "t", sz);
867 }
868
869 static int property_get_current_tasks(
870 sd_bus *bus,
871 const char *path,
872 const char *interface,
873 const char *property,
874 sd_bus_message *reply,
875 void *userdata,
876 sd_bus_error *error) {
877
878 uint64_t cn = (uint64_t) -1;
879 Unit *u = userdata;
880 int r;
881
882 assert(bus);
883 assert(reply);
884 assert(u);
885
886 r = unit_get_tasks_current(u, &cn);
887 if (r < 0 && r != -ENODATA)
888 log_unit_warning_errno(u, r, "Failed to get pids.current attribute: %m");
889
890 return sd_bus_message_append(reply, "t", cn);
891 }
892
893 static int property_get_cpu_usage(
894 sd_bus *bus,
895 const char *path,
896 const char *interface,
897 const char *property,
898 sd_bus_message *reply,
899 void *userdata,
900 sd_bus_error *error) {
901
902 nsec_t ns = (nsec_t) -1;
903 Unit *u = userdata;
904 int r;
905
906 assert(bus);
907 assert(reply);
908 assert(u);
909
910 r = unit_get_cpu_usage(u, &ns);
911 if (r < 0 && r != -ENODATA)
912 log_unit_warning_errno(u, r, "Failed to get cpuacct.usage attribute: %m");
913
914 return sd_bus_message_append(reply, "t", ns);
915 }
916
917 static int property_get_cgroup(
918 sd_bus *bus,
919 const char *path,
920 const char *interface,
921 const char *property,
922 sd_bus_message *reply,
923 void *userdata,
924 sd_bus_error *error) {
925
926 Unit *u = userdata;
927 const char *t;
928
929 assert(bus);
930 assert(reply);
931 assert(u);
932
933 /* Three cases: a) u->cgroup_path is NULL, in which case the
934 * unit has no control group, which we report as the empty
935 * string. b) u->cgroup_path is the empty string, which
936 * indicates the root cgroup, which we report as "/". c) all
937 * other cases we report as-is. */
938
939 if (u->cgroup_path)
940 t = isempty(u->cgroup_path) ? "/" : u->cgroup_path;
941 else
942 t = "";
943
944 return sd_bus_message_append(reply, "s", t);
945 }
946
947 static int append_process(sd_bus_message *reply, const char *p, pid_t pid, Set *pids) {
948 _cleanup_free_ char *buf = NULL, *cmdline = NULL;
949 int r;
950
951 assert(reply);
952 assert(pid > 0);
953
954 r = set_put(pids, PID_TO_PTR(pid));
955 if (IN_SET(r, 0, -EEXIST))
956 return 0;
957 if (r < 0)
958 return r;
959
960 if (!p) {
961 r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &buf);
962 if (r == -ESRCH)
963 return 0;
964 if (r < 0)
965 return r;
966
967 p = buf;
968 }
969
970 (void) get_process_cmdline(pid, 0, true, &cmdline);
971
972 return sd_bus_message_append(reply,
973 "(sus)",
974 p,
975 (uint32_t) pid,
976 cmdline);
977 }
978
979 static int append_cgroup(sd_bus_message *reply, const char *p, Set *pids) {
980 _cleanup_closedir_ DIR *d = NULL;
981 _cleanup_fclose_ FILE *f = NULL;
982 int r;
983
984 assert(reply);
985 assert(p);
986
987 r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, p, &f);
988 if (r == ENOENT)
989 return 0;
990 if (r < 0)
991 return r;
992
993 for (;;) {
994 pid_t pid;
995
996 r = cg_read_pid(f, &pid);
997 if (r < 0)
998 return r;
999 if (r == 0)
1000 break;
1001
1002 if (is_kernel_thread(pid) > 0)
1003 continue;
1004
1005 r = append_process(reply, p, pid, pids);
1006 if (r < 0)
1007 return r;
1008 }
1009
1010 r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, p, &d);
1011 if (r == -ENOENT)
1012 return 0;
1013 if (r < 0)
1014 return r;
1015
1016 for (;;) {
1017 _cleanup_free_ char *g = NULL, *j = NULL;
1018
1019 r = cg_read_subgroup(d, &g);
1020 if (r < 0)
1021 return r;
1022 if (r == 0)
1023 break;
1024
1025 j = strjoin(p, "/", g);
1026 if (!j)
1027 return -ENOMEM;
1028
1029 r = append_cgroup(reply, j, pids);
1030 if (r < 0)
1031 return r;
1032 }
1033
1034 return 0;
1035 }
1036
1037 int bus_unit_method_get_processes(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1038 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1039 _cleanup_(set_freep) Set *pids = NULL;
1040 Unit *u = userdata;
1041 pid_t pid;
1042 int r;
1043
1044 assert(message);
1045
1046 r = mac_selinux_unit_access_check(u, message, "status", error);
1047 if (r < 0)
1048 return r;
1049
1050 pids = set_new(NULL);
1051 if (!pids)
1052 return -ENOMEM;
1053
1054 r = sd_bus_message_new_method_return(message, &reply);
1055 if (r < 0)
1056 return r;
1057
1058 r = sd_bus_message_open_container(reply, 'a', "(sus)");
1059 if (r < 0)
1060 return r;
1061
1062 if (u->cgroup_path) {
1063 r = append_cgroup(reply, u->cgroup_path, pids);
1064 if (r < 0)
1065 return r;
1066 }
1067
1068 /* The main and control pids might live outside of the cgroup, hence fetch them separately */
1069 pid = unit_main_pid(u);
1070 if (pid > 0) {
1071 r = append_process(reply, NULL, pid, pids);
1072 if (r < 0)
1073 return r;
1074 }
1075
1076 pid = unit_control_pid(u);
1077 if (pid > 0) {
1078 r = append_process(reply, NULL, pid, pids);
1079 if (r < 0)
1080 return r;
1081 }
1082
1083 r = sd_bus_message_close_container(reply);
1084 if (r < 0)
1085 return r;
1086
1087 return sd_bus_send(NULL, reply, NULL);
1088 }
1089
1090 static int property_get_ip_counter(
1091 sd_bus *bus,
1092 const char *path,
1093 const char *interface,
1094 const char *property,
1095 sd_bus_message *reply,
1096 void *userdata,
1097 sd_bus_error *error) {
1098
1099 CGroupIPAccountingMetric metric;
1100 uint64_t value = (uint64_t) -1;
1101 Unit *u = userdata;
1102
1103 assert(bus);
1104 assert(reply);
1105 assert(property);
1106 assert(u);
1107
1108 if (streq(property, "IPIngressBytes"))
1109 metric = CGROUP_IP_INGRESS_BYTES;
1110 else if (streq(property, "IPIngressPackets"))
1111 metric = CGROUP_IP_INGRESS_PACKETS;
1112 else if (streq(property, "IPEgressBytes"))
1113 metric = CGROUP_IP_EGRESS_BYTES;
1114 else {
1115 assert(streq(property, "IPEgressPackets"));
1116 metric = CGROUP_IP_EGRESS_PACKETS;
1117 }
1118
1119 (void) unit_get_ip_accounting(u, metric, &value);
1120 return sd_bus_message_append(reply, "t", value);
1121 }
1122
1123 const sd_bus_vtable bus_unit_cgroup_vtable[] = {
1124 SD_BUS_VTABLE_START(0),
1125 SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0),
1126 SD_BUS_PROPERTY("ControlGroup", "s", property_get_cgroup, 0, 0),
1127 SD_BUS_PROPERTY("MemoryCurrent", "t", property_get_current_memory, 0, 0),
1128 SD_BUS_PROPERTY("CPUUsageNSec", "t", property_get_cpu_usage, 0, 0),
1129 SD_BUS_PROPERTY("TasksCurrent", "t", property_get_current_tasks, 0, 0),
1130 SD_BUS_PROPERTY("IPIngressBytes", "t", property_get_ip_counter, 0, 0),
1131 SD_BUS_PROPERTY("IPIngressPackets", "t", property_get_ip_counter, 0, 0),
1132 SD_BUS_PROPERTY("IPEgressBytes", "t", property_get_ip_counter, 0, 0),
1133 SD_BUS_PROPERTY("IPEgressPackets", "t", property_get_ip_counter, 0, 0),
1134 SD_BUS_METHOD("GetProcesses", NULL, "a(sus)", bus_unit_method_get_processes, SD_BUS_VTABLE_UNPRIVILEGED),
1135 SD_BUS_VTABLE_END
1136 };
1137
1138 static int send_new_signal(sd_bus *bus, void *userdata) {
1139 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1140 _cleanup_free_ char *p = NULL;
1141 Unit *u = userdata;
1142 int r;
1143
1144 assert(bus);
1145 assert(u);
1146
1147 p = unit_dbus_path(u);
1148 if (!p)
1149 return -ENOMEM;
1150
1151 r = sd_bus_message_new_signal(
1152 bus,
1153 &m,
1154 "/org/freedesktop/systemd1",
1155 "org.freedesktop.systemd1.Manager",
1156 "UnitNew");
1157 if (r < 0)
1158 return r;
1159
1160 r = sd_bus_message_append(m, "so", u->id, p);
1161 if (r < 0)
1162 return r;
1163
1164 return sd_bus_send(bus, m, NULL);
1165 }
1166
1167 static int send_changed_signal(sd_bus *bus, void *userdata) {
1168 _cleanup_free_ char *p = NULL;
1169 Unit *u = userdata;
1170 int r;
1171
1172 assert(bus);
1173 assert(u);
1174
1175 p = unit_dbus_path(u);
1176 if (!p)
1177 return -ENOMEM;
1178
1179 /* Send a properties changed signal. First for the specific
1180 * type, then for the generic unit. The clients may rely on
1181 * this order to get atomic behavior if needed. */
1182
1183 r = sd_bus_emit_properties_changed_strv(
1184 bus, p,
1185 unit_dbus_interface_from_type(u->type),
1186 NULL);
1187 if (r < 0)
1188 return r;
1189
1190 return sd_bus_emit_properties_changed_strv(
1191 bus, p,
1192 "org.freedesktop.systemd1.Unit",
1193 NULL);
1194 }
1195
1196 void bus_unit_send_change_signal(Unit *u) {
1197 int r;
1198 assert(u);
1199
1200 if (u->in_dbus_queue) {
1201 LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
1202 u->in_dbus_queue = false;
1203 }
1204
1205 if (!u->id)
1206 return;
1207
1208 r = bus_foreach_bus(u->manager, u->bus_track, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
1209 if (r < 0)
1210 log_unit_debug_errno(u, r, "Failed to send unit change signal for %s: %m", u->id);
1211
1212 u->sent_dbus_new_signal = true;
1213 }
1214
1215 static int send_removed_signal(sd_bus *bus, void *userdata) {
1216 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1217 _cleanup_free_ char *p = NULL;
1218 Unit *u = userdata;
1219 int r;
1220
1221 assert(bus);
1222 assert(u);
1223
1224 p = unit_dbus_path(u);
1225 if (!p)
1226 return -ENOMEM;
1227
1228 r = sd_bus_message_new_signal(
1229 bus,
1230 &m,
1231 "/org/freedesktop/systemd1",
1232 "org.freedesktop.systemd1.Manager",
1233 "UnitRemoved");
1234 if (r < 0)
1235 return r;
1236
1237 r = sd_bus_message_append(m, "so", u->id, p);
1238 if (r < 0)
1239 return r;
1240
1241 return sd_bus_send(bus, m, NULL);
1242 }
1243
1244 void bus_unit_send_removed_signal(Unit *u) {
1245 int r;
1246 assert(u);
1247
1248 if (!u->sent_dbus_new_signal || u->in_dbus_queue)
1249 bus_unit_send_change_signal(u);
1250
1251 if (!u->id)
1252 return;
1253
1254 r = bus_foreach_bus(u->manager, u->bus_track, send_removed_signal, u);
1255 if (r < 0)
1256 log_unit_debug_errno(u, r, "Failed to send unit remove signal for %s: %m", u->id);
1257 }
1258
1259 int bus_unit_queue_job(
1260 sd_bus_message *message,
1261 Unit *u,
1262 JobType type,
1263 JobMode mode,
1264 bool reload_if_possible,
1265 sd_bus_error *error) {
1266
1267 _cleanup_free_ char *path = NULL;
1268 Job *j;
1269 int r;
1270
1271 assert(message);
1272 assert(u);
1273 assert(type >= 0 && type < _JOB_TYPE_MAX);
1274 assert(mode >= 0 && mode < _JOB_MODE_MAX);
1275
1276 r = mac_selinux_unit_access_check(
1277 u, message,
1278 job_type_to_access_method(type),
1279 error);
1280 if (r < 0)
1281 return r;
1282
1283 if (reload_if_possible && unit_can_reload(u)) {
1284 if (type == JOB_RESTART)
1285 type = JOB_RELOAD_OR_START;
1286 else if (type == JOB_TRY_RESTART)
1287 type = JOB_TRY_RELOAD;
1288 }
1289
1290 if (type == JOB_STOP &&
1291 (IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR)) &&
1292 unit_active_state(u) == UNIT_INACTIVE)
1293 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
1294
1295 if ((type == JOB_START && u->refuse_manual_start) ||
1296 (type == JOB_STOP && u->refuse_manual_stop) ||
1297 (IN_SET(type, JOB_RESTART, JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) ||
1298 (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start))
1299 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);
1300
1301 r = manager_add_job(u->manager, type, u, mode, error, &j);
1302 if (r < 0)
1303 return r;
1304
1305 r = bus_job_track_sender(j, message);
1306 if (r < 0)
1307 return r;
1308
1309 path = job_dbus_path(j);
1310 if (!path)
1311 return -ENOMEM;
1312
1313 return sd_bus_reply_method_return(message, "o", path);
1314 }
1315
1316 static int bus_unit_set_transient_property(
1317 Unit *u,
1318 const char *name,
1319 sd_bus_message *message,
1320 UnitSetPropertiesMode mode,
1321 sd_bus_error *error) {
1322
1323 int r;
1324
1325 assert(u);
1326 assert(name);
1327 assert(message);
1328
1329 if (streq(name, "Description")) {
1330 const char *d;
1331
1332 r = sd_bus_message_read(message, "s", &d);
1333 if (r < 0)
1334 return r;
1335
1336 if (mode != UNIT_CHECK) {
1337 r = unit_set_description(u, d);
1338 if (r < 0)
1339 return r;
1340
1341 unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s", d);
1342 }
1343
1344 return 1;
1345
1346 } else if (streq(name, "DefaultDependencies")) {
1347 int b;
1348
1349 r = sd_bus_message_read(message, "b", &b);
1350 if (r < 0)
1351 return r;
1352
1353 if (mode != UNIT_CHECK) {
1354 u->default_dependencies = b;
1355 unit_write_drop_in_format(u, mode, name, "[Unit]\nDefaultDependencies=%s", yes_no(b));
1356 }
1357
1358 return 1;
1359
1360 } else if (streq(name, "CollectMode")) {
1361 const char *s;
1362 CollectMode m;
1363
1364 r = sd_bus_message_read(message, "s", &s);
1365 if (r < 0)
1366 return r;
1367
1368 m = collect_mode_from_string(s);
1369 if (m < 0)
1370 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown garbage collection mode: %s", s);
1371
1372 if (mode != UNIT_CHECK) {
1373 u->collect_mode = m;
1374 unit_write_drop_in_format(u, mode, name, "[Unit]\nCollectMode=%s", collect_mode_to_string(m));
1375 }
1376
1377 return 1;
1378
1379 } else if (streq(name, "Slice")) {
1380 Unit *slice;
1381 const char *s;
1382
1383 if (!UNIT_HAS_CGROUP_CONTEXT(u))
1384 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "The slice property is only available for units with control groups.");
1385 if (u->type == UNIT_SLICE)
1386 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Slice may not be set for slice units.");
1387 if (unit_has_name(u, SPECIAL_INIT_SCOPE))
1388 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set slice for init.scope");
1389
1390 r = sd_bus_message_read(message, "s", &s);
1391 if (r < 0)
1392 return r;
1393
1394 if (!unit_name_is_valid(s, UNIT_NAME_PLAIN))
1395 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name '%s'", s);
1396
1397 /* Note that we do not dispatch the load queue here yet, as we don't want our own transient unit to be
1398 * loaded while we are still setting it up. Or in other words, we use manager_load_unit_prepare()
1399 * instead of manager_load_unit() on purpose, here. */
1400 r = manager_load_unit_prepare(u->manager, s, NULL, error, &slice);
1401 if (r < 0)
1402 return r;
1403
1404 if (slice->type != UNIT_SLICE)
1405 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit name '%s' is not a slice", s);
1406
1407 if (mode != UNIT_CHECK) {
1408 r = unit_set_slice(u, slice);
1409 if (r < 0)
1410 return r;
1411
1412 unit_write_drop_in_private_format(u, mode, name, "Slice=%s", s);
1413 }
1414
1415 return 1;
1416
1417 } else if (STR_IN_SET(name,
1418 "Requires", "RequiresOverridable",
1419 "Requisite", "RequisiteOverridable",
1420 "Wants",
1421 "BindsTo",
1422 "Conflicts",
1423 "Before", "After",
1424 "OnFailure",
1425 "PropagatesReloadTo", "ReloadPropagatedFrom",
1426 "PartOf")) {
1427
1428 UnitDependency d;
1429 const char *other;
1430
1431 if (streq(name, "RequiresOverridable"))
1432 d = UNIT_REQUIRES; /* redirect for obsolete unit dependency type */
1433 else if (streq(name, "RequisiteOverridable"))
1434 d = UNIT_REQUISITE; /* same here */
1435 else {
1436 d = unit_dependency_from_string(name);
1437 if (d < 0)
1438 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit dependency: %s", name);
1439 }
1440
1441 r = sd_bus_message_enter_container(message, 'a', "s");
1442 if (r < 0)
1443 return r;
1444
1445 while ((r = sd_bus_message_read(message, "s", &other)) > 0) {
1446 if (!unit_name_is_valid(other, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
1447 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
1448
1449 if (mode != UNIT_CHECK) {
1450 _cleanup_free_ char *label = NULL;
1451
1452 r = unit_add_dependency_by_name(u, d, other, NULL, true, UNIT_DEPENDENCY_FILE);
1453 if (r < 0)
1454 return r;
1455
1456 label = strjoin(name, "-", other);
1457 if (!label)
1458 return -ENOMEM;
1459
1460 unit_write_drop_in_format(u, mode, label, "[Unit]\n%s=%s", name, other);
1461 }
1462
1463 }
1464 if (r < 0)
1465 return r;
1466
1467 r = sd_bus_message_exit_container(message);
1468 if (r < 0)
1469 return r;
1470
1471 return 1;
1472
1473 } else if (streq(name, "AddRef")) {
1474
1475 int b;
1476
1477 /* Why is this called "AddRef" rather than just "Ref", or "Reference"? There's already a "Ref()" method
1478 * on the Unit interface, and it's probably not a good idea to expose a property and a method on the
1479 * same interface (well, strictly speaking AddRef isn't exposed as full property, we just read it for
1480 * transient units, but still). And "References" and "ReferencedBy" is already used as unit reference
1481 * dependency type, hence let's not confuse things with that.
1482 *
1483 * Note that we don't acually add the reference to the bus track. We do that only after the setup of
1484 * the transient unit is complete, so that setting this property multiple times in the same transient
1485 * unit creation call doesn't count as individual references. */
1486
1487 r = sd_bus_message_read(message, "b", &b);
1488 if (r < 0)
1489 return r;
1490
1491 if (mode != UNIT_CHECK)
1492 u->bus_track_add = b;
1493
1494 return 1;
1495 }
1496
1497 return 0;
1498 }
1499
1500 int bus_unit_set_properties(
1501 Unit *u,
1502 sd_bus_message *message,
1503 UnitSetPropertiesMode mode,
1504 bool commit,
1505 sd_bus_error *error) {
1506
1507 bool for_real = false;
1508 unsigned n = 0;
1509 int r;
1510
1511 assert(u);
1512 assert(message);
1513
1514 /* We iterate through the array twice. First run we just check
1515 * if all passed data is valid, second run actually applies
1516 * it. This is to implement transaction-like behaviour without
1517 * actually providing full transactions. */
1518
1519 r = sd_bus_message_enter_container(message, 'a', "(sv)");
1520 if (r < 0)
1521 return r;
1522
1523 for (;;) {
1524 const char *name;
1525
1526 r = sd_bus_message_enter_container(message, 'r', "sv");
1527 if (r < 0)
1528 return r;
1529 if (r == 0) {
1530 if (for_real || mode == UNIT_CHECK)
1531 break;
1532
1533 /* Reached EOF. Let's try again, and this time for realz... */
1534 r = sd_bus_message_rewind(message, false);
1535 if (r < 0)
1536 return r;
1537
1538 for_real = true;
1539 continue;
1540 }
1541
1542 r = sd_bus_message_read(message, "s", &name);
1543 if (r < 0)
1544 return r;
1545
1546 if (!UNIT_VTABLE(u)->bus_set_property)
1547 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
1548
1549 r = sd_bus_message_enter_container(message, 'v', NULL);
1550 if (r < 0)
1551 return r;
1552
1553 r = UNIT_VTABLE(u)->bus_set_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
1554 if (r == 0 && u->transient && u->load_state == UNIT_STUB)
1555 r = bus_unit_set_transient_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
1556 if (r < 0)
1557 return r;
1558 if (r == 0)
1559 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
1560
1561 r = sd_bus_message_exit_container(message);
1562 if (r < 0)
1563 return r;
1564
1565 r = sd_bus_message_exit_container(message);
1566 if (r < 0)
1567 return r;
1568
1569 n += for_real;
1570 }
1571
1572 r = sd_bus_message_exit_container(message);
1573 if (r < 0)
1574 return r;
1575
1576 if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties)
1577 UNIT_VTABLE(u)->bus_commit_properties(u);
1578
1579 return n;
1580 }
1581
1582 int bus_unit_check_load_state(Unit *u, sd_bus_error *error) {
1583 assert(u);
1584
1585 if (u->load_state == UNIT_LOADED)
1586 return 0;
1587
1588 /* Give a better description of the unit error when
1589 * possible. Note that in the case of UNIT_MASKED, load_error
1590 * is not set. */
1591 if (u->load_state == UNIT_MASKED)
1592 return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit %s is masked.", u->id);
1593
1594 if (u->load_state == UNIT_NOT_FOUND)
1595 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not found.", u->id);
1596
1597 return sd_bus_error_set_errnof(error, u->load_error, "Unit %s is not loaded properly: %m.", u->id);
1598 }
1599
1600 static int bus_unit_track_handler(sd_bus_track *t, void *userdata) {
1601 Unit *u = userdata;
1602
1603 assert(t);
1604 assert(u);
1605
1606 u->bus_track = sd_bus_track_unref(u->bus_track); /* make sure we aren't called again */
1607
1608 unit_add_to_gc_queue(u);
1609 return 0;
1610 }
1611
1612 static int bus_unit_allocate_bus_track(Unit *u) {
1613 int r;
1614
1615 assert(u);
1616
1617 if (u->bus_track)
1618 return 0;
1619
1620 r = sd_bus_track_new(u->manager->api_bus, &u->bus_track, bus_unit_track_handler, u);
1621 if (r < 0)
1622 return r;
1623
1624 r = sd_bus_track_set_recursive(u->bus_track, true);
1625 if (r < 0) {
1626 u->bus_track = sd_bus_track_unref(u->bus_track);
1627 return r;
1628 }
1629
1630 return 0;
1631 }
1632
1633 int bus_unit_track_add_name(Unit *u, const char *name) {
1634 int r;
1635
1636 assert(u);
1637
1638 r = bus_unit_allocate_bus_track(u);
1639 if (r < 0)
1640 return r;
1641
1642 return sd_bus_track_add_name(u->bus_track, name);
1643 }
1644
1645 int bus_unit_track_add_sender(Unit *u, sd_bus_message *m) {
1646 int r;
1647
1648 assert(u);
1649
1650 r = bus_unit_allocate_bus_track(u);
1651 if (r < 0)
1652 return r;
1653
1654 return sd_bus_track_add_sender(u->bus_track, m);
1655 }
1656
1657 int bus_unit_track_remove_sender(Unit *u, sd_bus_message *m) {
1658 assert(u);
1659
1660 /* If we haven't allocated the bus track object yet, then there's definitely no reference taken yet, return an
1661 * error */
1662 if (!u->bus_track)
1663 return -EUNATCH;
1664
1665 return sd_bus_track_remove_sender(u->bus_track, m);
1666 }