2 * Copyright (C) 2013 Red Hat Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
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
41 #include <sys/types.h>
42 #include <sys/socket.h>
51 #include "nbdkit-plugin.h"
55 bind_unix_socket (size_t *nr_socks
)
59 struct sockaddr_un addr
;
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);
72 sock
= socket (AF_UNIX
, SOCK_STREAM
|SOCK_CLOEXEC
, 0);
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) {
86 if (listen (sock
, SOMAXCONN
) == -1) {
91 ret
= malloc (sizeof (int));
99 debug ("bound to unix socket %s", unixsocket
);
105 bind_tcpip_socket (size_t *nr_socks
)
107 struct addrinfo
*ai
= NULL
;
108 struct addrinfo hints
;
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
);
123 fprintf (stderr
, "%s: getaddrinfo: %s: %s: %s",
125 ipaddr
? ipaddr
: "<any>",
133 for (a
= ai
; a
!= NULL
; a
= a
->ai_next
) {
136 sock
= socket (a
->ai_family
, a
->ai_socktype
, a
->ai_protocol
);
143 if (setsockopt (sock
, SOL_SOCKET
, SO_REUSEADDR
, &opt
, sizeof opt
) == -1)
144 perror ("setsockopt: SO_REUSEADDR");
147 if (a
->ai_family
== PF_INET6
) {
148 if (setsockopt (sock
, IPPROTO_IPV6
, IPV6_V6ONLY
, &opt
, sizeof opt
) == -1)
149 perror ("setsockopt: IPv6 only");
153 if (bind (sock
, a
->ai_addr
, a
->ai_addrlen
) == -1) {
154 if (errno
== EADDRINUSE
) {
163 if (listen (sock
, SOMAXCONN
) == -1) {
169 socks
= realloc (socks
, sizeof (int) * (*nr_socks
));
174 socks
[*nr_socks
- 1] = sock
;
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
));
185 debug ("bound to IP address %s:%s (%zu socket(s))",
186 ipaddr
? ipaddr
: "<any>", port
, *nr_socks
);
192 free_listening_sockets (int *socks
, size_t nr_socks
)
196 for (i
= 0; i
< nr_socks
; ++i
)
204 struct sockaddr addr
;
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
);
226 accept_connection (int listen_sock
)
229 pthread_attr_t attrs
;
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
;
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
)
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
);
255 fprintf (stderr
, "%s: pthread_create: %s\n", program_name
, strerror (err
));
256 close (thread_data
.sock
);
260 /* If the thread starts successfully, then it is responsible for
261 * closing the socket.
266 accept_incoming_connections (int *socks
, size_t nr_socks
)
268 struct pollfd fds
[nr_socks
];
273 for (i
= 0; i
< nr_socks
; ++i
) {
274 fds
[i
].fd
= socks
[i
];
275 fds
[i
].events
= POLLIN
;
279 r
= poll (fds
, nr_socks
, -1);
281 if (errno
== EINTR
|| errno
== EAGAIN
)
287 for (i
= 0; i
< nr_socks
; ++i
) {
288 if (fds
[i
].revents
& POLLIN
)
289 accept_connection (fds
[i
].fd
);