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