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