server: Change unreachable oldstyle error to assert
[nbdkit/ericb.git] / server / sockets.c
blobdfaa3ea139f31e1ea1f50889166092e2dcc02e7c
1 /* nbdkit
2 * Copyright (C) 2013-2019 Red Hat Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 #include <config.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdbool.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <poll.h>
41 #include <errno.h>
42 #include <assert.h>
43 #include <sys/types.h>
44 #include <sys/socket.h>
45 #include <sys/un.h>
46 #include <netinet/in.h>
47 #include <netinet/tcp.h>
48 #include <netdb.h>
50 #ifdef HAVE_LIBSELINUX
51 #include <selinux/selinux.h>
52 #endif
54 #include <pthread.h>
56 #include "internal.h"
57 #include "utils.h"
59 static void
60 set_selinux_label (void)
62 if (selinux_label) {
63 #ifdef HAVE_LIBSELINUX
64 if (setsockcreatecon_raw (selinux_label) == -1) {
65 perror ("selinux-label: setsockcreatecon_raw");
66 exit (EXIT_FAILURE);
68 #else
69 fprintf (stderr,
70 "%s: --selinux-label option used, but "
71 "this binary was compiled without SELinux support\n",
72 program_name);
73 exit (EXIT_FAILURE);
74 #endif
78 static void
79 clear_selinux_label (void)
81 #ifdef HAVE_LIBSELINUX
82 if (selinux_label) {
83 if (setsockcreatecon_raw (NULL) == -1) {
84 perror ("selinux-label: setsockcreatecon_raw(NULL)");
85 exit (EXIT_FAILURE);
88 #endif
91 int *
92 bind_unix_socket (size_t *nr_socks)
94 size_t len;
95 int sock;
96 struct sockaddr_un addr;
97 int *ret;
99 assert (unixsocket);
100 assert (unixsocket[0] == '/');
102 len = strlen (unixsocket);
103 if (len >= UNIX_PATH_MAX) {
104 fprintf (stderr, "%s: -U: path too long: length %zu > max %d bytes\n",
105 program_name, len, UNIX_PATH_MAX-1);
106 exit (EXIT_FAILURE);
109 set_selinux_label ();
111 #ifdef SOCK_CLOEXEC
112 sock = socket (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
113 #else
114 /* Fortunately, this code is only run at startup, so there is no
115 * risk of the fd leaking to a plugin's fork()
117 sock = set_cloexec (socket (AF_UNIX, SOCK_STREAM, 0));
118 #endif
119 if (sock == -1) {
120 perror ("bind_unix_socket: socket");
121 exit (EXIT_FAILURE);
124 addr.sun_family = AF_UNIX;
125 memcpy (addr.sun_path, unixsocket, len+1 /* trailing \0 */);
127 if (bind (sock, (struct sockaddr *) &addr, sizeof addr) == -1) {
128 perror (unixsocket);
129 exit (EXIT_FAILURE);
132 if (listen (sock, SOMAXCONN) == -1) {
133 perror ("listen");
134 exit (EXIT_FAILURE);
137 clear_selinux_label ();
139 ret = malloc (sizeof (int));
140 if (!ret) {
141 perror ("malloc");
142 exit (EXIT_FAILURE);
144 ret[0] = sock;
145 *nr_socks = 1;
147 debug ("bound to unix socket %s", unixsocket);
149 return ret;
152 int *
153 bind_tcpip_socket (size_t *nr_socks)
155 struct addrinfo *ai = NULL;
156 struct addrinfo hints;
157 struct addrinfo *a;
158 int err, opt;
159 int *socks = NULL;
160 bool addr_in_use = false;
162 if (port == NULL)
163 port = "10809";
165 memset (&hints, 0, sizeof hints);
166 hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
167 hints.ai_socktype = SOCK_STREAM;
169 err = getaddrinfo (ipaddr, port, &hints, &ai);
170 if (err != 0) {
171 fprintf (stderr, "%s: getaddrinfo: %s: %s: %s",
172 program_name,
173 ipaddr ? ipaddr : "<any>",
174 port,
175 gai_strerror (err));
176 exit (EXIT_FAILURE);
179 *nr_socks = 0;
181 for (a = ai; a != NULL; a = a->ai_next) {
182 int sock;
184 set_selinux_label ();
186 #ifdef SOCK_CLOEXEC
187 sock = socket (a->ai_family, a->ai_socktype | SOCK_CLOEXEC, a->ai_protocol);
188 #else
189 /* Fortunately, this code is only run at startup, so there is no
190 * risk of the fd leaking to a plugin's fork()
192 sock = set_cloexec (socket (a->ai_family, a->ai_socktype, a->ai_protocol));
193 #endif
194 if (sock == -1) {
195 perror ("bind_tcpip_socket: socket");
196 exit (EXIT_FAILURE);
199 opt = 1;
200 if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt) == -1)
201 perror ("setsockopt: SO_REUSEADDR");
203 #ifdef IPV6_V6ONLY
204 if (a->ai_family == PF_INET6) {
205 if (setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof opt) == -1)
206 perror ("setsockopt: IPv6 only");
208 #endif
210 if (bind (sock, a->ai_addr, a->ai_addrlen) == -1) {
211 if (errno == EADDRINUSE) {
212 addr_in_use = true;
213 close (sock);
214 continue;
216 perror ("bind");
217 exit (EXIT_FAILURE);
220 if (listen (sock, SOMAXCONN) == -1) {
221 perror ("listen");
222 exit (EXIT_FAILURE);
225 clear_selinux_label ();
227 (*nr_socks)++;
228 socks = realloc (socks, sizeof (int) * (*nr_socks));
229 if (!socks) {
230 perror ("realloc");
231 exit (EXIT_FAILURE);
233 socks[*nr_socks - 1] = sock;
236 freeaddrinfo (ai);
238 if (*nr_socks == 0 && addr_in_use) {
239 fprintf (stderr, "%s: unable to bind to any sockets: %s\n",
240 program_name, strerror (EADDRINUSE));
241 exit (EXIT_FAILURE);
244 debug ("bound to IP address %s:%s (%zu socket(s))",
245 ipaddr ? ipaddr : "<any>", port, *nr_socks);
247 return socks;
250 void
251 free_listening_sockets (int *socks, size_t nr_socks)
253 size_t i;
255 for (i = 0; i < nr_socks; ++i)
256 close (socks[i]);
257 free (socks);
260 struct thread_data {
261 int sock;
262 size_t instance_num;
263 struct sockaddr addr;
264 socklen_t addrlen;
267 static void *
268 start_thread (void *datav)
270 struct thread_data *data = datav;
272 debug ("accepted connection");
274 /* Set thread-local data. */
275 threadlocal_new_server_thread ();
276 threadlocal_set_instance_num (data->instance_num);
277 threadlocal_set_sockaddr (&data->addr, data->addrlen);
279 handle_single_connection (data->sock, data->sock);
281 free (data);
282 return NULL;
285 static void
286 accept_connection (int listen_sock)
288 int err;
289 pthread_attr_t attrs;
290 pthread_t thread;
291 struct thread_data *thread_data;
292 static size_t instance_num = 1;
293 const int flag = 1;
295 thread_data = malloc (sizeof *thread_data);
296 if (!thread_data) {
297 perror ("malloc");
298 return;
301 thread_data->instance_num = instance_num++;
302 thread_data->addrlen = sizeof thread_data->addr;
303 again:
304 #ifdef HAVE_ACCEPT4
305 thread_data->sock = accept4 (listen_sock,
306 &thread_data->addr, &thread_data->addrlen,
307 SOCK_CLOEXEC);
308 #else
309 /* If we were fully parallel, then this function could be accepting
310 * connections in one thread while another thread could be in a
311 * plugin trying to fork. But plugins.c forced thread_model to
312 * serialize_all_requests when it detects a lack of atomic CLOEXEC,
313 * at which point, we can use a mutex to ensure we aren't accepting
314 * until the plugin is not running, making non-atomicity okay.
316 assert (backend->thread_model (backend) <=
317 NBDKIT_THREAD_MODEL_SERIALIZE_ALL_REQUESTS);
318 lock_request (NULL);
319 thread_data->sock = set_cloexec (accept (listen_sock,
320 &thread_data->addr,
321 &thread_data->addrlen));
322 unlock_request (NULL);
323 #endif
324 if (thread_data->sock == -1) {
325 if (errno == EINTR || errno == EAGAIN)
326 goto again;
327 perror ("accept");
328 free (thread_data);
329 return;
332 /* Disable Nagle's algorithm on this socket. However we don't want
333 * to fail if this doesn't work.
335 setsockopt (thread_data->sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof flag);
337 /* Start a thread to handle this connection. Note we always do this
338 * even for non-threaded plugins. There are mutexes in plugins.c
339 * which ensure that non-threaded plugins are handled correctly.
341 pthread_attr_init (&attrs);
342 pthread_attr_setdetachstate (&attrs, PTHREAD_CREATE_DETACHED);
343 err = pthread_create (&thread, &attrs, start_thread, thread_data);
344 pthread_attr_destroy (&attrs);
345 if (err != 0) {
346 fprintf (stderr, "%s: pthread_create: %s\n", program_name, strerror (err));
347 close (thread_data->sock);
348 free (thread_data);
349 return;
352 /* If the thread starts successfully, then it is responsible for
353 * closing the socket and freeing thread_data.
357 /* Check the list of sockets plus quit_fd until a POLLIN event occurs
358 * on any of them.
360 * If POLLIN occurs on quit_fd do nothing except returning early
361 * (don't call accept_connection in this case).
363 * If POLLIN occurs on one of the sockets, call
364 * accept_connection (socks[i]) on each of them.
366 static void
367 check_sockets_and_quit_fd (int *socks, size_t nr_socks)
369 size_t i;
370 int r;
372 CLEANUP_FREE struct pollfd *fds =
373 malloc (sizeof (struct pollfd) * (nr_socks+1));
374 if (fds == NULL) {
375 perror ("malloc");
376 exit (EXIT_FAILURE);
379 for (i = 0; i < nr_socks; ++i) {
380 fds[i].fd = socks[i];
381 fds[i].events = POLLIN;
382 fds[i].revents = 0;
384 fds[nr_socks].fd = quit_fd;
385 fds[nr_socks].events = POLLIN;
386 fds[nr_socks].revents = 0;
388 r = poll (fds, nr_socks + 1, -1);
389 if (r == -1) {
390 if (errno == EINTR || errno == EAGAIN)
391 return;
392 perror ("poll");
393 exit (EXIT_FAILURE);
396 /* We don't even have to read quit_fd - just knowing that it has
397 * data means the signal handler ran, so we are ready to quit the
398 * loop.
400 if (fds[nr_socks].revents & POLLIN)
401 return;
403 for (i = 0; i < nr_socks; ++i) {
404 if (fds[i].revents & POLLIN)
405 accept_connection (socks[i]);
409 void
410 accept_incoming_connections (int *socks, size_t nr_socks)
412 while (!quit)
413 check_sockets_and_quit_fd (socks, nr_socks);