1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
14 static const NameActiveState state_table[_SOCKET_STATE_MAX] = {
15 [SOCKET_DEAD] = NAME_INACTIVE,
16 [SOCKET_START_PRE] = NAME_ACTIVATING,
17 [SOCKET_START_POST] = NAME_ACTIVATING,
18 [SOCKET_LISTENING] = NAME_ACTIVE,
19 [SOCKET_RUNNING] = NAME_ACTIVE,
20 [SOCKET_STOP_PRE] = NAME_DEACTIVATING,
21 [SOCKET_STOP_POST] = NAME_DEACTIVATING,
22 [SOCKET_MAINTAINANCE] = NAME_INACTIVE,
25 static int socket_load(Name *n) {
26 Socket *s = SOCKET(n);
28 exec_context_defaults(&s->exec_context);
29 s->backlog = SOMAXCONN;
31 return name_load_fragment_and_dropin(n);
34 static const char* listen_lookup(int type) {
36 if (type == SOCK_STREAM)
37 return "ListenStream";
38 else if (type == SOCK_DGRAM)
39 return "ListenDatagram";
40 else if (type == SOCK_SEQPACKET)
41 return "ListenSequentialPacket";
43 assert_not_reached("Unkown socket type");
47 static void socket_dump(Name *n, FILE *f, const char *prefix) {
49 static const char* const state_table[_SOCKET_STATE_MAX] = {
50 [SOCKET_DEAD] = "dead",
51 [SOCKET_START_PRE] = "start-pre",
52 [SOCKET_START_POST] = "start-post",
53 [SOCKET_LISTENING] = "listening",
54 [SOCKET_RUNNING] = "running",
55 [SOCKET_STOP_PRE] = "stop-pre",
56 [SOCKET_STOP_POST] = "stop-post",
57 [SOCKET_MAINTAINANCE] = "maintainance"
60 static const char* const command_table[_SOCKET_EXEC_MAX] = {
61 [SOCKET_EXEC_START_PRE] = "StartPre",
62 [SOCKET_EXEC_START_POST] = "StartPost",
63 [SOCKET_EXEC_STOP_PRE] = "StopPre",
64 [SOCKET_EXEC_STOP_POST] = "StopPost"
68 Socket *s = SOCKET(n);
74 "%sSocket State: %s\n"
75 "%sBindIPv6Only: %s\n"
77 prefix, state_table[s->state],
78 prefix, yes_no(s->bind_ipv6_only),
81 LIST_FOREACH(p, s->ports) {
83 if (p->type == SOCKET_SOCKET) {
88 if ((r = socket_address_print(&p->address, &k)) < 0)
93 fprintf(f, "%s%s: %s\n", prefix, listen_lookup(p->address.type), k);
96 fprintf(f, "%sListenFIFO: %s\n", prefix, p->path);
99 exec_context_dump(&s->exec_context, f, prefix);
101 for (c = 0; c < _SOCKET_EXEC_MAX; c++) {
104 LIST_FOREACH(i, s->exec_command[c])
105 fprintf(f, "%s%s: %s\n", prefix, command_table[c], i->path);
109 static void socket_set_state(Socket *s, SocketState state) {
110 SocketState old_state;
113 old_state = s->state;
116 name_notify(NAME(s), state_table[old_state], state_table[s->state]);
119 static void close_fds(Socket *s) {
124 LIST_FOREACH(p, s->ports) {
128 name_unwatch_fd(NAME(s), p->fd);
129 assert_se(close_nointr(p->fd) >= 0);
135 static int socket_start(Name *n) {
136 Socket *s = SOCKET(n);
142 if (s->state == SOCKET_START_PRE ||
143 s->state == SOCKET_START_POST)
146 if (s->state == SOCKET_LISTENING ||
147 s->state == SOCKET_RUNNING)
150 if (s->state == SOCKET_STOP_PRE ||
151 s->state == SOCKET_STOP_POST)
154 assert(s->state == SOCKET_DEAD || s->state == SOCKET_MAINTAINANCE);
156 LIST_FOREACH(p, s->ports) {
160 if (p->type == SOCKET_SOCKET) {
162 if ((r = socket_address_listen(&p->address, s->backlog, s->bind_ipv6_only, &p->fd)) < 0)
167 assert(p->type == SOCKET_FIFO);
169 if (mkfifo(p->path, 0666 & ~s->exec_context.umask) < 0 && errno != EEXIST) {
174 if ((p->fd = open(p->path, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW)) < 0) {
179 if (fstat(p->fd, &st) < 0) {
184 /* FIXME verify user, access mode */
186 if (!S_ISFIFO(st.st_mode)) {
192 if ((r = name_watch_fd(n, p->fd, POLLIN)) < 0)
196 socket_set_state(s, SOCKET_LISTENING);
203 socket_set_state(s, SOCKET_MAINTAINANCE);
208 static int socket_stop(Name *n) {
209 Socket *s = SOCKET(n);
213 if (s->state == SOCKET_START_PRE ||
214 s->state == SOCKET_START_POST)
217 if (s->state == SOCKET_DEAD ||
218 s->state == SOCKET_MAINTAINANCE)
221 if (s->state == SOCKET_STOP_PRE ||
222 s->state == SOCKET_STOP_POST)
225 assert(s->state == SOCKET_LISTENING || s->state == SOCKET_RUNNING);
229 socket_set_state(s, SOCKET_DEAD);
234 static NameActiveState socket_active_state(Name *n) {
237 return state_table[SOCKET(n)->state];
240 static void socket_fd_event(Name *n, int fd, uint32_t events) {
241 Socket *s = SOCKET(n);
245 if (events != POLLIN)
248 log_info("POLLIN on %s", name_id(n));
254 socket_set_state(s, SOCKET_MAINTAINANCE);
257 static void socket_free_hook(Name *n) {
259 Socket *s = SOCKET(n);
264 while ((p = s->ports)) {
265 LIST_REMOVE(SocketPort, s->ports, p);
273 exec_context_free(&s->exec_context);
275 for (c = 0; c < _SOCKET_EXEC_MAX; c++)
276 exec_command_free_list(s->exec_command[c]);
279 s->service->socket = NULL;
282 const NameVTable socket_vtable = {
288 .start = socket_start,
292 .active_state = socket_active_state,
294 .fd_event = socket_fd_event,
296 .free_hook = socket_free_hook