chiark / gitweb /
conf-parse: don't accept invalid bus names as BusName= arguments in service units
[elogind.git] / src / core / dbus-unit.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "sd-bus.h"
23 #include "log.h"
24 #include "selinux-access.h"
25 #include "cgroup-util.h"
26 #include "strv.h"
27 #include "path-util.h"
28 #include "fileio.h"
29 #include "bus-common-errors.h"
30 #include "dbus.h"
31 #include "dbus-manager.h"
32 #include "dbus-unit.h"
33
34 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
35 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode);
36 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_failure_action, failure_action, FailureAction);
37
38 static int property_get_names(
39                 sd_bus *bus,
40                 const char *path,
41                 const char *interface,
42                 const char *property,
43                 sd_bus_message *reply,
44                 void *userdata,
45                 sd_bus_error *error) {
46
47         Unit *u = userdata;
48         Iterator i;
49         const char *t;
50         int r;
51
52         assert(bus);
53         assert(reply);
54         assert(u);
55
56         r = sd_bus_message_open_container(reply, 'a', "s");
57         if (r < 0)
58                 return r;
59
60         SET_FOREACH(t, u->names, i) {
61                 r = sd_bus_message_append(reply, "s", t);
62                 if (r < 0)
63                         return r;
64         }
65
66         return sd_bus_message_close_container(reply);
67 }
68
69 static int property_get_following(
70                 sd_bus *bus,
71                 const char *path,
72                 const char *interface,
73                 const char *property,
74                 sd_bus_message *reply,
75                 void *userdata,
76                 sd_bus_error *error) {
77
78         Unit *u = userdata, *f;
79
80         assert(bus);
81         assert(reply);
82         assert(u);
83
84         f = unit_following(u);
85         return sd_bus_message_append(reply, "s", f ? f->id : "");
86 }
87
88 static int property_get_dependencies(
89                 sd_bus *bus,
90                 const char *path,
91                 const char *interface,
92                 const char *property,
93                 sd_bus_message *reply,
94                 void *userdata,
95                 sd_bus_error *error) {
96
97         Set *s = *(Set**) userdata;
98         Iterator j;
99         Unit *u;
100         int r;
101
102         assert(bus);
103         assert(reply);
104
105         r = sd_bus_message_open_container(reply, 'a', "s");
106         if (r < 0)
107                 return r;
108
109         SET_FOREACH(u, s, j) {
110                 r = sd_bus_message_append(reply, "s", u->id);
111                 if (r < 0)
112                         return r;
113         }
114
115         return sd_bus_message_close_container(reply);
116 }
117
118 static int property_get_description(
119                 sd_bus *bus,
120                 const char *path,
121                 const char *interface,
122                 const char *property,
123                 sd_bus_message *reply,
124                 void *userdata,
125                 sd_bus_error *error) {
126
127         Unit *u = userdata;
128
129         assert(bus);
130         assert(reply);
131         assert(u);
132
133         return sd_bus_message_append(reply, "s", unit_description(u));
134 }
135
136 static int property_get_active_state(
137                 sd_bus *bus,
138                 const char *path,
139                 const char *interface,
140                 const char *property,
141                 sd_bus_message *reply,
142                 void *userdata,
143                 sd_bus_error *error) {
144
145         Unit *u = userdata;
146
147         assert(bus);
148         assert(reply);
149         assert(u);
150
151         return sd_bus_message_append(reply, "s", unit_active_state_to_string(unit_active_state(u)));
152 }
153
154 static int property_get_sub_state(
155                 sd_bus *bus,
156                 const char *path,
157                 const char *interface,
158                 const char *property,
159                 sd_bus_message *reply,
160                 void *userdata,
161                 sd_bus_error *error) {
162
163         Unit *u = userdata;
164
165         assert(bus);
166         assert(reply);
167         assert(u);
168
169         return sd_bus_message_append(reply, "s", unit_sub_state_to_string(u));
170 }
171
172 static int property_get_unit_file_preset(
173                 sd_bus *bus,
174                 const char *path,
175                 const char *interface,
176                 const char *property,
177                 sd_bus_message *reply,
178                 void *userdata,
179                 sd_bus_error *error) {
180
181         Unit *u = userdata;
182         int r;
183
184         assert(bus);
185         assert(reply);
186         assert(u);
187
188         r = unit_get_unit_file_preset(u);
189
190         return sd_bus_message_append(reply, "s",
191                                      r < 0 ? "":
192                                      r > 0 ? "enabled" : "disabled");
193 }
194
195 static int property_get_unit_file_state(
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
206         assert(bus);
207         assert(reply);
208         assert(u);
209
210         return sd_bus_message_append(reply, "s", unit_file_state_to_string(unit_get_unit_file_state(u)));
211 }
212
213 static int property_get_can_start(
214                 sd_bus *bus,
215                 const char *path,
216                 const char *interface,
217                 const char *property,
218                 sd_bus_message *reply,
219                 void *userdata,
220                 sd_bus_error *error) {
221
222         Unit *u = userdata;
223
224         assert(bus);
225         assert(reply);
226         assert(u);
227
228         return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_start);
229 }
230
231 static int property_get_can_stop(
232                 sd_bus *bus,
233                 const char *path,
234                 const char *interface,
235                 const char *property,
236                 sd_bus_message *reply,
237                 void *userdata,
238                 sd_bus_error *error) {
239
240         Unit *u = userdata;
241
242         assert(bus);
243         assert(reply);
244         assert(u);
245
246         /* On the lower levels we assume that every unit we can start
247          * we can also stop */
248
249         return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_stop);
250 }
251
252 static int property_get_can_reload(
253                 sd_bus *bus,
254                 const char *path,
255                 const char *interface,
256                 const char *property,
257                 sd_bus_message *reply,
258                 void *userdata,
259                 sd_bus_error *error) {
260
261         Unit *u = userdata;
262
263         assert(bus);
264         assert(reply);
265         assert(u);
266
267         return sd_bus_message_append(reply, "b", unit_can_reload(u));
268 }
269
270 static int property_get_can_isolate(
271                 sd_bus *bus,
272                 const char *path,
273                 const char *interface,
274                 const char *property,
275                 sd_bus_message *reply,
276                 void *userdata,
277                 sd_bus_error *error) {
278
279         Unit *u = userdata;
280
281         assert(bus);
282         assert(reply);
283         assert(u);
284
285         return sd_bus_message_append(reply, "b", unit_can_isolate(u) && !u->refuse_manual_start);
286 }
287
288 static int property_get_job(
289                 sd_bus *bus,
290                 const char *path,
291                 const char *interface,
292                 const char *property,
293                 sd_bus_message *reply,
294                 void *userdata,
295                 sd_bus_error *error) {
296
297         _cleanup_free_ char *p = NULL;
298         Unit *u = userdata;
299
300         assert(bus);
301         assert(reply);
302         assert(u);
303
304         if (!u->job)
305                 return sd_bus_message_append(reply, "(uo)", 0, "/");
306
307         p = job_dbus_path(u->job);
308         if (!p)
309                 return -ENOMEM;
310
311         return sd_bus_message_append(reply, "(uo)", u->job->id, p);
312 }
313
314 static int property_get_need_daemon_reload(
315                 sd_bus *bus,
316                 const char *path,
317                 const char *interface,
318                 const char *property,
319                 sd_bus_message *reply,
320                 void *userdata,
321                 sd_bus_error *error) {
322
323         Unit *u = userdata;
324
325         assert(bus);
326         assert(reply);
327         assert(u);
328
329         return sd_bus_message_append(reply, "b", unit_need_daemon_reload(u));
330 }
331
332 static int property_get_conditions(
333                 sd_bus *bus,
334                 const char *path,
335                 const char *interface,
336                 const char *property,
337                 sd_bus_message *reply,
338                 void *userdata,
339                 sd_bus_error *error) {
340
341         const char *(*to_string)(ConditionType type) = NULL;
342         Condition **list = userdata, *c;
343         int r;
344
345         assert(bus);
346         assert(reply);
347         assert(list);
348
349         to_string = streq(property, "Asserts") ? assert_type_to_string : condition_type_to_string;
350
351         r = sd_bus_message_open_container(reply, 'a', "(sbbsi)");
352         if (r < 0)
353                 return r;
354
355         LIST_FOREACH(conditions, c, *list) {
356                 int tristate;
357
358                 tristate =
359                         c->result == CONDITION_UNTESTED ? 0 :
360                         c->result == CONDITION_SUCCEEDED ? 1 : -1;
361
362                 r = sd_bus_message_append(reply, "(sbbsi)",
363                                           to_string(c->type),
364                                           c->trigger, c->negate,
365                                           c->parameter, tristate);
366                 if (r < 0)
367                         return r;
368
369         }
370
371         return sd_bus_message_close_container(reply);
372 }
373
374 static int property_get_load_error(
375                 sd_bus *bus,
376                 const char *path,
377                 const char *interface,
378                 const char *property,
379                 sd_bus_message *reply,
380                 void *userdata,
381                 sd_bus_error *error) {
382
383         _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
384         Unit *u = userdata;
385
386         assert(bus);
387         assert(reply);
388         assert(u);
389
390         if (u->load_error != 0)
391                 sd_bus_error_set_errno(&e, u->load_error);
392
393         return sd_bus_message_append(reply, "(ss)", e.name, e.message);
394 }
395
396 int bus_unit_method_start_generic(sd_bus *bus, sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible, sd_bus_error *error) {
397         const char *smode;
398         JobMode mode;
399         int r;
400
401         assert(bus);
402         assert(message);
403         assert(u);
404         assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
405
406         r = sd_bus_message_read(message, "s", &smode);
407         if (r < 0)
408                 return r;
409
410         mode = job_mode_from_string(smode);
411         if (mode < 0)
412                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
413
414         return bus_unit_queue_job(bus, message, u, job_type, mode, reload_if_possible, error);
415 }
416
417 static int method_start(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
418         return bus_unit_method_start_generic(bus, message, userdata, JOB_START, false, error);
419 }
420
421 static int method_stop(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
422         return bus_unit_method_start_generic(bus, message, userdata, JOB_STOP, false, error);
423 }
424
425 static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
426         return bus_unit_method_start_generic(bus, message, userdata, JOB_RELOAD, false, error);
427 }
428
429 static int method_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
430         return bus_unit_method_start_generic(bus, message, userdata, JOB_RESTART, false, error);
431 }
432
433 static int method_try_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
434         return bus_unit_method_start_generic(bus, message, userdata, JOB_TRY_RESTART, false, error);
435 }
436
437 static int method_reload_or_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
438         return bus_unit_method_start_generic(bus, message, userdata, JOB_RESTART, true, error);
439 }
440
441 static int method_reload_or_try_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
442         return bus_unit_method_start_generic(bus, message, userdata, JOB_TRY_RESTART, true, error);
443 }
444
445 int bus_unit_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
446         Unit *u = userdata;
447         const char *swho;
448         int32_t signo;
449         KillWho who;
450         int r;
451
452         assert(bus);
453         assert(message);
454         assert(u);
455
456         r = bus_verify_manage_unit_async_for_kill(u->manager, message, error);
457         if (r < 0)
458                 return r;
459         if (r == 0)
460                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
461
462         r = sd_bus_message_read(message, "si", &swho, &signo);
463         if (r < 0)
464                 return r;
465
466         if (isempty(swho))
467                 who = KILL_ALL;
468         else {
469                 who = kill_who_from_string(swho);
470                 if (who < 0)
471                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho);
472         }
473
474         if (signo <= 0 || signo >= _NSIG)
475                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
476
477         r = mac_selinux_unit_access_check(u, message, "stop", error);
478         if (r < 0)
479                 return r;
480
481         r = unit_kill(u, who, signo, error);
482         if (r < 0)
483                 return r;
484
485         return sd_bus_reply_method_return(message, NULL);
486 }
487
488 int bus_unit_method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
489         Unit *u = userdata;
490         int r;
491
492         assert(bus);
493         assert(message);
494         assert(u);
495
496         r = bus_verify_manage_unit_async(u->manager, message, error);
497         if (r < 0)
498                 return r;
499         if (r == 0)
500                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
501
502         r = mac_selinux_unit_access_check(u, message, "reload", error);
503         if (r < 0)
504                 return r;
505
506         unit_reset_failed(u);
507
508         return sd_bus_reply_method_return(message, NULL);
509 }
510
511 int bus_unit_method_set_properties(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
512         Unit *u = userdata;
513         int runtime, r;
514
515         assert(bus);
516         assert(message);
517         assert(u);
518
519         r = bus_verify_manage_unit_async(u->manager, message, error);
520         if (r < 0)
521                 return r;
522         if (r == 0)
523                 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
524
525         r = sd_bus_message_read(message, "b", &runtime);
526         if (r < 0)
527                 return r;
528
529         r = mac_selinux_unit_access_check(u, message, "start", error);
530         if (r < 0)
531                 return r;
532
533         r = bus_unit_set_properties(u, message, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, error);
534         if (r < 0)
535                 return r;
536
537         return sd_bus_reply_method_return(message, NULL);
538 }
539
540 const sd_bus_vtable bus_unit_vtable[] = {
541         SD_BUS_VTABLE_START(0),
542
543         SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), SD_BUS_VTABLE_PROPERTY_CONST),
544         SD_BUS_PROPERTY("Names", "as", property_get_names, 0, SD_BUS_VTABLE_PROPERTY_CONST),
545         SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
546         SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST),
547         SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST),
548         SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), SD_BUS_VTABLE_PROPERTY_CONST),
549         SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST),
550         SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTS]), SD_BUS_VTABLE_PROPERTY_CONST),
551         SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BINDS_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
552         SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
553         SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
554         SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST),
555         SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
556         SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
557         SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
558         SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTS]), SD_BUS_VTABLE_PROPERTY_CONST),
559         SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
560         SD_BUS_PROPERTY("Before", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BEFORE]), SD_BUS_VTABLE_PROPERTY_CONST),
561         SD_BUS_PROPERTY("After", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_AFTER]), SD_BUS_VTABLE_PROPERTY_CONST),
562         SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_ON_FAILURE]), SD_BUS_VTABLE_PROPERTY_CONST),
563         SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERS]), SD_BUS_VTABLE_PROPERTY_CONST),
564         SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
565         SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
566         SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), SD_BUS_VTABLE_PROPERTY_CONST),
567         SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_JOINS_NAMESPACE_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
568         SD_BUS_PROPERTY("RequiresMountsFor", "as", NULL, offsetof(Unit, requires_mounts_for), SD_BUS_VTABLE_PROPERTY_CONST),
569         SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), SD_BUS_VTABLE_PROPERTY_CONST),
570         SD_BUS_PROPERTY("Description", "s", property_get_description, 0, SD_BUS_VTABLE_PROPERTY_CONST),
571         SD_BUS_PROPERTY("LoadState", "s", property_get_load_state, offsetof(Unit, load_state), SD_BUS_VTABLE_PROPERTY_CONST),
572         SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
573         SD_BUS_PROPERTY("SubState", "s", property_get_sub_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
574         SD_BUS_PROPERTY("FragmentPath", "s", NULL, offsetof(Unit, fragment_path), SD_BUS_VTABLE_PROPERTY_CONST),
575         SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Unit, source_path), SD_BUS_VTABLE_PROPERTY_CONST),
576         SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), SD_BUS_VTABLE_PROPERTY_CONST),
577         SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0),
578         SD_BUS_PROPERTY("UnitFilePreset", "s", property_get_unit_file_preset, 0, 0),
579         BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
580         BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
581         BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
582         BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit, inactive_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
583         SD_BUS_PROPERTY("CanStart", "b", property_get_can_start, 0, SD_BUS_VTABLE_PROPERTY_CONST),
584         SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, SD_BUS_VTABLE_PROPERTY_CONST),
585         SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
586         SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, SD_BUS_VTABLE_PROPERTY_CONST),
587         SD_BUS_PROPERTY("Job", "(uo)", property_get_job, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
588         SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), SD_BUS_VTABLE_PROPERTY_CONST),
589         SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), SD_BUS_VTABLE_PROPERTY_CONST),
590         SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST),
591         SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
592         SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), SD_BUS_VTABLE_PROPERTY_CONST),
593         SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
594         SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
595         SD_BUS_PROPERTY("IgnoreOnSnapshot", "b", bus_property_get_bool, offsetof(Unit, ignore_on_snapshot), SD_BUS_VTABLE_PROPERTY_CONST),
596         SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
597         SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
598         SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_failure_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
599         SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
600         SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
601         SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
602         BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
603         BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit, assert_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
604         SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), 0),
605         SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
606         SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
607         SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
608
609         SD_BUS_METHOD("Start", "s", "o", method_start, 0),
610         SD_BUS_METHOD("Stop", "s", "o", method_stop, 0),
611         SD_BUS_METHOD("Reload", "s", "o", method_reload, 0),
612         SD_BUS_METHOD("Restart", "s", "o", method_restart, 0),
613         SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart, 0),
614         SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart, 0),
615         SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart, 0),
616         SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, 0),
617         SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, 0),
618         SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, 0),
619
620         SD_BUS_VTABLE_END
621 };
622
623 static int property_get_slice(
624                 sd_bus *bus,
625                 const char *path,
626                 const char *interface,
627                 const char *property,
628                 sd_bus_message *reply,
629                 void *userdata,
630                 sd_bus_error *error) {
631
632         Unit *u = userdata;
633
634         assert(bus);
635         assert(reply);
636         assert(u);
637
638         return sd_bus_message_append(reply, "s", unit_slice_name(u));
639 }
640
641 const sd_bus_vtable bus_unit_cgroup_vtable[] = {
642         SD_BUS_VTABLE_START(0),
643         SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0),
644         SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Unit, cgroup_path), 0),
645         SD_BUS_VTABLE_END
646 };
647
648 static int send_new_signal(sd_bus *bus, void *userdata) {
649         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
650         _cleanup_free_ char *p = NULL;
651         Unit *u = userdata;
652         int r;
653
654         assert(bus);
655         assert(u);
656
657         p = unit_dbus_path(u);
658         if (!u)
659                 return -ENOMEM;
660
661         r = sd_bus_message_new_signal(
662                         bus,
663                         &m,
664                         "/org/freedesktop/systemd1",
665                         "org.freedesktop.systemd1.Manager",
666                         "UnitNew");
667         if (r < 0)
668                 return r;
669
670         r = sd_bus_message_append(m, "so", u->id, p);
671         if (r < 0)
672                 return r;
673
674         return sd_bus_send(bus, m, NULL);
675 }
676
677 static int send_changed_signal(sd_bus *bus, void *userdata) {
678         _cleanup_free_ char *p = NULL;
679         Unit *u = userdata;
680         int r;
681
682         assert(bus);
683         assert(u);
684
685         p = unit_dbus_path(u);
686         if (!p)
687                 return -ENOMEM;
688
689         /* Send a properties changed signal. First for the specific
690          * type, then for the generic unit. The clients may rely on
691          * this order to get atomic behavior if needed. */
692
693         r = sd_bus_emit_properties_changed_strv(
694                         bus, p,
695                         UNIT_VTABLE(u)->bus_interface,
696                         NULL);
697         if (r < 0)
698                 return r;
699
700         return sd_bus_emit_properties_changed_strv(
701                         bus, p,
702                         "org.freedesktop.systemd1.Unit",
703                         NULL);
704 }
705
706 void bus_unit_send_change_signal(Unit *u) {
707         int r;
708         assert(u);
709
710         if (u->in_dbus_queue) {
711                 LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
712                 u->in_dbus_queue = false;
713         }
714
715         if (!u->id)
716                 return;
717
718         r = bus_foreach_bus(u->manager, NULL, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
719         if (r < 0)
720                 log_debug_errno(r, "Failed to send unit change signal for %s: %m", u->id);
721
722         u->sent_dbus_new_signal = true;
723 }
724
725 static int send_removed_signal(sd_bus *bus, void *userdata) {
726         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
727         _cleanup_free_ char *p = NULL;
728         Unit *u = userdata;
729         int r;
730
731         assert(bus);
732         assert(u);
733
734         p = unit_dbus_path(u);
735         if (!u)
736                 return -ENOMEM;
737
738         r = sd_bus_message_new_signal(
739                         bus,
740                         &m,
741                         "/org/freedesktop/systemd1",
742                         "org.freedesktop.systemd1.Manager",
743                         "UnitRemoved");
744         if (r < 0)
745                 return r;
746
747         r = sd_bus_message_append(m, "so", u->id, p);
748         if (r < 0)
749                 return r;
750
751         return sd_bus_send(bus, m, NULL);
752 }
753
754 void bus_unit_send_removed_signal(Unit *u) {
755         int r;
756         assert(u);
757
758         if (!u->sent_dbus_new_signal)
759                 bus_unit_send_change_signal(u);
760
761         if (!u->id)
762                 return;
763
764         r = bus_foreach_bus(u->manager, NULL, send_removed_signal, u);
765         if (r < 0)
766                 log_debug_errno(r, "Failed to send unit remove signal for %s: %m", u->id);
767 }
768
769 int bus_unit_queue_job(
770                 sd_bus *bus,
771                 sd_bus_message *message,
772                 Unit *u,
773                 JobType type,
774                 JobMode mode,
775                 bool reload_if_possible,
776                 sd_bus_error *error) {
777
778         _cleanup_free_ char *path = NULL;
779         Job *j;
780         int r;
781
782         assert(bus);
783         assert(message);
784         assert(u);
785         assert(type >= 0 && type < _JOB_TYPE_MAX);
786         assert(mode >= 0 && mode < _JOB_MODE_MAX);
787
788         if (reload_if_possible && unit_can_reload(u)) {
789                 if (type == JOB_RESTART)
790                         type = JOB_RELOAD_OR_START;
791                 else if (type == JOB_TRY_RESTART)
792                         type = JOB_RELOAD;
793         }
794
795         r = mac_selinux_unit_access_check(
796                         u, message,
797                         (type == JOB_START || type == JOB_RESTART || type == JOB_TRY_RESTART) ? "start" :
798                         type == JOB_STOP ? "stop" : "reload", error);
799         if (r < 0)
800                 return r;
801
802         if (type == JOB_STOP &&
803             (u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) &&
804             unit_active_state(u) == UNIT_INACTIVE)
805                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
806
807         if ((type == JOB_START && u->refuse_manual_start) ||
808             (type == JOB_STOP && u->refuse_manual_stop) ||
809             ((type == JOB_RESTART || type == JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)))
810                 return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only.", u->id);
811
812         r = manager_add_job(u->manager, type, u, mode, true, error, &j);
813         if (r < 0)
814                 return r;
815
816         if (bus == u->manager->api_bus) {
817                 if (!j->clients) {
818                         r = sd_bus_track_new(bus, &j->clients, NULL, NULL);
819                         if (r < 0)
820                                 return r;
821                 }
822
823                 r = sd_bus_track_add_sender(j->clients, message);
824                 if (r < 0)
825                         return r;
826         }
827
828         path = job_dbus_path(j);
829         if (!path)
830                 return -ENOMEM;
831
832         return sd_bus_reply_method_return(message, "o", path);
833 }
834
835 static int bus_unit_set_transient_property(
836                 Unit *u,
837                 const char *name,
838                 sd_bus_message *message,
839                 UnitSetPropertiesMode mode,
840                 sd_bus_error *error) {
841
842         int r;
843
844         assert(u);
845         assert(name);
846         assert(message);
847
848         if (streq(name, "Description")) {
849                 const char *d;
850
851                 r = sd_bus_message_read(message, "s", &d);
852                 if (r < 0)
853                         return r;
854
855                 if (mode != UNIT_CHECK) {
856                         r = unit_set_description(u, d);
857                         if (r < 0)
858                                 return r;
859
860                         unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s\n", d);
861                 }
862
863                 return 1;
864
865         } else if (streq(name, "Slice") && unit_get_cgroup_context(u)) {
866                 const char *s;
867
868                 r = sd_bus_message_read(message, "s", &s);
869                 if (r < 0)
870                         return r;
871
872                 if (!unit_name_is_valid(s, TEMPLATE_INVALID) || !endswith(s, ".slice"))
873                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid slice name %s", s);
874
875                 if (isempty(s)) {
876                         if (mode != UNIT_CHECK) {
877                                 unit_ref_unset(&u->slice);
878                                 unit_remove_drop_in(u, mode, name);
879                         }
880                 } else {
881                         Unit *slice;
882
883                         r = manager_load_unit(u->manager, s, NULL, error, &slice);
884                         if (r < 0)
885                                 return r;
886
887                         if (slice->type != UNIT_SLICE)
888                                 return -EINVAL;
889
890                         if (mode != UNIT_CHECK) {
891                                 unit_ref_set(&u->slice, slice);
892                                 unit_write_drop_in_private_format(u, mode, name, "Slice=%s\n", s);
893                         }
894                 }
895
896                 return 1;
897         } else if (STR_IN_SET(name,
898                               "Requires", "RequiresOverridable",
899                               "Requisite", "RequisiteOverridable",
900                               "Wants",
901                               "BindsTo",
902                               "Conflicts",
903                               "Before", "After",
904                               "OnFailure",
905                               "PropagatesReloadTo", "ReloadPropagatedFrom",
906                               "PartOf")) {
907
908                 UnitDependency d;
909                 const char *other;
910
911                 d = unit_dependency_from_string(name);
912                 if (d < 0)
913                         return -EINVAL;
914
915                 r = sd_bus_message_enter_container(message, 'a', "s");
916                 if (r < 0)
917                         return r;
918
919                 while ((r = sd_bus_message_read(message, "s", &other)) > 0) {
920                         if (!unit_name_is_valid(other, TEMPLATE_INVALID))
921                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
922
923                         if (mode != UNIT_CHECK) {
924                                 _cleanup_free_ char *label = NULL;
925
926                                 r = unit_add_dependency_by_name(u, d, other, NULL, true);
927                                 if (r < 0)
928                                         return r;
929
930                                 label = strjoin(name, "-", other, NULL);
931                                 if (!label)
932                                         return -ENOMEM;
933
934                                 unit_write_drop_in_format(u, mode, label, "[Unit]\n%s=%s\n", name, other);
935                         }
936
937                 }
938                 if (r < 0)
939                         return r;
940
941                 r = sd_bus_message_exit_container(message);
942                 if (r < 0)
943                         return r;
944
945                 return 1;
946         }
947
948         return 0;
949 }
950
951 int bus_unit_set_properties(
952                 Unit *u,
953                 sd_bus_message *message,
954                 UnitSetPropertiesMode mode,
955                 bool commit,
956                 sd_bus_error *error) {
957
958         bool for_real = false;
959         unsigned n = 0;
960         int r;
961
962         assert(u);
963         assert(message);
964
965         /* We iterate through the array twice. First run we just check
966          * if all passed data is valid, second run actually applies
967          * it. This is to implement transaction-like behaviour without
968          * actually providing full transactions. */
969
970         r = sd_bus_message_enter_container(message, 'a', "(sv)");
971         if (r < 0)
972                 return r;
973
974         for (;;) {
975                 const char *name;
976
977                 r = sd_bus_message_enter_container(message, 'r', "sv");
978                 if (r < 0)
979                         return r;
980                 if (r == 0) {
981                         if (for_real || mode == UNIT_CHECK)
982                                 break;
983
984                         /* Reached EOF. Let's try again, and this time for realz... */
985                         r = sd_bus_message_rewind(message, false);
986                         if (r < 0)
987                                 return r;
988
989                         for_real = true;
990                         continue;
991                 }
992
993                 r = sd_bus_message_read(message, "s", &name);
994                 if (r < 0)
995                         return r;
996
997                 if (!UNIT_VTABLE(u)->bus_set_property)
998                         return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
999
1000                 r = sd_bus_message_enter_container(message, 'v', NULL);
1001                 if (r < 0)
1002                         return r;
1003
1004                 r = UNIT_VTABLE(u)->bus_set_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
1005                 if (r == 0 && u->transient && u->load_state == UNIT_STUB)
1006                         r = bus_unit_set_transient_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
1007                 if (r < 0)
1008                         return r;
1009                 if (r == 0)
1010                         return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
1011
1012                 r = sd_bus_message_exit_container(message);
1013                 if (r < 0)
1014                         return r;
1015
1016                 r = sd_bus_message_exit_container(message);
1017                 if (r < 0)
1018                         return r;
1019
1020                 n += for_real;
1021         }
1022
1023         r = sd_bus_message_exit_container(message);
1024         if (r < 0)
1025                 return r;
1026
1027         if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties)
1028                 UNIT_VTABLE(u)->bus_commit_properties(u);
1029
1030         return n;
1031 }