chiark / gitweb /
bd7d02d73b6940ad3246d38cf86a4fbf44bf6444
[elogind.git] / src / core / busname.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 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 "special.h"
23 #include "bus-kernel.h"
24 #include "bus-internal.h"
25 #include "bus-util.h"
26 #include "service.h"
27 #include "dbus-busname.h"
28 #include "busname.h"
29
30 static const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = {
31         [BUSNAME_DEAD] = UNIT_INACTIVE,
32         [BUSNAME_LISTENING] = UNIT_ACTIVE,
33         [BUSNAME_RUNNING] = UNIT_ACTIVE,
34         [BUSNAME_FAILED] = UNIT_FAILED
35 };
36
37 static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
38
39 static void busname_init(Unit *u) {
40         BusName *n = BUSNAME(u);
41
42         assert(u);
43         assert(u->load_state == UNIT_STUB);
44
45         n->starter_fd = -1;
46 }
47
48 static void busname_done(Unit *u) {
49         BusName *n = BUSNAME(u);
50
51         assert(u);
52
53         free(n->name);
54         n->name = NULL;
55
56         unit_ref_unset(&n->service);
57
58         n->event_source = sd_event_source_unref(n->event_source);
59
60         if (n->starter_fd >= 0) {
61                 close_nointr_nofail(n->starter_fd);
62                 n->starter_fd = -1;
63         }
64 }
65
66 static int busname_add_default_default_dependencies(BusName *n) {
67         int r;
68
69         assert(n);
70
71         r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true);
72         if (r < 0)
73                 return r;
74
75         if (UNIT(n)->manager->running_as == SYSTEMD_SYSTEM) {
76                 r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
77                 if (r < 0)
78                         return r;
79         }
80
81         return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
82 }
83
84 static int busname_add_extras(BusName *n) {
85         Unit *u = UNIT(n);
86         int r;
87
88         assert(n);
89
90         if (!n->name) {
91                 n->name = unit_name_to_prefix(u->id);
92                 if (!n->name)
93                         return -ENOMEM;
94         }
95
96         if (!u->description) {
97                 r = unit_set_description(u, n->name);
98                 if (r < 0)
99                         return r;
100         }
101
102         if (!UNIT_DEREF(n->service)) {
103                 Unit *x;
104
105                 r = unit_load_related_unit(u, ".service", &x);
106                 if (r < 0)
107                         return r;
108
109                 unit_ref_set(&n->service, x);
110         }
111
112         r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true);
113         if (r < 0)
114                 return r;
115
116         if (u->default_dependencies) {
117                 r = busname_add_default_default_dependencies(n);
118                 if (r < 0)
119                         return r;
120         }
121
122         return 0;
123 }
124
125
126
127 static int busname_verify(BusName *n) {
128         char *e;
129
130         assert(n);
131
132         if (UNIT(n)->load_state != UNIT_LOADED)
133                 return 0;
134
135         if (!service_name_is_valid(n->name)) {
136                 log_error_unit(UNIT(n)->id, "%s's Name= setting is not a valid service name Refusing.", UNIT(n)->id);
137                 return -EINVAL;
138         }
139
140         e = strappenda(n->name, ".busname");
141         if (!unit_has_name(UNIT(n), e)) {
142                 log_error_unit(UNIT(n)->id, "%s's Name= setting doesn't match unit name. Refusing.", UNIT(n)->id);
143                 return -EINVAL;
144         }
145
146         return 0;
147 }
148
149 static int busname_load(Unit *u) {
150         BusName *n = BUSNAME(u);
151         int r;
152
153         assert(u);
154         assert(u->load_state == UNIT_STUB);
155
156         r = unit_load_fragment_and_dropin(u);
157         if (r < 0)
158                 return r;
159
160         if (u->load_state == UNIT_LOADED) {
161                 /* This is a new unit? Then let's add in some extras */
162                 r = busname_add_extras(n);
163                 if (r < 0)
164                         return r;
165         }
166
167         return busname_verify(n);
168 }
169
170 static void busname_dump(Unit *u, FILE *f, const char *prefix) {
171         BusName *n = BUSNAME(u);
172
173         assert(n);
174         assert(f);
175
176         fprintf(f,
177                 "%sBus Name State: %s\n"
178                 "%sResult: %s\n"
179                 "%sName: %s\n",
180                 prefix, busname_state_to_string(n->state),
181                 prefix, busname_result_to_string(n->result),
182                 prefix, n->name);
183 }
184
185 static void busname_unwatch_fd(BusName *n) {
186         int r;
187
188         assert(n);
189
190         if (n->event_source) {
191                 r = sd_event_source_set_enabled(n->event_source, SD_EVENT_OFF);
192                 if (r < 0)
193                         log_debug_unit(UNIT(n)->id, "Failed to disable event source.");
194         }
195 }
196
197 static void busname_close_fd(BusName *n) {
198         assert(n);
199
200         busname_unwatch_fd(n);
201
202         if (n->starter_fd <= 0)
203                 return;
204
205         close_nointr_nofail(n->starter_fd);
206         n->starter_fd = -1;
207 }
208
209 static int busname_watch_fd(BusName *n) {
210         int r;
211
212         assert(n);
213
214         if (n->starter_fd < 0)
215                 return 0;
216
217         if (n->event_source)
218                 r = sd_event_source_set_enabled(n->event_source, SD_EVENT_ON);
219         else
220                 r = sd_event_add_io(UNIT(n)->manager->event, &n->event_source, n->starter_fd, EPOLLIN, busname_dispatch_io, n);
221         if (r < 0) {
222                 log_warning_unit(UNIT(n)->id, "Failed to watch starter fd: %s", strerror(-r));
223                 busname_unwatch_fd(n);
224                 return r;
225         }
226
227         return 0;
228 }
229
230 static int busname_open_fd(BusName *n) {
231         assert(n);
232
233         if (n->starter_fd >= 0)
234                 return 0;
235
236         n->starter_fd = bus_kernel_create_starter(UNIT(n)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user",
237                                                   n->name, n->policy);
238         if (n->starter_fd < 0) {
239                 log_warning_unit(UNIT(n)->id, "Failed to create starter fd: %s", strerror(-n->starter_fd));
240                 return n->starter_fd;
241         }
242
243         return 0;
244 }
245
246 static void busname_set_state(BusName *n, BusNameState state) {
247         BusNameState old_state;
248         assert(n);
249
250         old_state = n->state;
251         n->state = state;
252
253         if (state != BUSNAME_LISTENING)
254                 busname_unwatch_fd(n);
255
256         if (!IN_SET(state, BUSNAME_LISTENING, BUSNAME_RUNNING))
257                 busname_close_fd(n);
258
259         if (state != old_state)
260                 log_debug_unit(UNIT(n)->id, "%s changed %s -> %s",
261                                UNIT(n)->id, busname_state_to_string(old_state), busname_state_to_string(state));
262
263         unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true);
264 }
265
266 static int busname_coldplug(Unit *u) {
267         BusName *n = BUSNAME(u);
268         int r;
269
270         assert(n);
271         assert(n->state == BUSNAME_DEAD);
272
273         if (n->deserialized_state == n->state)
274                 return 0;
275
276         if (IN_SET(n->deserialized_state, BUSNAME_LISTENING, BUSNAME_RUNNING)) {
277                 r = busname_open_fd(n);
278                 if (r < 0)
279                         return r;
280         }
281
282         if (n->deserialized_state == BUSNAME_LISTENING) {
283                 r = busname_watch_fd(n);
284                 if (r < 0)
285                         return r;
286         }
287
288         busname_set_state(n, n->deserialized_state);
289         return 0;
290 }
291
292 static void busname_enter_dead(BusName *n, BusNameResult f) {
293         assert(n);
294
295         if (f != BUSNAME_SUCCESS)
296                 n->result = f;
297
298         busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD);
299 }
300
301 static void busname_enter_listening(BusName *n) {
302         int r;
303
304         assert(n);
305
306         r = busname_open_fd(n);
307         if (r < 0) {
308                 log_warning_unit(UNIT(n)->id, "%s failed to listen on bus names: %s", UNIT(n)->id, strerror(-r));
309                 goto fail;
310         }
311
312         r = busname_watch_fd(n);
313         if (r < 0) {
314                 log_warning_unit(UNIT(n)->id, "%s failed to watch names: %s", UNIT(n)->id, strerror(-r));
315                 goto fail;
316         }
317
318         busname_set_state(n, BUSNAME_LISTENING);
319         return;
320
321 fail:
322         busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
323 }
324
325 static void busname_enter_running(BusName *n) {
326         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
327         bool pending = false;
328         Unit *other;
329         Iterator i;
330         int r;
331
332         assert(n);
333
334         /* We don't take conenctions anymore if we are supposed to
335          * shut down anyway */
336
337         if (unit_stop_pending(UNIT(n))) {
338                 log_debug_unit(UNIT(n)->id, "Suppressing activation request on %s since unit stop is scheduled.", UNIT(n)->id);
339
340                 /* Flush all queued activation reqeuest by closing and reopening the connection */
341                 bus_kernel_drop_one(n->starter_fd);
342
343                 busname_enter_listening(n);
344                 return;
345         }
346
347         /* If there's already a start pending don't bother to do
348          * anything */
349         SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
350                 if (unit_active_or_pending(other)) {
351                         pending = true;
352                         break;
353                 }
354
355         if (!pending) {
356                 r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
357                 if (r < 0)
358                         goto fail;
359         }
360
361         busname_set_state(n, BUSNAME_RUNNING);
362         return;
363
364 fail:
365         log_warning_unit(UNIT(n)->id, "%s failed to queue service startup job: %s", UNIT(n)->id, bus_error_message(&error, r));
366         busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
367 }
368
369 static int busname_start(Unit *u) {
370         BusName *n = BUSNAME(u);
371
372         assert(n);
373
374         if (UNIT_ISSET(n->service)) {
375                 Service *service;
376
377                 service = SERVICE(UNIT_DEREF(n->service));
378
379                 if (UNIT(service)->load_state != UNIT_LOADED) {
380                         log_error_unit(u->id, "Bus service %s not loaded, refusing.", UNIT(service)->id);
381                         return -ENOENT;
382                 }
383         }
384
385         assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
386
387         n->result = BUSNAME_SUCCESS;
388         busname_enter_listening(n);
389
390         return 0;
391 }
392
393 static int busname_stop(Unit *u) {
394         BusName *n = BUSNAME(u);
395
396         assert(n);
397         assert(n->state == BUSNAME_LISTENING || n->state == BUSNAME_RUNNING);
398
399         busname_enter_dead(n, BUSNAME_SUCCESS);
400         return 0;
401 }
402
403 static int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
404         BusName *n = BUSNAME(u);
405
406         assert(n);
407         assert(f);
408         assert(fds);
409
410         unit_serialize_item(u, f, "state", busname_state_to_string(n->state));
411         unit_serialize_item(u, f, "result", busname_result_to_string(n->result));
412
413         if (n->starter_fd >= 0) {
414                 int copy;
415
416                 copy = fdset_put_dup(fds, n->starter_fd);
417                 if (copy < 0)
418                         return copy;
419
420                 unit_serialize_item_format(u, f, "starter-fd", "%i", copy);
421         }
422
423         return 0;
424 }
425
426 static int busname_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
427         BusName *n = BUSNAME(u);
428
429         assert(n);
430         assert(key);
431         assert(value);
432
433         if (streq(key, "state")) {
434                 BusNameState state;
435
436                 state = busname_state_from_string(value);
437                 if (state < 0)
438                         log_debug_unit(u->id, "Failed to parse state value %s", value);
439                 else
440                         n->deserialized_state = state;
441
442         } else if (streq(key, "result")) {
443                 BusNameResult f;
444
445                 f = busname_result_from_string(value);
446                 if (f < 0)
447                         log_debug_unit(u->id, "Failed to parse result value %s", value);
448                 else if (f != BUSNAME_SUCCESS)
449                         n->result = f;
450
451         } else if (streq(key, "starter-fd")) {
452                 int fd;
453
454                 if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
455                         log_debug_unit(u->id, "Failed to parse starter fd value %s", value);
456                 else {
457                         if (n->starter_fd >= 0)
458                                 close_nointr_nofail(n->starter_fd);
459                         n->starter_fd = fdset_remove(fds, fd);
460                 }
461         } else
462                 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
463
464         return 0;
465 }
466
467 _pure_ static UnitActiveState busname_active_state(Unit *u) {
468         assert(u);
469
470         return state_translation_table[BUSNAME(u)->state];
471 }
472
473 _pure_ static const char *busname_sub_state_to_string(Unit *u) {
474         assert(u);
475
476         return busname_state_to_string(BUSNAME(u)->state);
477 }
478
479 static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
480         BusName *n = userdata;
481
482         assert(n);
483         assert(fd >= 0);
484
485         if (n->state != BUSNAME_LISTENING)
486                 return 0;
487
488         log_debug_unit(UNIT(n)->id, "Activation request on %s", UNIT(n)->id);
489
490         if (revents != EPOLLIN) {
491                 log_error_unit(UNIT(n)->id, "%s: Got unexpected poll event (0x%x) on starter fd.",
492                                UNIT(n)->id, revents);
493                 goto fail;
494         }
495
496         busname_enter_running(n);
497         return 0;
498 fail:
499
500         busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
501         return 0;
502 }
503
504 static void busname_reset_failed(Unit *u) {
505         BusName *n = BUSNAME(u);
506
507         assert(n);
508
509         if (n->state == BUSNAME_FAILED)
510                 busname_set_state(n, BUSNAME_DEAD);
511
512         n->result = BUSNAME_SUCCESS;
513 }
514
515 static void busname_trigger_notify(Unit *u, Unit *other) {
516         BusName *n = BUSNAME(u);
517         Service *s;
518
519         assert(n);
520         assert(other);
521
522         if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING))
523                 return;
524
525         if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
526                 return;
527
528         s = SERVICE(other);
529
530         if (s->state == SERVICE_FAILED && s->result == SERVICE_FAILURE_START_LIMIT)
531                 busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT);
532         else if (IN_SET(s->state,
533                         SERVICE_DEAD, SERVICE_FAILED,
534                         SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
535                         SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
536                         SERVICE_AUTO_RESTART))
537                 busname_enter_listening(n);
538 }
539
540 static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
541         [BUSNAME_DEAD] = "dead",
542         [BUSNAME_LISTENING] = "listening",
543         [BUSNAME_RUNNING] = "running",
544         [BUSNAME_FAILED] = "failed"
545 };
546
547 DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
548
549 static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
550         [BUSNAME_SUCCESS] = "success",
551         [BUSNAME_FAILURE_RESOURCES] = "resources",
552         [BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT] = "service-failed-permanent",
553 };
554
555 DEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);
556
557 static const char* const busname_policy_access_table[_BUSNAME_POLICY_ACCESS_MAX] = {
558         [BUSNAME_POLICY_ACCESS_SEE] = "see",
559         [BUSNAME_POLICY_ACCESS_TALK] = "talk",
560         [BUSNAME_POLICY_ACCESS_OWN] = "own",
561 };
562
563 DEFINE_STRING_TABLE_LOOKUP(busname_policy_access, BusNamePolicyAccess);
564
565 const UnitVTable busname_vtable = {
566         .object_size = sizeof(BusName),
567
568         .sections =
569                 "Unit\0"
570                 "BusName\0"
571                 "Install\0",
572         .private_section = "BusName",
573
574         .init = busname_init,
575         .done = busname_done,
576         .load = busname_load,
577
578         .coldplug = busname_coldplug,
579
580         .dump = busname_dump,
581
582         .start = busname_start,
583         .stop = busname_stop,
584
585         .serialize = busname_serialize,
586         .deserialize_item = busname_deserialize_item,
587
588         .active_state = busname_active_state,
589         .sub_state_to_string = busname_sub_state_to_string,
590
591         .trigger_notify = busname_trigger_notify,
592
593         .reset_failed = busname_reset_failed,
594
595         .bus_interface = "org.freedesktop.systemd1.BusName",
596         .bus_vtable = bus_busname_vtable,
597
598         .status_message_formats = {
599                 .finished_start_job = {
600                         [JOB_DONE]       = "Listening on %s.",
601                         [JOB_FAILED]     = "Failed to listen on %s.",
602                         [JOB_DEPENDENCY] = "Dependency failed for %s.",
603                         [JOB_TIMEOUT]    = "Timed out starting %s.",
604                 },
605                 .finished_stop_job = {
606                         [JOB_DONE]       = "Closed %s.",
607                         [JOB_FAILED]     = "Failed stopping %s.",
608                         [JOB_TIMEOUT]    = "Timed out stopping %s.",
609                 },
610         },
611 };