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