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