1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
13 static const NameActiveState state_table
[_SOCKET_STATE_MAX
] = {
14 [SOCKET_DEAD
] = NAME_INACTIVE
,
15 [SOCKET_START_PRE
] = NAME_ACTIVATING
,
16 [SOCKET_START_POST
] = NAME_ACTIVATING
,
17 [SOCKET_LISTENING
] = NAME_ACTIVE
,
18 [SOCKET_RUNNING
] = NAME_ACTIVE
,
19 [SOCKET_STOP_PRE
] = NAME_DEACTIVATING
,
20 [SOCKET_STOP_POST
] = NAME_DEACTIVATING
,
21 [SOCKET_MAINTAINANCE
] = NAME_INACTIVE
,
24 static int socket_load(Name
*n
) {
25 Socket
*s
= SOCKET(n
);
27 exec_context_defaults(&s
->exec_context
);
28 s
->backlog
= SOMAXCONN
;
30 return name_load_fragment_and_dropin(n
);
33 static const char* listen_lookup(int type
) {
35 if (type
== SOCK_STREAM
)
36 return "ListenStream";
37 else if (type
== SOCK_DGRAM
)
38 return "ListenDatagram";
39 else if (type
== SOCK_SEQPACKET
)
40 return "ListenSequentialPacket";
42 assert_not_reached("Unkown socket type");
46 static void socket_dump(Name
*n
, FILE *f
, const char *prefix
) {
48 static const char* const state_table
[_SOCKET_STATE_MAX
] = {
49 [SOCKET_DEAD
] = "dead",
50 [SOCKET_START_PRE
] = "start-pre",
51 [SOCKET_START_POST
] = "start-post",
52 [SOCKET_LISTENING
] = "listening",
53 [SOCKET_RUNNING
] = "running",
54 [SOCKET_STOP_PRE
] = "stop-pre",
55 [SOCKET_STOP_POST
] = "stop-post",
56 [SOCKET_MAINTAINANCE
] = "maintainance"
59 static const char* const command_table
[_SOCKET_EXEC_MAX
] = {
60 [SOCKET_EXEC_START_PRE
] = "StartPre",
61 [SOCKET_EXEC_START_POST
] = "StartPost",
62 [SOCKET_EXEC_STOP_PRE
] = "StopPre",
63 [SOCKET_EXEC_STOP_POST
] = "StopPost"
67 Socket
*s
= SOCKET(n
);
73 "%sSocket State: %s\n"
74 "%sBindIPv6Only: %s\n"
76 prefix
, state_table
[s
->state
],
77 prefix
, yes_no(s
->bind_ipv6_only
),
80 LIST_FOREACH(p
, s
->ports
) {
82 if (p
->type
== SOCKET_SOCKET
) {
87 if ((r
= socket_address_print(&p
->address
, &k
)) < 0)
92 fprintf(f
, "%s%s: %s\n", prefix
, listen_lookup(p
->address
.type
), k
);
95 fprintf(f
, "%sListenFIFO: %s\n", prefix
, p
->path
);
98 exec_context_dump(&s
->exec_context
, f
, prefix
);
100 for (c
= 0; c
< _SOCKET_EXEC_MAX
; c
++) {
103 LIST_FOREACH(i
, s
->exec_command
[c
])
104 fprintf(f
, "%s%s: %s\n", prefix
, command_table
[c
], i
->path
);
108 static void socket_set_state(Socket
*s
, SocketState state
) {
109 SocketState old_state
;
112 old_state
= s
->state
;
115 name_notify(NAME(s
), state_table
[old_state
], state_table
[s
->state
]);
118 static void close_fds(Socket
*s
) {
123 LIST_FOREACH(p
, s
->ports
) {
132 static int socket_start(Name
*n
) {
133 Socket
*s
= SOCKET(n
);
139 if (s
->state
== SOCKET_START_PRE
||
140 s
->state
== SOCKET_START_POST
)
143 if (s
->state
== SOCKET_LISTENING
||
144 s
->state
== SOCKET_RUNNING
)
147 if (s
->state
== SOCKET_STOP_PRE
||
148 s
->state
== SOCKET_STOP_POST
)
151 assert(s
->state
== SOCKET_DEAD
|| s
->state
== SOCKET_MAINTAINANCE
);
153 LIST_FOREACH(p
, s
->ports
) {
157 if (p
->type
== SOCKET_SOCKET
) {
159 if ((r
= socket_address_listen(&p
->address
, s
->backlog
, s
->bind_ipv6_only
, &p
->fd
)) < 0)
164 assert(p
->type
== SOCKET_FIFO
);
166 if (mkfifo(p
->path
, 0666 & ~s
->exec_context
.umask
) < 0 && errno
!= EEXIST
) {
171 if ((p
->fd
= open(p
->path
, O_RDWR
|O_CLOEXEC
|O_NOCTTY
|O_NONBLOCK
|O_NOFOLLOW
)) < 0) {
176 if (fstat(p
->fd
, &st
) < 0) {
181 /* FIXME verify user, access mode */
183 if (!S_ISFIFO(st
.st_mode
)) {
190 socket_set_state(s
, SOCKET_LISTENING
);
197 socket_set_state(s
, SOCKET_MAINTAINANCE
);
202 static int socket_stop(Name
*n
) {
203 Socket
*s
= SOCKET(n
);
207 if (s
->state
== SOCKET_START_PRE
||
208 s
->state
== SOCKET_START_POST
)
211 if (s
->state
== SOCKET_DEAD
||
212 s
->state
== SOCKET_MAINTAINANCE
)
215 if (s
->state
== SOCKET_STOP_PRE
||
216 s
->state
== SOCKET_STOP_POST
)
219 assert(s
->state
== SOCKET_LISTENING
|| s
->state
== SOCKET_RUNNING
);
223 socket_set_state(s
, SOCKET_DEAD
);
228 static NameActiveState
socket_active_state(Name
*n
) {
231 return state_table
[SOCKET(n
)->state
];
234 static void socket_free_hook(Name
*n
) {
236 Socket
*s
= SOCKET(n
);
241 while ((p
= s
->ports
)) {
242 LIST_REMOVE(SocketPort
, s
->ports
, p
);
250 exec_context_free(&s
->exec_context
);
252 for (c
= 0; c
< _SOCKET_EXEC_MAX
; c
++)
253 exec_command_free_list(s
->exec_command
[c
]);
256 s
->service
->socket
= NULL
;
259 const NameVTable socket_vtable
= {
265 .start
= socket_start
,
269 .active_state
= socket_active_state
,
271 .free_hook
= socket_free_hook