]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/socket.c
unit: make unit casts typesafe
[thirdparty/systemd.git] / src / socket.c
CommitLineData
5cb5a6ff
LP
1/*-*- Mode: C; c-basic-offset: 8 -*-*/
2
a7334b09
LP
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 General Public License as published by
10 the Free Software Foundation; either version 2 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 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
83c60c9f
LP
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include <errno.h>
26#include <fcntl.h>
f94ea366 27#include <sys/epoll.h>
034c6ed7 28#include <signal.h>
4f2d528d 29#include <arpa/inet.h>
83c60c9f 30
87f0e418 31#include "unit.h"
5cb5a6ff 32#include "socket.h"
83c60c9f 33#include "log.h"
23a177ef
LP
34#include "load-dropin.h"
35#include "load-fragment.h"
9e2f7c11 36#include "strv.h"
4f2d528d 37#include "unit-name.h"
4139c1b2 38#include "dbus-socket.h"
83c60c9f 39
acbb0225 40static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
87f0e418
LP
41 [SOCKET_DEAD] = UNIT_INACTIVE,
42 [SOCKET_START_PRE] = UNIT_ACTIVATING,
43 [SOCKET_START_POST] = UNIT_ACTIVATING,
44 [SOCKET_LISTENING] = UNIT_ACTIVE,
45 [SOCKET_RUNNING] = UNIT_ACTIVE,
46 [SOCKET_STOP_PRE] = UNIT_DEACTIVATING,
47 [SOCKET_STOP_PRE_SIGTERM] = UNIT_DEACTIVATING,
48 [SOCKET_STOP_PRE_SIGKILL] = UNIT_DEACTIVATING,
49 [SOCKET_STOP_POST] = UNIT_DEACTIVATING,
80876c20
LP
50 [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING,
51 [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING,
18c78fb1 52 [SOCKET_MAINTENANCE] = UNIT_INACTIVE,
83c60c9f 53};
5cb5a6ff 54
a16e1123
LP
55static void socket_init(Unit *u) {
56 Socket *s = SOCKET(u);
57
58 assert(u);
59 assert(u->meta.load_state == UNIT_STUB);
60
a16e1123
LP
61 s->backlog = SOMAXCONN;
62 s->timeout_usec = DEFAULT_TIMEOUT_USEC;
63 s->directory_mode = 0755;
64 s->socket_mode = 0666;
65
6cf6bbc2
LP
66 s->max_connections = 64;
67
a16e1123
LP
68 exec_context_init(&s->exec_context);
69
70 s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
71}
acbb0225 72
5e94833f
LP
73static void socket_unwatch_control_pid(Socket *s) {
74 assert(s);
75
76 if (s->control_pid <= 0)
77 return;
78
79 unit_unwatch_pid(UNIT(s), s->control_pid);
80 s->control_pid = 0;
81}
82
87f0e418
LP
83static void socket_done(Unit *u) {
84 Socket *s = SOCKET(u);
034c6ed7 85 SocketPort *p;
6cf6bbc2 86 Meta *i;
034c6ed7
LP
87
88 assert(s);
89
90 while ((p = s->ports)) {
91 LIST_REMOVE(SocketPort, port, s->ports, p);
92
a16e1123
LP
93 if (p->fd >= 0) {
94 unit_unwatch_fd(UNIT(s), &p->fd_watch);
95 close_nointr_nofail(p->fd);
96 }
97
034c6ed7
LP
98 free(p->path);
99 free(p);
100 }
101
102 exec_context_done(&s->exec_context);
e537352b 103 exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX);
034c6ed7
LP
104 s->control_command = NULL;
105
5e94833f 106 socket_unwatch_control_pid(s);
034c6ed7
LP
107
108 s->service = NULL;
109
acbb0225 110 free(s->bind_to_device);
e537352b 111 s->bind_to_device = NULL;
acbb0225
LP
112
113 unit_unwatch_timer(u, &s->timer_watch);
6cf6bbc2
LP
114
115 /* Make sure no service instance refers to us anymore. */
116 LIST_FOREACH(units_per_type, i, u->meta.manager->units_per_type[UNIT_SERVICE]) {
117 Service *service = (Service *) i;
118
119 if (service->socket == s)
120 service->socket = NULL;
121 }
5cb5a6ff
LP
122}
123
4f2d528d
LP
124static bool have_non_accept_socket(Socket *s) {
125 SocketPort *p;
126
127 assert(s);
128
129 if (!s->accept)
130 return true;
131
dd5ad9d4
LP
132 LIST_FOREACH(port, p, s->ports) {
133
134 if (p->type != SOCKET_SOCKET)
135 return true;
136
4f2d528d
LP
137 if (!socket_address_can_accept(&p->address))
138 return true;
dd5ad9d4 139 }
4f2d528d
LP
140
141 return false;
142}
143
144static int socket_verify(Socket *s) {
145 assert(s);
146
4cd1fbcc 147 if (s->meta.load_state != UNIT_LOADED)
4f2d528d
LP
148 return 0;
149
150 if (!s->ports) {
4cd1fbcc 151 log_error("%s lacks Listen setting. Refusing.", s->meta.id);
4f2d528d
LP
152 return -EINVAL;
153 }
154
6cf6bbc2
LP
155 if (s->accept && s->max_connections <= 0) {
156 log_error("%s's MaxConnection setting too small. Refusing.", UNIT(s)->meta.id);
157 return -EINVAL;
158 }
159
4f2d528d
LP
160 return 0;
161}
162
6e2ef85b
LP
163static bool socket_needs_mount(Socket *s, const char *prefix) {
164 SocketPort *p;
165
166 assert(s);
167
168 LIST_FOREACH(port, p, s->ports) {
169
170 if (p->type == SOCKET_SOCKET) {
171 if (socket_address_needs_mount(&p->address, prefix))
172 return true;
173 } else {
174 assert(p->type == SOCKET_FIFO);
175 if (path_startswith(p->path, prefix))
176 return true;
177 }
178 }
179
180 return false;
181}
182
183int socket_add_one_mount_link(Socket *s, Mount *m) {
184 int r;
185
186 assert(s);
187 assert(m);
188
189 if (s->meta.load_state != UNIT_LOADED ||
190 m->meta.load_state != UNIT_LOADED)
191 return 0;
192
193 if (!socket_needs_mount(s, m->where))
194 return 0;
195
196 if ((r = unit_add_dependency(UNIT(m), UNIT_BEFORE, UNIT(s), true)) < 0)
197 return r;
198
199 if ((r = unit_add_dependency(UNIT(s), UNIT_REQUIRES, UNIT(m), true)) < 0)
200 return r;
201
202 return 0;
203}
204
205static int socket_add_mount_links(Socket *s) {
206 Meta *other;
207 int r;
208
209 assert(s);
210
211 LIST_FOREACH(units_per_type, other, s->meta.manager->units_per_type[UNIT_MOUNT])
212 if ((r = socket_add_one_mount_link(s, (Mount*) other)) < 0)
213 return r;
214
215 return 0;
216}
217
218static int socket_add_device_link(Socket *s) {
219 char *t;
220 int r;
221
222 assert(s);
223
224 if (!s->bind_to_device)
225 return 0;
226
227 if (asprintf(&t, "/sys/subsystem/net/devices/%s", s->bind_to_device) < 0)
228 return -ENOMEM;
229
230 r = unit_add_node_link(UNIT(s), t, false);
231 free(t);
232
233 return r;
234}
235
e537352b
LP
236static int socket_load(Unit *u) {
237 Socket *s = SOCKET(u);
238 int r;
44d8db9e 239
e537352b
LP
240 assert(u);
241 assert(u->meta.load_state == UNIT_STUB);
44d8db9e 242
e537352b 243 if ((r = unit_load_fragment_and_dropin(u)) < 0)
23a177ef 244 return r;
44d8db9e 245
23a177ef 246 /* This is a new unit? Then let's add in some extras */
e537352b 247 if (u->meta.load_state == UNIT_LOADED) {
44d8db9e 248
4f2d528d
LP
249 if (have_non_accept_socket(s)) {
250 if ((r = unit_load_related_unit(u, ".service", (Unit**) &s->service)))
251 return r;
23a177ef 252
701cc384 253 if ((r = unit_add_dependency(u, UNIT_BEFORE, UNIT(s->service), true)) < 0)
4f2d528d
LP
254 return r;
255 }
44d8db9e 256
6e2ef85b
LP
257 if ((r = socket_add_mount_links(s)) < 0)
258 return r;
259
260 if ((r = socket_add_device_link(s)) < 0)
261 return r;
262
23a177ef
LP
263 if ((r = unit_add_exec_dependencies(u, &s->exec_context)) < 0)
264 return r;
265
266 if ((r = unit_add_default_cgroup(u)) < 0)
267 return r;
268 }
269
4f2d528d 270 return socket_verify(s);
44d8db9e
LP
271}
272
542563ba
LP
273static const char* listen_lookup(int type) {
274
275 if (type == SOCK_STREAM)
276 return "ListenStream";
277 else if (type == SOCK_DGRAM)
278 return "ListenDatagram";
279 else if (type == SOCK_SEQPACKET)
280 return "ListenSequentialPacket";
281
034c6ed7 282 assert_not_reached("Unknown socket type");
542563ba
LP
283 return NULL;
284}
285
87f0e418 286static void socket_dump(Unit *u, FILE *f, const char *prefix) {
5cb5a6ff 287
5cb5a6ff 288 SocketExecCommand c;
87f0e418 289 Socket *s = SOCKET(u);
542563ba 290 SocketPort *p;
82ba9f08
LP
291 const char *prefix2;
292 char *p2;
5cb5a6ff
LP
293
294 assert(s);
fa068367 295 assert(f);
5cb5a6ff 296
82ba9f08
LP
297 p2 = strappend(prefix, "\t");
298 prefix2 = p2 ? p2 : prefix;
c43d20a0 299
5cb5a6ff
LP
300 fprintf(f,
301 "%sSocket State: %s\n"
542563ba 302 "%sBindIPv6Only: %s\n"
b5a0699f 303 "%sBacklog: %u\n"
50159e6a 304 "%sKillMode: %s\n"
b5a0699f
LP
305 "%sSocketMode: %04o\n"
306 "%sDirectoryMode: %04o\n",
a16e1123 307 prefix, socket_state_to_string(s->state),
c0120d99 308 prefix, socket_address_bind_ipv6_only_to_string(s->bind_ipv6_only),
b5a0699f 309 prefix, s->backlog,
50159e6a 310 prefix, kill_mode_to_string(s->kill_mode),
b5a0699f
LP
311 prefix, s->socket_mode,
312 prefix, s->directory_mode);
542563ba 313
70123e68
LP
314 if (s->control_pid > 0)
315 fprintf(f,
bb00e604
LP
316 "%sControl PID: %lu\n",
317 prefix, (unsigned long) s->control_pid);
70123e68 318
acbb0225
LP
319 if (s->bind_to_device)
320 fprintf(f,
321 "%sBindToDevice: %s\n",
322 prefix, s->bind_to_device);
323
4f2d528d
LP
324 if (s->accept)
325 fprintf(f,
6cf6bbc2
LP
326 "%sAccepted: %u\n"
327 "%sNConnections: %u\n"
328 "%sMaxConnections: %u\n",
329 prefix, s->n_accepted,
330 prefix, s->n_connections,
331 prefix, s->max_connections);
4f2d528d 332
034c6ed7 333 LIST_FOREACH(port, p, s->ports) {
5cb5a6ff 334
542563ba
LP
335 if (p->type == SOCKET_SOCKET) {
336 const char *t;
337 int r;
338 char *k;
339
340 if ((r = socket_address_print(&p->address, &k)) < 0)
341 t = strerror(-r);
342 else
343 t = k;
344
345 fprintf(f, "%s%s: %s\n", prefix, listen_lookup(p->address.type), k);
346 free(k);
347 } else
348 fprintf(f, "%sListenFIFO: %s\n", prefix, p->path);
349 }
5cb5a6ff
LP
350
351 exec_context_dump(&s->exec_context, f, prefix);
352
e537352b 353 for (c = 0; c < _SOCKET_EXEC_COMMAND_MAX; c++) {
c43d20a0
LP
354 if (!s->exec_command[c])
355 continue;
5cb5a6ff 356
40d50879 357 fprintf(f, "%s-> %s:\n",
a16e1123 358 prefix, socket_exec_command_to_string(c));
c43d20a0
LP
359
360 exec_command_dump_list(s->exec_command[c], f, prefix2);
5cb5a6ff 361 }
c43d20a0 362
82ba9f08 363 free(p2);
5cb5a6ff
LP
364}
365
4f2d528d
LP
366static int instance_from_socket(int fd, unsigned nr, char **instance) {
367 socklen_t l;
368 char *r;
369 union {
370 struct sockaddr sa;
371 struct sockaddr_un un;
372 struct sockaddr_in in;
373 struct sockaddr_in6 in6;
374 struct sockaddr_storage storage;
375 } local, remote;
376
377 assert(fd >= 0);
378 assert(instance);
379
380 l = sizeof(local);
381 if (getsockname(fd, &local.sa, &l) < 0)
382 return -errno;
383
384 l = sizeof(remote);
385 if (getpeername(fd, &remote.sa, &l) < 0)
386 return -errno;
387
388 switch (local.sa.sa_family) {
389
390 case AF_INET: {
391 uint32_t
392 a = ntohl(local.in.sin_addr.s_addr),
393 b = ntohl(remote.in.sin_addr.s_addr);
394
395 if (asprintf(&r,
a16e1123 396 "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u",
4f2d528d
LP
397 nr,
398 a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
399 ntohs(local.in.sin_port),
400 b >> 24, (b >> 16) & 0xFF, (b >> 8) & 0xFF, b & 0xFF,
401 ntohs(remote.in.sin_port)) < 0)
402 return -ENOMEM;
403
404 break;
405 }
406
407 case AF_INET6: {
2b061f5a
LP
408 static const char ipv4_prefix[] = {
409 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
410 };
411
412 if (memcmp(&local.in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0 &&
413 memcmp(&remote.in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) {
414 const uint8_t
415 *a = local.in6.sin6_addr.s6_addr+12,
416 *b = remote.in6.sin6_addr.s6_addr+12;
417
418 if (asprintf(&r,
419 "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u",
420 nr,
421 a[0], a[1], a[2], a[3],
422 ntohs(local.in6.sin6_port),
423 b[0], b[1], b[2], b[3],
424 ntohs(remote.in6.sin6_port)) < 0)
425 return -ENOMEM;
426 } else {
427 char a[INET6_ADDRSTRLEN], b[INET6_ADDRSTRLEN];
428
429 if (asprintf(&r,
430 "%u-%s:%u-%s:%u",
431 nr,
432 inet_ntop(AF_INET6, &local.in6.sin6_addr, a, sizeof(a)),
433 ntohs(local.in6.sin6_port),
434 inet_ntop(AF_INET6, &remote.in6.sin6_addr, b, sizeof(b)),
435 ntohs(remote.in6.sin6_port)) < 0)
436 return -ENOMEM;
437 }
4f2d528d
LP
438
439 break;
440 }
441
442 case AF_UNIX: {
443 struct ucred ucred;
444
445 l = sizeof(ucred);
446 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
447 return -errno;
448
449 if (asprintf(&r,
bb00e604 450 "%u-%lu-%lu",
4f2d528d 451 nr,
bb00e604
LP
452 (unsigned long) ucred.pid,
453 (unsigned long) ucred.uid) < 0)
4f2d528d
LP
454 return -ENOMEM;
455
456 break;
457 }
458
459 default:
460 assert_not_reached("Unhandled socket type.");
461 }
462
463 *instance = r;
464 return 0;
465}
466
034c6ed7 467static void socket_close_fds(Socket *s) {
83c60c9f
LP
468 SocketPort *p;
469
470 assert(s);
471
034c6ed7 472 LIST_FOREACH(port, p, s->ports) {
83c60c9f
LP
473 if (p->fd < 0)
474 continue;
475
acbb0225 476 unit_unwatch_fd(UNIT(s), &p->fd_watch);
a16e1123
LP
477 close_nointr_nofail(p->fd);
478
479 /* One little note: we should never delete any sockets
480 * in the file system here! After all some other
481 * process we spawned might still have a reference of
482 * this fd and wants to continue to use it. Therefore
483 * we delete sockets in the file system before we
484 * create a new one, not after we stopped using
485 * one! */
9152c765 486
83c60c9f
LP
487 p->fd = -1;
488 }
489}
490
034c6ed7 491static int socket_open_fds(Socket *s) {
83c60c9f
LP
492 SocketPort *p;
493 int r;
494
495 assert(s);
496
034c6ed7 497 LIST_FOREACH(port, p, s->ports) {
83c60c9f 498
034c6ed7
LP
499 if (p->fd >= 0)
500 continue;
83c60c9f
LP
501
502 if (p->type == SOCKET_SOCKET) {
503
b5a0699f
LP
504 if ((r = socket_address_listen(
505 &p->address,
506 s->backlog,
507 s->bind_ipv6_only,
508 s->bind_to_device,
509 s->directory_mode,
510 s->socket_mode,
511 &p->fd)) < 0)
83c60c9f
LP
512 goto rollback;
513
514 } else {
515 struct stat st;
516 assert(p->type == SOCKET_FIFO);
517
8cb45bf8
LP
518 mkdir_parents(p->path, s->directory_mode);
519
520 if (mkfifo(p->path, s->socket_mode) < 0 && errno != EEXIST) {
83c60c9f
LP
521 r = -errno;
522 goto rollback;
523 }
524
525 if ((p->fd = open(p->path, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW)) < 0) {
526 r = -errno;
527 goto rollback;
528 }
529
530 if (fstat(p->fd, &st) < 0) {
531 r = -errno;
532 goto rollback;
533 }
534
535 /* FIXME verify user, access mode */
536
537 if (!S_ISFIFO(st.st_mode)) {
538 r = -EEXIST;
539 goto rollback;
540 }
541 }
034c6ed7
LP
542 }
543
544 return 0;
545
546rollback:
547 socket_close_fds(s);
548 return r;
549}
550
551static void socket_unwatch_fds(Socket *s) {
552 SocketPort *p;
9152c765 553
034c6ed7
LP
554 assert(s);
555
556 LIST_FOREACH(port, p, s->ports) {
557 if (p->fd < 0)
558 continue;
559
acbb0225 560 unit_unwatch_fd(UNIT(s), &p->fd_watch);
83c60c9f 561 }
034c6ed7
LP
562}
563
564static int socket_watch_fds(Socket *s) {
565 SocketPort *p;
566 int r;
567
568 assert(s);
83c60c9f 569
034c6ed7
LP
570 LIST_FOREACH(port, p, s->ports) {
571 if (p->fd < 0)
572 continue;
573
cabab516 574 p->fd_watch.socket_accept =
4f2d528d 575 s->accept &&
dd5ad9d4 576 p->type == SOCKET_SOCKET &&
4f2d528d
LP
577 socket_address_can_accept(&p->address);
578
f94ea366 579 if ((r = unit_watch_fd(UNIT(s), p->fd, EPOLLIN, &p->fd_watch)) < 0)
034c6ed7
LP
580 goto fail;
581 }
83c60c9f 582
542563ba 583 return 0;
83c60c9f 584
034c6ed7
LP
585fail:
586 socket_unwatch_fds(s);
587 return r;
588}
589
590static void socket_set_state(Socket *s, SocketState state) {
591 SocketState old_state;
592 assert(s);
593
594 old_state = s->state;
595 s->state = state;
596
597 if (state != SOCKET_START_PRE &&
598 state != SOCKET_START_POST &&
599 state != SOCKET_STOP_PRE &&
600 state != SOCKET_STOP_PRE_SIGTERM &&
601 state != SOCKET_STOP_PRE_SIGKILL &&
602 state != SOCKET_STOP_POST &&
80876c20
LP
603 state != SOCKET_FINAL_SIGTERM &&
604 state != SOCKET_FINAL_SIGKILL) {
acbb0225 605 unit_unwatch_timer(UNIT(s), &s->timer_watch);
5e94833f 606 socket_unwatch_control_pid(s);
034c6ed7 607 s->control_command = NULL;
a16e1123 608 s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
e537352b 609 }
034c6ed7 610
a16e1123
LP
611 if (state != SOCKET_LISTENING)
612 socket_unwatch_fds(s);
613
034c6ed7
LP
614 if (state != SOCKET_START_POST &&
615 state != SOCKET_LISTENING &&
616 state != SOCKET_RUNNING &&
617 state != SOCKET_STOP_PRE &&
618 state != SOCKET_STOP_PRE_SIGTERM &&
619 state != SOCKET_STOP_PRE_SIGKILL)
620 socket_close_fds(s);
621
e537352b 622 if (state != old_state)
40d50879 623 log_debug("%s changed %s -> %s",
a16e1123
LP
624 s->meta.id,
625 socket_state_to_string(old_state),
626 socket_state_to_string(state));
acbb0225
LP
627
628 unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state]);
034c6ed7
LP
629}
630
a16e1123
LP
631static int socket_coldplug(Unit *u) {
632 Socket *s = SOCKET(u);
633 int r;
634
635 assert(s);
636 assert(s->state == SOCKET_DEAD);
637
638 if (s->deserialized_state != s->state) {
639
640 if (s->deserialized_state == SOCKET_START_PRE ||
641 s->deserialized_state == SOCKET_START_POST ||
642 s->deserialized_state == SOCKET_STOP_PRE ||
643 s->deserialized_state == SOCKET_STOP_PRE_SIGTERM ||
644 s->deserialized_state == SOCKET_STOP_PRE_SIGKILL ||
645 s->deserialized_state == SOCKET_STOP_POST ||
646 s->deserialized_state == SOCKET_FINAL_SIGTERM ||
647 s->deserialized_state == SOCKET_FINAL_SIGKILL) {
648
649 if (s->control_pid <= 0)
650 return -EBADMSG;
651
652 if ((r = unit_watch_pid(UNIT(s), s->control_pid)) < 0)
653 return r;
654
655 if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
656 return r;
657 }
658
659 if (s->deserialized_state == SOCKET_START_POST ||
660 s->deserialized_state == SOCKET_LISTENING ||
661 s->deserialized_state == SOCKET_RUNNING ||
662 s->deserialized_state == SOCKET_STOP_PRE ||
663 s->deserialized_state == SOCKET_STOP_PRE_SIGTERM ||
664 s->deserialized_state == SOCKET_STOP_PRE_SIGKILL)
665 if ((r = socket_open_fds(s)) < 0)
666 return r;
667
668 if (s->deserialized_state == SOCKET_LISTENING)
669 if ((r = socket_watch_fds(s)) < 0)
670 return r;
671
672 socket_set_state(s, s->deserialized_state);
673 }
674
675 return 0;
676}
677
e537352b 678static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
034c6ed7
LP
679 pid_t pid;
680 int r;
9e2f7c11 681 char **argv;
034c6ed7
LP
682
683 assert(s);
684 assert(c);
685 assert(_pid);
686
e537352b
LP
687 if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
688 goto fail;
034c6ed7 689
9e2f7c11
LP
690 if (!(argv = unit_full_printf_strv(UNIT(s), c->argv))) {
691 r = -ENOMEM;
692 goto fail;
693 }
694
695 r = exec_spawn(c,
696 argv,
697 &s->exec_context,
698 NULL, 0,
1137a57c 699 s->meta.manager->environment,
9e2f7c11
LP
700 true,
701 true,
4cd1fbcc
LP
702 s->meta.manager->confirm_spawn,
703 s->meta.cgroup_bondings,
9e2f7c11
LP
704 &pid);
705
706 strv_free(argv);
707 if (r < 0)
034c6ed7
LP
708 goto fail;
709
87f0e418 710 if ((r = unit_watch_pid(UNIT(s), pid)) < 0)
034c6ed7
LP
711 /* FIXME: we need to do something here */
712 goto fail;
83c60c9f 713
034c6ed7
LP
714 *_pid = pid;
715
716 return 0;
717
718fail:
e537352b 719 unit_unwatch_timer(UNIT(s), &s->timer_watch);
83c60c9f
LP
720
721 return r;
542563ba
LP
722}
723
034c6ed7
LP
724static void socket_enter_dead(Socket *s, bool success) {
725 assert(s);
726
727 if (!success)
728 s->failure = true;
729
18c78fb1 730 socket_set_state(s, s->failure ? SOCKET_MAINTENANCE : SOCKET_DEAD);
034c6ed7
LP
731}
732
80876c20
LP
733static void socket_enter_signal(Socket *s, SocketState state, bool success);
734
034c6ed7
LP
735static void socket_enter_stop_post(Socket *s, bool success) {
736 int r;
737 assert(s);
738
739 if (!success)
740 s->failure = true;
741
5e94833f
LP
742 socket_unwatch_control_pid(s);
743
a16e1123
LP
744 s->control_command_id = SOCKET_EXEC_STOP_POST;
745
80876c20 746 if ((s->control_command = s->exec_command[SOCKET_EXEC_STOP_POST])) {
e537352b 747 if ((r = socket_spawn(s, s->control_command, &s->control_pid)) < 0)
034c6ed7
LP
748 goto fail;
749
80876c20
LP
750 socket_set_state(s, SOCKET_STOP_POST);
751 } else
752 socket_enter_signal(s, SOCKET_FINAL_SIGTERM, true);
034c6ed7
LP
753
754 return;
755
756fail:
6cf6bbc2 757 log_warning("%s failed to run 'stop-post' task: %s", s->meta.id, strerror(-r));
80876c20 758 socket_enter_signal(s, SOCKET_FINAL_SIGTERM, false);
034c6ed7
LP
759}
760
761static void socket_enter_signal(Socket *s, SocketState state, bool success) {
762 int r;
80876c20 763 bool sent = false;
034c6ed7
LP
764
765 assert(s);
766
767 if (!success)
768 s->failure = true;
769
80876c20
LP
770 if (s->kill_mode != KILL_NONE) {
771 int sig = (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_FINAL_SIGTERM) ? SIGTERM : SIGKILL;
034c6ed7 772
50159e6a
LP
773 if (s->kill_mode == KILL_CONTROL_GROUP) {
774
4cd1fbcc 775 if ((r = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig)) < 0) {
50159e6a
LP
776 if (r != -EAGAIN && r != -ESRCH)
777 goto fail;
778 } else
779 sent = true;
034c6ed7 780 }
50159e6a 781
80876c20 782 if (!sent && s->control_pid > 0)
50159e6a
LP
783 if (kill(s->kill_mode == KILL_PROCESS ? s->control_pid : -s->control_pid, sig) < 0 && errno != ESRCH) {
784 r = -errno;
785 goto fail;
786 }
d6ea93e3 787 }
034c6ed7 788
e93bc5a6 789 if (sent && s->control_pid > 0) {
80876c20
LP
790 if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
791 goto fail;
d6ea93e3 792
80876c20
LP
793 socket_set_state(s, state);
794 } else if (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_STOP_PRE_SIGKILL)
795 socket_enter_stop_post(s, true);
796 else
034c6ed7
LP
797 socket_enter_dead(s, true);
798
799 return;
800
801fail:
9e2f7c11 802 log_warning("%s failed to kill processes: %s", s->meta.id, strerror(-r));
034c6ed7
LP
803
804 if (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_STOP_PRE_SIGKILL)
805 socket_enter_stop_post(s, false);
806 else
807 socket_enter_dead(s, false);
808}
809
810static void socket_enter_stop_pre(Socket *s, bool success) {
811 int r;
812 assert(s);
813
814 if (!success)
815 s->failure = true;
816
5e94833f
LP
817 socket_unwatch_control_pid(s);
818
a16e1123
LP
819 s->control_command_id = SOCKET_EXEC_STOP_PRE;
820
80876c20 821 if ((s->control_command = s->exec_command[SOCKET_EXEC_STOP_PRE])) {
e537352b 822 if ((r = socket_spawn(s, s->control_command, &s->control_pid)) < 0)
034c6ed7
LP
823 goto fail;
824
80876c20
LP
825 socket_set_state(s, SOCKET_STOP_PRE);
826 } else
034c6ed7
LP
827 socket_enter_stop_post(s, true);
828
829 return;
830
831fail:
6cf6bbc2 832 log_warning("%s failed to run 'stop-pre' task: %s", s->meta.id, strerror(-r));
034c6ed7
LP
833 socket_enter_stop_post(s, false);
834}
835
e9af15c3
LP
836static void socket_enter_listening(Socket *s) {
837 int r;
838 assert(s);
839
840 if ((r = socket_watch_fds(s)) < 0) {
9e2f7c11 841 log_warning("%s failed to watch sockets: %s", s->meta.id, strerror(-r));
e9af15c3
LP
842 goto fail;
843 }
844
845 socket_set_state(s, SOCKET_LISTENING);
846 return;
847
848fail:
849 socket_enter_stop_pre(s, false);
850}
851
034c6ed7
LP
852static void socket_enter_start_post(Socket *s) {
853 int r;
854 assert(s);
855
e9af15c3 856 if ((r = socket_open_fds(s)) < 0) {
9e2f7c11 857 log_warning("%s failed to listen on sockets: %s", s->meta.id, strerror(-r));
034c6ed7
LP
858 goto fail;
859 }
860
5e94833f
LP
861 socket_unwatch_control_pid(s);
862
a16e1123
LP
863 s->control_command_id = SOCKET_EXEC_START_POST;
864
80876c20 865 if ((s->control_command = s->exec_command[SOCKET_EXEC_START_POST])) {
e537352b 866 if ((r = socket_spawn(s, s->control_command, &s->control_pid)) < 0) {
6cf6bbc2 867 log_warning("%s failed to run 'start-post' task: %s", s->meta.id, strerror(-r));
034c6ed7
LP
868 goto fail;
869 }
870
80876c20
LP
871 socket_set_state(s, SOCKET_START_POST);
872 } else
e9af15c3 873 socket_enter_listening(s);
034c6ed7
LP
874
875 return;
876
877fail:
878 socket_enter_stop_pre(s, false);
879}
880
881static void socket_enter_start_pre(Socket *s) {
882 int r;
883 assert(s);
884
5e94833f
LP
885 socket_unwatch_control_pid(s);
886
a16e1123
LP
887 s->control_command_id = SOCKET_EXEC_START_PRE;
888
80876c20 889 if ((s->control_command = s->exec_command[SOCKET_EXEC_START_PRE])) {
e537352b 890 if ((r = socket_spawn(s, s->control_command, &s->control_pid)) < 0)
034c6ed7
LP
891 goto fail;
892
80876c20
LP
893 socket_set_state(s, SOCKET_START_PRE);
894 } else
034c6ed7
LP
895 socket_enter_start_post(s);
896
897 return;
898
899fail:
6cf6bbc2 900 log_warning("%s failed to run 'start-pre' task: %s", s->meta.id, strerror(-r));
034c6ed7
LP
901 socket_enter_dead(s, false);
902}
903
4f2d528d 904static void socket_enter_running(Socket *s, int cfd) {
034c6ed7
LP
905 int r;
906
907 assert(s);
908
4f2d528d 909 if (cfd < 0) {
4cd1fbcc 910 if ((r = manager_add_job(s->meta.manager, JOB_START, UNIT(s->service), JOB_REPLACE, true, NULL)) < 0)
4f2d528d
LP
911 goto fail;
912
913 socket_set_state(s, SOCKET_RUNNING);
914 } else {
915 Unit *u;
916 char *prefix, *instance, *name;
917
6cf6bbc2
LP
918 if (s->n_connections >= s->max_connections) {
919 log_warning("Too many incoming connections (%u)", s->n_connections);
920 close_nointr_nofail(cfd);
921 return;
922 }
923
b6dbbe1c 924 if ((r = instance_from_socket(cfd, s->n_accepted++, &instance)) < 0)
4f2d528d
LP
925 goto fail;
926
4cd1fbcc 927 if (!(prefix = unit_name_to_prefix(s->meta.id))) {
4f2d528d
LP
928 free(instance);
929 r = -ENOMEM;
930 goto fail;
931 }
932
933 name = unit_name_build(prefix, instance, ".service");
934 free(prefix);
935 free(instance);
936
b6dbbe1c 937 if (!name) {
4f2d528d 938 r = -ENOMEM;
b6dbbe1c
LP
939 goto fail;
940 }
4f2d528d 941
4cd1fbcc 942 r = manager_load_unit(s->meta.manager, name, NULL, &u);
4f2d528d
LP
943 free(name);
944
945 if (r < 0)
946 goto fail;
947
6cf6bbc2 948 if ((r = service_set_socket_fd(SERVICE(u), cfd, s)) < 0)
4f2d528d
LP
949 goto fail;
950
951 cfd = -1;
952
6cf6bbc2
LP
953 s->n_connections ++;
954
4f2d528d
LP
955 if ((r = manager_add_job(u->meta.manager, JOB_START, u, JOB_REPLACE, true, NULL)) < 0)
956 goto fail;
957 }
034c6ed7 958
034c6ed7
LP
959 return;
960
961fail:
9e2f7c11 962 log_warning("%s failed to queue socket startup job: %s", s->meta.id, strerror(-r));
80876c20 963 socket_enter_stop_pre(s, false);
4f2d528d
LP
964
965 if (cfd >= 0)
966 close_nointr_nofail(cfd);
034c6ed7
LP
967}
968
969static void socket_run_next(Socket *s, bool success) {
970 int r;
971
972 assert(s);
973 assert(s->control_command);
974 assert(s->control_command->command_next);
975
976 if (!success)
977 s->failure = true;
978
5e94833f
LP
979 socket_unwatch_control_pid(s);
980
034c6ed7
LP
981 s->control_command = s->control_command->command_next;
982
e537352b 983 if ((r = socket_spawn(s, s->control_command, &s->control_pid)) < 0)
034c6ed7
LP
984 goto fail;
985
986 return;
987
988fail:
6cf6bbc2 989 log_warning("%s failed to run next task: %s", s->meta.id, strerror(-r));
80876c20
LP
990
991 if (s->state == SOCKET_START_POST)
992 socket_enter_stop_pre(s, false);
034c6ed7
LP
993 else if (s->state == SOCKET_STOP_POST)
994 socket_enter_dead(s, false);
995 else
80876c20 996 socket_enter_signal(s, SOCKET_FINAL_SIGTERM, false);
034c6ed7
LP
997}
998
87f0e418
LP
999static int socket_start(Unit *u) {
1000 Socket *s = SOCKET(u);
83c60c9f
LP
1001
1002 assert(s);
1003
034c6ed7
LP
1004 /* We cannot fulfill this request right now, try again later
1005 * please! */
1006 if (s->state == SOCKET_STOP_PRE ||
1007 s->state == SOCKET_STOP_PRE_SIGKILL ||
1008 s->state == SOCKET_STOP_PRE_SIGTERM ||
1009 s->state == SOCKET_STOP_POST ||
80876c20
LP
1010 s->state == SOCKET_FINAL_SIGTERM ||
1011 s->state == SOCKET_FINAL_SIGKILL)
034c6ed7
LP
1012 return -EAGAIN;
1013
83c60c9f
LP
1014 if (s->state == SOCKET_START_PRE ||
1015 s->state == SOCKET_START_POST)
034c6ed7 1016 return 0;
83c60c9f 1017
034c6ed7 1018 /* Cannot run this without the service being around */
4f2d528d
LP
1019 if (s->service) {
1020 if (s->service->meta.load_state != UNIT_LOADED)
1021 return -ENOENT;
1022
1023 /* If the service is alredy actvie we cannot start the
1024 * socket */
1025 if (s->service->state != SERVICE_DEAD &&
18c78fb1 1026 s->service->state != SERVICE_MAINTENANCE &&
4f2d528d
LP
1027 s->service->state != SERVICE_AUTO_RESTART)
1028 return -EBUSY;
1029 }
e537352b 1030
18c78fb1 1031 assert(s->state == SOCKET_DEAD || s->state == SOCKET_MAINTENANCE);
83c60c9f 1032
034c6ed7
LP
1033 s->failure = false;
1034 socket_enter_start_pre(s);
1035 return 0;
1036}
83c60c9f 1037
87f0e418
LP
1038static int socket_stop(Unit *u) {
1039 Socket *s = SOCKET(u);
034c6ed7
LP
1040
1041 assert(s);
1042
1043 /* We cannot fulfill this request right now, try again later
1044 * please! */
1045 if (s->state == SOCKET_START_PRE ||
1046 s->state == SOCKET_START_POST)
1047 return -EAGAIN;
83c60c9f 1048
e537352b
LP
1049 /* Already on it */
1050 if (s->state == SOCKET_STOP_PRE ||
1051 s->state == SOCKET_STOP_PRE_SIGTERM ||
1052 s->state == SOCKET_STOP_PRE_SIGKILL ||
1053 s->state == SOCKET_STOP_POST ||
80876c20
LP
1054 s->state == SOCKET_FINAL_SIGTERM ||
1055 s->state == SOCKET_FINAL_SIGTERM)
e537352b
LP
1056 return 0;
1057
034c6ed7 1058 assert(s->state == SOCKET_LISTENING || s->state == SOCKET_RUNNING);
83c60c9f 1059
034c6ed7 1060 socket_enter_stop_pre(s, true);
542563ba
LP
1061 return 0;
1062}
1063
a16e1123
LP
1064static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
1065 Socket *s = SOCKET(u);
1066 SocketPort *p;
1067 int r;
1068
1069 assert(u);
1070 assert(f);
1071 assert(fds);
1072
1073 unit_serialize_item(u, f, "state", socket_state_to_string(s->state));
1074 unit_serialize_item(u, f, "failure", yes_no(s->failure));
1075 unit_serialize_item_format(u, f, "n-accepted", "%u", s->n_accepted);
1076
1077 if (s->control_pid > 0)
5925dd3c 1078 unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) s->control_pid);
a16e1123
LP
1079
1080 if (s->control_command_id >= 0)
1081 unit_serialize_item(u, f, "control-command", socket_exec_command_to_string(s->control_command_id));
1082
1083 LIST_FOREACH(port, p, s->ports) {
1084 int copy;
1085
1086 if (p->fd < 0)
1087 continue;
1088
1089 if ((copy = fdset_put_dup(fds, p->fd)) < 0)
1090 return copy;
1091
1092 if (p->type == SOCKET_SOCKET) {
1093 char *t;
1094
1095 if ((r = socket_address_print(&p->address, &t)) < 0)
1096 return r;
1097
27ca8d7a 1098 unit_serialize_item_format(u, f, "socket", "%i %i %s", copy, p->address.type, t);
a16e1123
LP
1099 free(t);
1100 } else {
1101 assert(p->type == SOCKET_FIFO);
1102 unit_serialize_item_format(u, f, "fifo", "%i %s", copy, p->path);
1103 }
1104 }
1105
1106 return 0;
1107}
1108
1109static int socket_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
1110 Socket *s = SOCKET(u);
1111 int r;
1112
1113 assert(u);
1114 assert(key);
1115 assert(value);
1116 assert(fds);
1117
1118 if (streq(key, "state")) {
1119 SocketState state;
1120
1121 if ((state = socket_state_from_string(value)) < 0)
1122 log_debug("Failed to parse state value %s", value);
1123 else
1124 s->deserialized_state = state;
1125 } else if (streq(key, "failure")) {
1126 int b;
1127
1128 if ((b = parse_boolean(value)) < 0)
1129 log_debug("Failed to parse failure value %s", value);
1130 else
1131 s->failure = b || s->failure;
1132
1133 } else if (streq(key, "n-accepted")) {
1134 unsigned k;
1135
1136 if ((r = safe_atou(value, &k)) < 0)
1137 log_debug("Failed to parse n-accepted value %s", value);
1138 else
1139 s->n_accepted += k;
1140 } else if (streq(key, "control-pid")) {
5925dd3c 1141 pid_t pid;
a16e1123 1142
5925dd3c 1143 if ((r = parse_pid(value, &pid)) < 0)
a16e1123
LP
1144 log_debug("Failed to parse control-pid value %s", value);
1145 else
5925dd3c 1146 s->control_pid = pid;
a16e1123
LP
1147 } else if (streq(key, "control-command")) {
1148 SocketExecCommand id;
1149
1150 if ((id = socket_exec_command_from_string(value)) < 0)
1151 log_debug("Failed to parse exec-command value %s", value);
1152 else {
1153 s->control_command_id = id;
1154 s->control_command = s->exec_command[id];
1155 }
1156 } else if (streq(key, "fifo")) {
1157 int fd, skip = 0;
1158 SocketPort *p;
1159
1160 if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
1161 log_debug("Failed to parse fifo value %s", value);
1162 else {
1163
1164 LIST_FOREACH(port, p, s->ports)
1165 if (streq(p->path, value+skip))
1166 break;
1167
1168 if (p) {
1169 if (p->fd >= 0)
1170 close_nointr_nofail(p->fd);
1171 p->fd = fdset_remove(fds, fd);
1172 }
1173 }
1174
1175 } else if (streq(key, "socket")) {
27ca8d7a 1176 int fd, type, skip = 0;
a16e1123
LP
1177 SocketPort *p;
1178
27ca8d7a 1179 if (sscanf(value, "%i %i %n", &fd, &type, &skip) < 2 || fd < 0 || type < 0 || !fdset_contains(fds, fd))
a16e1123
LP
1180 log_debug("Failed to parse socket value %s", value);
1181 else {
1182
1183 LIST_FOREACH(port, p, s->ports)
27ca8d7a 1184 if (socket_address_is(&p->address, value+skip, type))
a16e1123
LP
1185 break;
1186
1187 if (p) {
1188 if (p->fd >= 0)
1189 close_nointr_nofail(p->fd);
1190 p->fd = fdset_remove(fds, fd);
1191 }
1192 }
1193
1194 } else
1195 log_debug("Unknown serialization key '%s'", key);
1196
1197 return 0;
1198}
1199
87f0e418
LP
1200static UnitActiveState socket_active_state(Unit *u) {
1201 assert(u);
5cb5a6ff 1202
acbb0225 1203 return state_translation_table[SOCKET(u)->state];
5cb5a6ff
LP
1204}
1205
10a94420
LP
1206static const char *socket_sub_state_to_string(Unit *u) {
1207 assert(u);
1208
a16e1123 1209 return socket_state_to_string(SOCKET(u)->state);
10a94420
LP
1210}
1211
6cf6bbc2
LP
1212static bool socket_check_gc(Unit *u) {
1213 Socket *s = SOCKET(u);
1214
1215 assert(u);
1216
1217 return s->n_connections > 0;
1218}
1219
acbb0225 1220static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
87f0e418 1221 Socket *s = SOCKET(u);
4f2d528d 1222 int cfd = -1;
9152c765 1223
034c6ed7 1224 assert(s);
8d567588 1225 assert(fd >= 0);
9152c765 1226
871d7de4
LP
1227 if (s->state != SOCKET_LISTENING)
1228 return;
1229
9e2f7c11 1230 log_debug("Incoming traffic on %s", u->meta.id);
9152c765 1231
4f2d528d
LP
1232 if (events != EPOLLIN) {
1233 log_error("Got invalid poll event on socket.");
8d567588 1234 goto fail;
4f2d528d
LP
1235 }
1236
cabab516 1237 if (w->socket_accept) {
4f2d528d
LP
1238 for (;;) {
1239
1240 if ((cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK)) < 0) {
1241
1242 if (errno == EINTR)
1243 continue;
1244
1245 log_error("Failed to accept socket: %m");
8d567588 1246 goto fail;
4f2d528d
LP
1247 }
1248
1249 break;
1250 }
1251 }
9152c765 1252
4f2d528d 1253 socket_enter_running(s, cfd);
8d567588
LP
1254 return;
1255
1256fail:
1257 socket_enter_stop_pre(s, false);
9152c765
LP
1258}
1259
87f0e418
LP
1260static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
1261 Socket *s = SOCKET(u);
034c6ed7 1262 bool success;
5cb5a6ff
LP
1263
1264 assert(s);
034c6ed7 1265 assert(pid >= 0);
5cb5a6ff 1266
8c47c732
LP
1267 if (pid != s->control_pid)
1268 return;
542563ba 1269
034c6ed7
LP
1270 s->control_pid = 0;
1271
8c47c732
LP
1272 success = is_clean_exit(code, status);
1273 s->failure = s->failure || !success;
1274
a16e1123
LP
1275 if (s->control_command)
1276 exec_status_fill(&s->control_command->exec_status, pid, code, status);
1277
9e2f7c11 1278 log_debug("%s control process exited, code=%s status=%i", u->meta.id, sigchld_code_to_string(code), status);
034c6ed7 1279
a16e1123
LP
1280 if (s->control_command && s->control_command->command_next && success) {
1281 log_debug("%s running next command for state %s", u->meta.id, socket_state_to_string(s->state));
034c6ed7 1282 socket_run_next(s, success);
acbb0225 1283 } else {
a16e1123
LP
1284 s->control_command = NULL;
1285 s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
1286
034c6ed7
LP
1287 /* No further commands for this step, so let's figure
1288 * out what to do next */
5cb5a6ff 1289
a16e1123 1290 log_debug("%s got final SIGCHLD for state %s", u->meta.id, socket_state_to_string(s->state));
acbb0225 1291
034c6ed7
LP
1292 switch (s->state) {
1293
1294 case SOCKET_START_PRE:
1295 if (success)
acbb0225 1296 socket_enter_start_post(s);
034c6ed7 1297 else
80876c20 1298 socket_enter_signal(s, SOCKET_FINAL_SIGTERM, false);
034c6ed7
LP
1299 break;
1300
1301 case SOCKET_START_POST:
1302 if (success)
e9af15c3 1303 socket_enter_listening(s);
034c6ed7
LP
1304 else
1305 socket_enter_stop_pre(s, false);
1306 break;
1307
1308 case SOCKET_STOP_PRE:
1309 case SOCKET_STOP_PRE_SIGTERM:
1310 case SOCKET_STOP_PRE_SIGKILL:
1311 socket_enter_stop_post(s, success);
1312 break;
1313
1314 case SOCKET_STOP_POST:
80876c20
LP
1315 case SOCKET_FINAL_SIGTERM:
1316 case SOCKET_FINAL_SIGKILL:
034c6ed7
LP
1317 socket_enter_dead(s, success);
1318 break;
1319
1320 default:
1321 assert_not_reached("Uh, control process died at wrong time.");
1322 }
1323 }
1324}
5cb5a6ff 1325
acbb0225 1326static void socket_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
87f0e418 1327 Socket *s = SOCKET(u);
5cb5a6ff 1328
034c6ed7
LP
1329 assert(s);
1330 assert(elapsed == 1);
acbb0225 1331 assert(w == &s->timer_watch);
034c6ed7
LP
1332
1333 switch (s->state) {
1334
1335 case SOCKET_START_PRE:
9e2f7c11 1336 log_warning("%s starting timed out. Terminating.", u->meta.id);
80876c20
LP
1337 socket_enter_signal(s, SOCKET_FINAL_SIGTERM, false);
1338
034c6ed7 1339 case SOCKET_START_POST:
9e2f7c11 1340 log_warning("%s starting timed out. Stopping.", u->meta.id);
034c6ed7
LP
1341 socket_enter_stop_pre(s, false);
1342 break;
1343
1344 case SOCKET_STOP_PRE:
9e2f7c11 1345 log_warning("%s stopping timed out. Terminating.", u->meta.id);
034c6ed7
LP
1346 socket_enter_signal(s, SOCKET_STOP_PRE_SIGTERM, false);
1347 break;
1348
1349 case SOCKET_STOP_PRE_SIGTERM:
9e2f7c11 1350 log_warning("%s stopping timed out. Killing.", u->meta.id);
034c6ed7
LP
1351 socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, false);
1352 break;
1353
1354 case SOCKET_STOP_PRE_SIGKILL:
9e2f7c11 1355 log_warning("%s still around after SIGKILL. Ignoring.", u->meta.id);
034c6ed7
LP
1356 socket_enter_stop_post(s, false);
1357 break;
1358
1359 case SOCKET_STOP_POST:
9e2f7c11 1360 log_warning("%s stopping timed out (2). Terminating.", u->meta.id);
80876c20 1361 socket_enter_signal(s, SOCKET_FINAL_SIGTERM, false);
034c6ed7
LP
1362 break;
1363
80876c20 1364 case SOCKET_FINAL_SIGTERM:
9e2f7c11 1365 log_warning("%s stopping timed out (2). Killing.", u->meta.id);
80876c20 1366 socket_enter_signal(s, SOCKET_FINAL_SIGKILL, false);
034c6ed7
LP
1367 break;
1368
80876c20 1369 case SOCKET_FINAL_SIGKILL:
18c78fb1 1370 log_warning("%s still around after SIGKILL (2). Entering maintenance mode.", u->meta.id);
034c6ed7
LP
1371 socket_enter_dead(s, false);
1372 break;
1373
1374 default:
1375 assert_not_reached("Timeout at wrong time.");
1376 }
5cb5a6ff
LP
1377}
1378
44d8db9e
LP
1379int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds) {
1380 int *rfds;
1381 unsigned rn_fds, k;
1382 SocketPort *p;
1383
1384 assert(s);
1385 assert(fds);
1386 assert(n_fds);
1387
1388 /* Called from the service code for requesting our fds */
1389
1390 rn_fds = 0;
1391 LIST_FOREACH(port, p, s->ports)
1392 if (p->fd >= 0)
1393 rn_fds++;
1394
1395 if (!(rfds = new(int, rn_fds)) < 0)
1396 return -ENOMEM;
1397
1398 k = 0;
1399 LIST_FOREACH(port, p, s->ports)
1400 if (p->fd >= 0)
1401 rfds[k++] = p->fd;
1402
1403 assert(k == rn_fds);
1404
1405 *fds = rfds;
1406 *n_fds = rn_fds;
1407
1408 return 0;
1409}
1410
ceee3d82
LP
1411void socket_notify_service_dead(Socket *s) {
1412 assert(s);
1413
6cf6bbc2
LP
1414 /* The service is dead. Dang!
1415 *
1416 * This is strictly for one-instance-for-all-connections
1417 * services. */
ceee3d82
LP
1418
1419 if (s->state == SOCKET_RUNNING) {
9e2f7c11 1420 log_debug("%s got notified about service death.", s->meta.id);
ceee3d82
LP
1421 socket_enter_listening(s);
1422 }
1423}
1424
6cf6bbc2
LP
1425void socket_connection_unref(Socket *s) {
1426 assert(s);
1427
1428 /* The service is dead. Yay!
1429 *
1430 * This is strictly for one-onstance-per-connection
1431 * services. */
1432
1433 assert(s->n_connections > 0);
1434 s->n_connections--;
1435
1436 log_debug("%s: One connection closed, %u left.", s->meta.id, s->n_connections);
1437}
1438
a16e1123
LP
1439static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
1440 [SOCKET_DEAD] = "dead",
1441 [SOCKET_START_PRE] = "start-pre",
1442 [SOCKET_START_POST] = "start-post",
1443 [SOCKET_LISTENING] = "listening",
1444 [SOCKET_RUNNING] = "running",
1445 [SOCKET_STOP_PRE] = "stop-pre",
1446 [SOCKET_STOP_PRE_SIGTERM] = "stop-pre-sigterm",
1447 [SOCKET_STOP_PRE_SIGKILL] = "stop-pre-sigkill",
1448 [SOCKET_STOP_POST] = "stop-post",
1449 [SOCKET_FINAL_SIGTERM] = "final-sigterm",
1450 [SOCKET_FINAL_SIGKILL] = "final-sigkill",
18c78fb1 1451 [SOCKET_MAINTENANCE] = "maintenance"
a16e1123
LP
1452};
1453
1454DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState);
1455
1456static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
1457 [SOCKET_EXEC_START_PRE] = "StartPre",
1458 [SOCKET_EXEC_START_POST] = "StartPost",
1459 [SOCKET_EXEC_STOP_PRE] = "StopPre",
1460 [SOCKET_EXEC_STOP_POST] = "StopPost"
1461};
1462
1463DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand);
1464
87f0e418 1465const UnitVTable socket_vtable = {
5cb5a6ff
LP
1466 .suffix = ".socket",
1467
034c6ed7
LP
1468 .init = socket_init,
1469 .done = socket_done,
a16e1123
LP
1470 .load = socket_load,
1471
1472 .coldplug = socket_coldplug,
034c6ed7 1473
5cb5a6ff
LP
1474 .dump = socket_dump,
1475
542563ba
LP
1476 .start = socket_start,
1477 .stop = socket_stop,
5cb5a6ff 1478
a16e1123
LP
1479 .serialize = socket_serialize,
1480 .deserialize_item = socket_deserialize_item,
1481
5cb5a6ff 1482 .active_state = socket_active_state,
10a94420 1483 .sub_state_to_string = socket_sub_state_to_string,
5cb5a6ff 1484
6cf6bbc2
LP
1485 .check_gc = socket_check_gc,
1486
9152c765 1487 .fd_event = socket_fd_event,
034c6ed7 1488 .sigchld_event = socket_sigchld_event,
4139c1b2
LP
1489 .timer_event = socket_timer_event,
1490
1491 .bus_message_handler = bus_socket_message_handler
5cb5a6ff 1492};