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