6 #include "connections.h"
8 #include "configfile.h"
11 #include "network_write.h"
12 #include "sys-socket.h"
14 #include <sys/types.h>
25 network_accept_tcp_nagle_disable (const int fd
)
27 static int noinherit_tcpnodelay
= -1;
30 if (!noinherit_tcpnodelay
) /* TCP_NODELAY inherited from listen socket */
33 if (noinherit_tcpnodelay
< 0) {
34 socklen_t optlen
= sizeof(opt
);
35 if (0 == getsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, &opt
, &optlen
)) {
36 noinherit_tcpnodelay
= !opt
;
37 if (opt
) /* TCP_NODELAY inherited from listen socket */
43 (void)setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, &opt
, sizeof(opt
));
46 static handler_t
network_server_handle_fdevent(server
*srv
, void *context
, int revents
) {
47 server_socket
*srv_socket
= (server_socket
*)context
;
53 if (0 == (revents
& FDEVENT_IN
)) {
54 log_error_write(srv
, __FILE__
, __LINE__
, "sdd",
55 "strange event for server socket",
61 /* accept()s at most 100 connections directly
63 * we jump out after 100 to give the waiting connections a chance */
64 for (loops
= 0; loops
< 100 && NULL
!= (con
= connection_accept(srv
, srv_socket
)); loops
++) {
65 connection_state_machine(srv
, con
);
70 static void network_host_normalize_addr_str(buffer
*host
, sock_addr
*addr
) {
72 sock_addr_stringify_append_buffer(host
, addr
);
75 static int network_host_parse_addr(server
*srv
, sock_addr
*addr
, socklen_t
*addr_len
, buffer
*host
, int use_ipv6
) {
79 sa_family_t family
= use_ipv6
? AF_INET6
: AF_INET
;
80 unsigned int port
= srv
->srvconf
.port
;
81 if (buffer_string_is_empty(host
)) {
82 log_error_write(srv
, __FILE__
, __LINE__
, "s", "value of $SERVER[\"socket\"] must not be empty");
88 return (1 == sock_addr_from_str_hints(srv
,addr
,addr_len
,h
,AF_UNIX
,0))
92 log_error_write(srv
, __FILE__
, __LINE__
, "s",
93 "ERROR: Unix Domain sockets are not supported.");
97 buffer_copy_buffer(srv
->tmp_buf
, host
);
98 h
= srv
->tmp_buf
->ptr
;
101 if ((h
= strchr(h
, ']'))) {
103 if (*h
== ':') colon
= h
;
104 } /*(else should not happen; validated in configparser.y)*/
105 h
= srv
->tmp_buf
->ptr
+1;
108 colon
= strrchr(h
, ':');
112 port
= strtol(colon
, NULL
, 10);
113 if (port
== 0 || port
> 65535) {
114 log_error_write(srv
, __FILE__
, __LINE__
, "sd",
115 "port not set or out of range:", port
);
119 chost
= *h
? h
: family
== AF_INET
? "0.0.0.0" : "::";
120 if (1 != sock_addr_from_str_hints(srv
,addr
,addr_len
,chost
,family
,port
)) {
126 static int network_server_init(server
*srv
, buffer
*host_token
, size_t sidx
, int stdin_fd
) {
127 server_socket
*srv_socket
;
129 specific_config
*s
= srv
->config_storage
[sidx
];
130 socklen_t addr_len
= sizeof(sock_addr
);
137 WORD wVersionRequested
;
140 wVersionRequested
= MAKEWORD( 2, 2 );
142 err
= WSAStartup( wVersionRequested
, &wsaData
);
144 /* Tell the user that we could not find a usable */
150 if (buffer_string_is_empty(host_token
)) {
151 log_error_write(srv
, __FILE__
, __LINE__
, "s", "value of $SERVER[\"socket\"] must not be empty");
155 /* check if we already know this socket, and if yes, don't init it
156 * (optimization: check strings here to filter out exact matches;
157 * binary addresses are matched further below) */
158 for (size_t i
= 0; i
< srv
->srv_sockets
.used
; ++i
) {
159 if (buffer_is_equal(srv
->srv_sockets
.ptr
[i
]->srv_token
, host_token
)) {
160 buffer_copy_buffer(host_token
, srv
->srv_sockets
.ptr
[i
]->srv_token
);
165 host
= host_token
->ptr
;
166 if ((s
->use_ipv6
&& (*host
== '\0' || *host
== ':')) || (host
[0] == '[' && host
[1] == ']')) {
167 log_error_write(srv
, __FILE__
, __LINE__
, "s", "warning: please use server.use-ipv6 only for hostnames, not without server.bind / empty address; your config will break if the kernel default for IPV6_V6ONLY changes");
169 if (*host
== '[') s
->use_ipv6
= 1;
171 memset(&addr
, 0, sizeof(addr
));
172 if (-1 != stdin_fd
) {
173 if (0 == sidx
&& srv
->srv_sockets
.used
> 0) {
174 close(stdin_fd
);/*(graceful restart listening to "/dev/stdin")*/
177 if (-1 == getsockname(stdin_fd
, (struct sockaddr
*)&addr
, &addr_len
)) {
178 log_error_write(srv
, __FILE__
, __LINE__
, "ss",
179 "getsockname()", strerror(errno
));
182 } else if (0 != network_host_parse_addr(srv
, &addr
, &addr_len
, host_token
, s
->use_ipv6
)) {
186 family
= sock_addr_get_family(&addr
);
189 if (*host
!= '\0' && AF_INET6
== family
) {
193 log_error_write(srv
, __FILE__
, __LINE__
, "s", "warning: server.set-v6only will be removed soon, update your config to have different sockets for ipv4 and ipv6");
198 network_host_normalize_addr_str(host_token
, &addr
);
199 host
= host_token
->ptr
;
201 if (srv
->srvconf
.preflight_check
) {
205 /* check if we already know this socket (after potential DNS resolution), and if yes, don't init it */
206 for (size_t i
= 0; i
< srv
->srv_sockets
.used
; ++i
) {
207 if (0 == memcmp(&srv
->srv_sockets
.ptr
[i
]->addr
, &addr
, sizeof(addr
))) {
212 srv_socket
= calloc(1, sizeof(*srv_socket
));
213 force_assert(NULL
!= srv_socket
);
214 memcpy(&srv_socket
->addr
, &addr
, addr_len
);
216 srv_socket
->fde_ndx
= -1;
217 srv_socket
->sidx
= sidx
;
218 srv_socket
->is_ssl
= s
->ssl_enabled
;
219 srv_socket
->srv_token
= buffer_init_buffer(host_token
);
221 if (srv
->srv_sockets
.size
== 0) {
222 srv
->srv_sockets
.size
= 4;
223 srv
->srv_sockets
.used
= 0;
224 srv
->srv_sockets
.ptr
= malloc(srv
->srv_sockets
.size
* sizeof(server_socket
*));
225 force_assert(NULL
!= srv
->srv_sockets
.ptr
);
226 } else if (srv
->srv_sockets
.used
== srv
->srv_sockets
.size
) {
227 srv
->srv_sockets
.size
+= 4;
228 srv
->srv_sockets
.ptr
= realloc(srv
->srv_sockets
.ptr
, srv
->srv_sockets
.size
* sizeof(server_socket
*));
229 force_assert(NULL
!= srv
->srv_sockets
.ptr
);
231 srv
->srv_sockets
.ptr
[srv
->srv_sockets
.used
++] = srv_socket
;
233 if (srv
->sockets_disabled
) { /* lighttpd -1 (one-shot mode) */
237 if (-1 != stdin_fd
) {
238 srv_socket
->fd
= stdin_fd
;
239 if (-1 == fdevent_fcntl_set_nb_cloexec(srv
->ev
, stdin_fd
)) {
240 log_error_write(srv
, __FILE__
, __LINE__
, "ss", "fcntl:", strerror(errno
));
245 if (AF_UNIX
== family
) {
246 /* check if the socket exists and try to connect to it. */
247 force_assert(host
); /*(static analysis hint)*/
248 if (-1 == (srv_socket
->fd
= fdevent_socket_cloexec(AF_UNIX
, SOCK_STREAM
, 0))) {
249 log_error_write(srv
, __FILE__
, __LINE__
, "ss", "socket failed:", strerror(errno
));
252 if (0 == connect(srv_socket
->fd
, (struct sockaddr
*) &(srv_socket
->addr
), addr_len
)) {
253 log_error_write(srv
, __FILE__
, __LINE__
, "ss",
254 "server socket is still in use:",
269 log_error_write(srv
, __FILE__
, __LINE__
, "sds",
270 "testing socket failed:",
271 host
, strerror(errno
));
276 fdevent_fcntl_set_nb(srv
->ev
, srv_socket
->fd
);
280 if (-1 == (srv_socket
->fd
= fdevent_socket_nb_cloexec(family
, SOCK_STREAM
, IPPROTO_TCP
))) {
281 log_error_write(srv
, __FILE__
, __LINE__
, "ss", "socket failed:", strerror(errno
));
287 if (set_v6only
&& -1 == stdin_fd
) {
289 if (-1 == setsockopt(srv_socket
->fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &val
, sizeof(val
))) {
290 log_error_write(srv
, __FILE__
, __LINE__
, "ss", "setsockopt(IPV6_V6ONLY) failed:", strerror(errno
));
297 srv
->cur_fds
= srv_socket
->fd
;
299 if (fdevent_set_so_reuseaddr(srv_socket
->fd
, 1) < 0) {
300 log_error_write(srv
, __FILE__
, __LINE__
, "ss", "setsockopt(SO_REUSEADDR) failed:", strerror(errno
));
304 if (family
!= AF_UNIX
) {
305 if (fdevent_set_tcp_nodelay(srv_socket
->fd
, 1) < 0) {
306 log_error_write(srv
, __FILE__
, __LINE__
, "ss", "setsockopt(TCP_NODELAY) failed:", strerror(errno
));
311 if (-1 != stdin_fd
) { } else
312 if (0 != bind(srv_socket
->fd
, (struct sockaddr
*) &(srv_socket
->addr
), addr_len
)) {
313 log_error_write(srv
, __FILE__
, __LINE__
, "sss",
314 "can't bind to socket:", host
, strerror(errno
));
318 if (-1 != stdin_fd
) { } else
319 if (AF_UNIX
== family
&& !buffer_string_is_empty(s
->socket_perms
)) {
321 for (char *str
= s
->socket_perms
->ptr
; *str
; ++str
) {
325 if (0 != m
&& -1 == chmod(host
, m
)) {
326 log_error_write(srv
, __FILE__
, __LINE__
, "sssbss", "chmod(\"", host
, "\", ", s
->socket_perms
, "):", strerror(errno
));
330 if (-1 != stdin_fd
) { } else
331 if (-1 == listen(srv_socket
->fd
, s
->listen_backlog
)) {
332 log_error_write(srv
, __FILE__
, __LINE__
, "ss", "listen failed: ", strerror(errno
));
336 if (s
->ssl_enabled
) {
337 #ifdef TCP_DEFER_ACCEPT
338 } else if (s
->defer_accept
) {
339 int v
= s
->defer_accept
;
340 if (-1 == setsockopt(srv_socket
->fd
, IPPROTO_TCP
, TCP_DEFER_ACCEPT
, &v
, sizeof(v
))) {
341 log_error_write(srv
, __FILE__
, __LINE__
, "ss", "can't set TCP_DEFER_ACCEPT: ", strerror(errno
));
344 #if defined(__FreeBSD__) || defined(__NetBSD__) \
345 || defined(__OpenBSD__) || defined(__DragonFly__)
346 } else if (!buffer_is_empty(s
->bsd_accept_filter
)
347 && (buffer_is_equal_string(s
->bsd_accept_filter
, CONST_STR_LEN("httpready"))
348 || buffer_is_equal_string(s
->bsd_accept_filter
, CONST_STR_LEN("dataready")))) {
349 #ifdef SO_ACCEPTFILTER
350 /* FreeBSD accf_http filter */
351 struct accept_filter_arg afa
;
352 memset(&afa
, 0, sizeof(afa
));
353 strncpy(afa
.af_name
, s
->bsd_accept_filter
->ptr
, sizeof(afa
.af_name
));
354 if (setsockopt(srv_socket
->fd
, SOL_SOCKET
, SO_ACCEPTFILTER
, &afa
, sizeof(afa
)) < 0) {
355 if (errno
!= ENOENT
) {
356 log_error_write(srv
, __FILE__
, __LINE__
, "SBss", "can't set accept-filter '", s
->bsd_accept_filter
, "':", strerror(errno
));
366 int network_close(server
*srv
) {
368 for (i
= 0; i
< srv
->srv_sockets
.used
; i
++) {
369 server_socket
*srv_socket
= srv
->srv_sockets
.ptr
[i
];
370 if (srv_socket
->fd
!= -1) {
371 network_unregister_sock(srv
, srv_socket
);
372 close(srv_socket
->fd
);
375 buffer_free(srv_socket
->srv_token
);
380 free(srv
->srv_sockets
.ptr
);
381 srv
->srv_sockets
.ptr
= NULL
;
382 srv
->srv_sockets
.used
= 0;
383 srv
->srv_sockets
.size
= 0;
388 int network_init(server
*srv
, int stdin_fd
) {
390 if (0 != network_write_init(srv
)) return -1;
394 buffer
*b
= buffer_init();
395 buffer_copy_buffer(b
, srv
->srvconf
.bindhost
);
396 if (b
->ptr
[0] != '/') { /*(skip adding port if unix socket path)*/
397 buffer_append_string_len(b
, CONST_STR_LEN(":"));
398 buffer_append_int(b
, srv
->srvconf
.port
);
401 rc
= network_server_init(srv
, b
, 0, stdin_fd
);
403 if (0 != rc
) return -1;
406 /* check for $SERVER["socket"] */
407 for (i
= 1; i
< srv
->config_context
->used
; i
++) {
408 data_config
*dc
= (data_config
*)srv
->config_context
->data
[i
];
411 if (COMP_SERVER_SOCKET
!= dc
->comp
) continue;
413 if (dc
->cond
== CONFIG_COND_NE
) {
414 socklen_t addr_len
= sizeof(sock_addr
);
416 if (0 != network_host_parse_addr(srv
, &addr
, &addr_len
, dc
->string
, srv
->config_storage
[i
]->use_ipv6
)) {
419 network_host_normalize_addr_str(dc
->string
, &addr
);
423 if (dc
->cond
!= CONFIG_COND_EQ
) continue;
425 if (0 != network_server_init(srv
, dc
->string
, i
, -1)) return -1;
431 void network_unregister_sock(server
*srv
, server_socket
*srv_socket
) {
432 if (-1 == srv_socket
->fd
|| -1 == srv_socket
->fde_ndx
) return;
433 fdevent_event_del(srv
->ev
, &srv_socket
->fde_ndx
, srv_socket
->fd
);
434 fdevent_unregister(srv
->ev
, srv_socket
->fd
);
437 int network_register_fdevents(server
*srv
) {
440 if (-1 == fdevent_reset(srv
->ev
)) {
444 if (srv
->sockets_disabled
) return 0; /* lighttpd -1 (one-shot mode) */
446 /* register fdevents after reset */
447 for (i
= 0; i
< srv
->srv_sockets
.used
; i
++) {
448 server_socket
*srv_socket
= srv
->srv_sockets
.ptr
[i
];
450 fdevent_register(srv
->ev
, srv_socket
->fd
, network_server_handle_fdevent
, srv_socket
);
451 fdevent_event_set(srv
->ev
, &(srv_socket
->fde_ndx
), srv_socket
->fd
, FDEVENT_IN
);