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