Ignore test files.
[nbdkit/ericb.git] / src / sockets.c
blob458cd9281f8ea8a6dc542f00b7d8917ceebbe9a2
1 /* nbdkit
2 * Copyright (C) 2013 Red Hat Inc.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * * Neither the name of Red Hat nor the names of its contributors may be
17 * used to endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include <config.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <stdbool.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <sys/un.h>
44 #include <netdb.h>
45 #include <poll.h>
46 #include <errno.h>
47 #include <assert.h>
49 #include <pthread.h>
51 #include "nbdkit-plugin.h"
52 #include "internal.h"
54 int *
55 bind_unix_socket (size_t *nr_socks)
57 size_t len;
58 int sock;
59 struct sockaddr_un addr;
60 int *ret;
62 assert (unixsocket);
63 assert (unixsocket[0] == '/');
65 len = strlen (unixsocket);
66 if (len >= UNIX_PATH_MAX) {
67 fprintf (stderr, "%s: -U option: path too long (max is %d) bytes",
68 program_name, UNIX_PATH_MAX-1);
69 exit (EXIT_FAILURE);
72 sock = socket (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
73 if (sock == -1) {
74 perror ("socket");
75 exit (EXIT_FAILURE);
78 addr.sun_family = AF_UNIX;
79 memcpy (addr.sun_path, unixsocket, len+1 /* trailing \0 */);
81 if (bind (sock, (struct sockaddr *) &addr, sizeof addr) == -1) {
82 perror (unixsocket);
83 exit (EXIT_FAILURE);
86 if (listen (sock, SOMAXCONN) == -1) {
87 perror ("listen");
88 exit (EXIT_FAILURE);
91 ret = malloc (sizeof (int));
92 if (!ret) {
93 perror ("malloc");
94 exit (EXIT_FAILURE);
96 ret[0] = sock;
97 *nr_socks = 1;
99 debug ("bound to unix socket %s", unixsocket);
101 return ret;
104 int *
105 bind_tcpip_socket (size_t *nr_socks)
107 struct addrinfo *ai = NULL;
108 struct addrinfo hints;
109 struct addrinfo *a;
110 int err, opt;
111 int *socks = NULL;
112 bool addr_in_use;
114 if (port == NULL)
115 port = "10809";
117 memset (&hints, 0, sizeof hints);
118 hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
119 hints.ai_socktype = SOCK_STREAM;
121 err = getaddrinfo (ipaddr, port, &hints, &ai);
122 if (err != 0) {
123 fprintf (stderr, "%s: getaddrinfo: %s: %s: %s",
124 program_name,
125 ipaddr ? ipaddr : "<any>",
126 port,
127 gai_strerror (err));
128 exit (EXIT_FAILURE);
131 *nr_socks = 0;
133 for (a = ai; a != NULL; a = a->ai_next) {
134 int sock;
136 sock = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
137 if (sock == -1) {
138 perror ("socket");
139 exit (EXIT_FAILURE);
142 opt = 1;
143 if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt) == -1)
144 perror ("setsockopt: SO_REUSEADDR");
146 #ifdef IPV6_V6ONLY
147 if (a->ai_family == PF_INET6) {
148 if (setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof opt) == -1)
149 perror ("setsockopt: IPv6 only");
151 #endif
153 if (bind (sock, a->ai_addr, a->ai_addrlen) == -1) {
154 if (errno == EADDRINUSE) {
155 addr_in_use = true;
156 close (sock);
157 continue;
159 perror ("bind");
160 exit (EXIT_FAILURE);
163 if (listen (sock, SOMAXCONN) == -1) {
164 perror ("listen");
165 exit (EXIT_FAILURE);
168 (*nr_socks)++;
169 socks = realloc (socks, sizeof (int) * (*nr_socks));
170 if (!socks) {
171 perror ("realloc");
172 exit (EXIT_FAILURE);
174 socks[*nr_socks - 1] = sock;
177 freeaddrinfo (ai);
179 if (*nr_socks == 0 && addr_in_use) {
180 fprintf (stderr, "%s: unable to bind to any sockets: %s\n",
181 program_name, strerror (EADDRINUSE));
182 exit (EXIT_FAILURE);
185 debug ("bound to IP address %s:%s (%zu socket(s))",
186 ipaddr ? ipaddr : "<any>", port, *nr_socks);
188 return socks;
191 void
192 free_listening_sockets (int *socks, size_t nr_socks)
194 size_t i;
196 for (i = 0; i < nr_socks; ++i)
197 close (socks[i]);
198 free (socks);
201 struct thread_data {
202 int sock;
203 size_t instance_num;
204 struct sockaddr addr;
205 socklen_t addrlen;
208 static void *
209 start_thread (void *datav)
211 struct thread_data *data = datav;
213 debug ("accepted connection");
215 /* Set thread-local data. */
216 tls_new_server_thread ();
217 tls_set_instance_num (data->instance_num);
218 tls_set_sockaddr (&data->addr, data->addrlen);
220 handle_single_connection (data->sock, data->sock);
222 return NULL;
225 static void
226 accept_connection (int listen_sock)
228 int err;
229 pthread_attr_t attrs;
230 pthread_t thread;
231 struct thread_data thread_data;
232 static size_t instance_num = 1;
234 thread_data.instance_num = instance_num++;
235 thread_data.addrlen = sizeof thread_data.addr;
236 again:
237 thread_data.sock = accept (listen_sock,
238 &thread_data.addr, &thread_data.addrlen);
239 if (thread_data.sock == -1) {
240 if (errno == EINTR || errno == EAGAIN)
241 goto again;
242 perror ("accept");
243 return;
246 /* Start a thread to handle this connection. Note we always do this
247 * even for non-threaded plugins. There are mutexes in plugins.c
248 * which ensure that non-threaded plugins are handled correctly.
250 pthread_attr_init (&attrs);
251 pthread_attr_setdetachstate (&attrs, PTHREAD_CREATE_DETACHED);
252 err = pthread_create (&thread, &attrs, start_thread, &thread_data);
253 pthread_attr_destroy (&attrs);
254 if (err != 0) {
255 fprintf (stderr, "%s: pthread_create: %s\n", program_name, strerror (err));
256 close (thread_data.sock);
257 return;
260 /* If the thread starts successfully, then it is responsible for
261 * closing the socket.
265 void
266 accept_incoming_connections (int *socks, size_t nr_socks)
268 struct pollfd fds[nr_socks];
269 size_t i;
270 int r;
272 while (!quit) {
273 for (i = 0; i < nr_socks; ++i) {
274 fds[i].fd = socks[i];
275 fds[i].events = POLLIN;
276 fds[i].revents = 0;
279 r = poll (fds, nr_socks, -1);
280 if (r == -1) {
281 if (errno == EINTR || errno == EAGAIN)
282 continue;
283 perror ("poll");
284 exit (EXIT_FAILURE);
287 for (i = 0; i < nr_socks; ++i) {
288 if (fds[i].revents & POLLIN)
289 accept_connection (fds[i].fd);