xref: /lighttpd1.4/src/network.c (revision 54c07b54)
1 #include "first.h"
2 
3 #include "network.h"
4 #include "base.h"
5 #include "fdevent.h"
6 #include "log.h"
7 #include "connections.h"
8 #include "plugin.h"
9 #include "sock_addr.h"
10 
11 #include "network_write.h"
12 #include "sys-socket.h"
13 
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include "sys-time.h"
17 
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <stdlib.h>
23 
24 void
25 network_accept_tcp_nagle_disable (const int fd)
26 {
27     static int noinherit_tcpnodelay = -1;
28     int opt;
29 
30     if (!noinherit_tcpnodelay) /* TCP_NODELAY inherited from listen socket */
31         return;
32 
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 */
38                 return;
39         }
40     }
41 
42     opt = 1;
43     (void)setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
44 }
45 
46 static handler_t network_server_handle_fdevent(void *context, int revents) {
47     const server_socket * const srv_socket = (server_socket *)context;
48     server * const srv = srv_socket->srv;
49 
50     if (0 == (revents & FDEVENT_IN)) {
51         log_error(srv->errh, __FILE__, __LINE__,
52           "strange event for server socket %d %d", srv_socket->fd, revents);
53         return HANDLER_ERROR;
54     }
55 
56     /* accept()s at most 100 new connections before
57      * jumping out to process events on other connections */
58     int loops = (int)srv->lim_conns;
59     if (loops > 100)
60         loops = 100;
61     else if (loops <= 0)
62         return HANDLER_GO_ON;
63 
64     const int nagle_disable =
65       (sock_addr_get_family(&srv_socket->addr) != AF_UNIX);
66 
67     sock_addr addr;
68     size_t addrlen; /*(size_t intentional; not socklen_t)*/
69     do {
70         addrlen = sizeof(addr);
71         int fd = fdevent_accept_listenfd(srv_socket->fd,
72                                          (struct sockaddr *)&addr, &addrlen);
73         if (-1 == fd) break;
74 
75         if (nagle_disable)
76             network_accept_tcp_nagle_disable(fd);
77         else if (addrlen <= 2) /*(AF_UNIX if !nagle_disable)*/
78             memcpy(addr.un.sun_path, BUF_PTR_LEN(srv_socket->srv_token)+1);
79 
80         connection *con = connection_accepted(srv, srv_socket, &addr, fd);
81         if (__builtin_expect( (!con), 0)) return HANDLER_GO_ON;
82         connection_state_machine(con);
83     } while (--loops);
84 
85     if (loops) {
86         switch (errno) {
87           case EAGAIN:
88          #if EWOULDBLOCK != EAGAIN
89           case EWOULDBLOCK:
90          #endif
91           case EINTR:
92           case ECONNABORTED:
93           case EMFILE:
94             break;
95           default:
96             log_perror(srv->errh, __FILE__, __LINE__, "accept()");
97         }
98     }
99 
100     return HANDLER_GO_ON;
101 }
102 
103 static void network_host_normalize_addr_str(buffer *host, sock_addr *addr) {
104     buffer_clear(host);
105     sock_addr_stringify_append_buffer(host, addr);
106 }
107 
108 static int network_host_parse_addr(server *srv, sock_addr *addr, socklen_t *addr_len, buffer *host, int use_ipv6) {
109     char *h;
110     char *colon = NULL;
111     const char *chost;
112     sa_family_t family = use_ipv6 ? AF_INET6 : AF_INET;
113     unsigned int port = srv->srvconf.port;
114     if (buffer_is_blank(host)) {
115         log_error(srv->errh, __FILE__, __LINE__,
116           "value of $SERVER[\"socket\"] must not be empty");
117         return -1;
118     }
119     h = host->ptr;
120     if (h[0] == '/') {
121       #ifdef HAVE_SYS_UN_H
122         return (1 ==
123                 sock_addr_from_str_hints(addr,addr_len,h,AF_UNIX,0,srv->errh))
124           ? 0
125           : -1;
126       #else
127         log_error(srv, __FILE__, __LINE__,
128           "ERROR: Unix Domain sockets are not supported.");
129         return -1;
130       #endif
131     }
132     buffer * const tb = srv->tmp_buf;
133     buffer_copy_buffer(tb, host);
134     h = tb->ptr;
135     if (h[0] == '[') {
136         family = AF_INET6;
137         if ((h = strchr(h, ']'))) {
138             *h++ = '\0';
139             if (*h == ':') colon = h;
140         } /*(else should not happen; validated in configparser.y)*/
141         h = tb->ptr+1;
142     }
143     else {
144         colon = strrchr(h, ':');
145     }
146     if (colon) {
147         *colon++ = '\0';
148         port = (unsigned int)strtol(colon, NULL, 10);
149         if (port == 0 || port > 65535) {
150             log_error(srv->errh, __FILE__, __LINE__,
151               "port not set or out of range: %u", port);
152             return -1;
153         }
154     }
155     if (h[0] == '*' && h[1] == '\0') {
156         family = AF_INET;
157         ++h;
158     }
159     chost = *h ? h : family == AF_INET ? "0.0.0.0" : "::";
160     if (1 !=
161         sock_addr_from_str_hints(addr,addr_len,chost,family,port,srv->errh)) {
162         return -1;
163     }
164     return 0;
165 }
166 
167 static void network_srv_sockets_append(server *srv, server_socket *srv_socket) {
168 	if (srv->srv_sockets.used == srv->srv_sockets.size) {
169 		srv->srv_sockets.size += 4;
170 		srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket*));
171 		force_assert(NULL != srv->srv_sockets.ptr);
172 	}
173 
174 	srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
175 }
176 
177 typedef struct {
178     /* global or per-socket config; not patched per connection */
179     int listen_backlog;
180     unsigned char ssl_enabled;
181     unsigned char use_ipv6;
182     unsigned char set_v6only; /* set_v6only is only a temporary option */
183     unsigned char defer_accept;
184     int8_t v4mapped;
185     const buffer *socket_perms;
186     const buffer *bsd_accept_filter;
187 } network_socket_config;
188 
189 typedef struct {
190     PLUGIN_DATA;
191     network_socket_config defaults;
192     network_socket_config conf;
193 } network_plugin_data;
194 
195 static void network_merge_config_cpv(network_socket_config * const pconf, const config_plugin_value_t * const cpv) {
196     switch (cpv->k_id) { /* index into static config_plugin_keys_t cpk[] */
197       case 0: /* ssl.engine */
198         pconf->ssl_enabled = (0 != cpv->v.u);
199         break;
200       case 1: /* server.listen-backlog */
201         pconf->listen_backlog = (int)cpv->v.u;
202         break;
203       case 2: /* server.socket-perms */
204         pconf->socket_perms = cpv->v.b;
205         break;
206       case 3: /* server.bsd-accept-filter */
207         pconf->bsd_accept_filter = cpv->v.b;
208         break;
209       case 4: /* server.defer-accept */
210         pconf->defer_accept = (0 != cpv->v.u);
211         break;
212       case 5: /* server.use-ipv6 */
213         pconf->use_ipv6 = (0 != cpv->v.u);
214         break;
215       case 6: /* server.set-v6only */
216         pconf->set_v6only = (0 != cpv->v.u);
217         break;
218       case 7: /* server.v4mapped */
219         pconf->v4mapped = (0 != cpv->v.u);
220         break;
221       default:/* should not happen */
222         return;
223     }
224 }
225 
226 static void network_merge_config(network_socket_config * const pconf, const config_plugin_value_t *cpv) {
227     do {
228         network_merge_config_cpv(pconf, cpv);
229     } while ((++cpv)->k_id != -1);
230 }
231 
232 __attribute_pure__
233 static uint8_t network_srv_token_colon (const buffer * const b) {
234     const char *colon = NULL;
235     const char * const p = b->ptr;
236     if (*p == '[') {
237         colon = strstr(p, "]:");
238         if (colon) ++colon;
239     }
240     else if (*p != '/') {
241         colon = strchr(p, ':');
242     }
243     return colon ? (uint8_t)(colon - p) : (uint8_t)buffer_clen(b);
244 }
245 
246 static int network_server_init(server *srv, network_socket_config *s, buffer *host_token, size_t sidx, int stdin_fd) {
247 	server_socket *srv_socket;
248 	const char *host;
249 	socklen_t addr_len = sizeof(sock_addr);
250 	sock_addr addr;
251 	int family = 0;
252 	int set_v6only = 0;
253 
254 	if (buffer_is_blank(host_token)) {
255 		log_error(srv->errh, __FILE__, __LINE__,
256 		  "value of $SERVER[\"socket\"] must not be empty");
257 		return -1;
258 	}
259 
260 	/* check if we already know this socket, and if yes, don't init it
261 	 * (optimization: check strings here to filter out exact matches;
262 	 *  binary addresses are matched further below) */
263 	for (uint32_t i = 0; i < srv->srv_sockets.used; ++i) {
264 		if (buffer_is_equal(srv->srv_sockets.ptr[i]->srv_token, host_token)) {
265 			return 0;
266 		}
267 	}
268 
269 	host = host_token->ptr;
270 	if ((s->use_ipv6 && (*host == '\0' || *host == ':')) || (host[0] == '[' && host[1] == ']')) {
271 		log_error(srv->errh, __FILE__, __LINE__,
272 		  "warning: please use server.use-ipv6 only for hostnames, "
273 		  "not without server.bind / empty address; your config will "
274 		  "break if the kernel default for IPV6_V6ONLY changes");
275 	}
276 	if (*host == '[') s->use_ipv6 = 1;
277 
278 	memset(&addr, 0, sizeof(addr));
279 	if (-1 != stdin_fd) {
280 		if (-1 == getsockname(stdin_fd, (struct sockaddr *)&addr, &addr_len)) {
281 			log_perror(srv->errh, __FILE__, __LINE__, "getsockname()");
282 			return -1;
283 		}
284 	} else if (0 != network_host_parse_addr(srv, &addr, &addr_len, host_token, s->use_ipv6)) {
285 		return -1;
286 	}
287 
288 	family = sock_addr_get_family(&addr);
289 
290       #ifdef HAVE_IPV6
291 	if (*host != '\0' && AF_INET6 == family) {
292 		if (s->set_v6only) {
293 			set_v6only = 1;
294 		} else {
295 			log_error(srv->errh, __FILE__, __LINE__,
296 			  "warning: server.set-v6only will be removed soon, "
297 			  "update your config to have different sockets for ipv4 and ipv6");
298 		}
299 	}
300 	if (AF_INET6 == family && -1 != s->v4mapped) { /*(configured; -1 is unset)*/
301 		set_v6only = (s->v4mapped ? -1 : 1);
302 	}
303       #endif
304 
305 	network_host_normalize_addr_str(host_token, &addr);
306 	host = host_token->ptr;
307 
308 	if (srv->srvconf.preflight_check) {
309 		return 0;
310 	}
311 
312 	/* check if we already know this socket (after potential DNS resolution), and if yes, don't init it */
313 	for (uint32_t i = 0; i < srv->srv_sockets.used; ++i) {
314 		if (0 == memcmp(&srv->srv_sockets.ptr[i]->addr, &addr, sizeof(addr))) {
315 			return 0;
316 		}
317 	}
318 
319 	srv_socket = calloc(1, sizeof(*srv_socket));
320 	force_assert(NULL != srv_socket);
321 	memcpy(&srv_socket->addr, &addr, addr_len);
322 	srv_socket->fd = -1;
323 	srv_socket->sidx = sidx;
324 	srv_socket->is_ssl = s->ssl_enabled;
325 	srv_socket->srv = srv;
326 	buffer_copy_buffer((srv_socket->srv_token = buffer_init()), host_token);
327 	srv_socket->srv_token_colon =
328 	  network_srv_token_colon(srv_socket->srv_token);
329 
330 	network_srv_sockets_append(srv, srv_socket);
331 
332 	if (srv->sockets_disabled) { /* lighttpd -1 (one-shot mode) */
333 		return 0;
334 	}
335 
336 	if (srv->srvconf.systemd_socket_activation) {
337 		for (uint32_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
338 			if (0 != memcmp(&srv->srv_sockets_inherited.ptr[i]->addr, &srv_socket->addr, addr_len)) continue;
339 			if ((unsigned short)~0u == srv->srv_sockets_inherited.ptr[i]->sidx) {
340 				srv->srv_sockets_inherited.ptr[i]->sidx = sidx;
341 			}
342 			stdin_fd = srv->srv_sockets_inherited.ptr[i]->fd;
343 			break;
344 		}
345 	}
346 
347 	if (-1 != stdin_fd) {
348 		srv_socket->fd = stdin_fd;
349 		if (-1 == fdevent_fcntl_set_nb_cloexec(stdin_fd)) {
350 			log_perror(srv->errh, __FILE__, __LINE__, "fcntl");
351 			return -1;
352 		}
353 	} else
354 #ifdef HAVE_SYS_UN_H
355 	if (AF_UNIX == family) {
356 		/* check if the socket exists and try to connect to it. */
357 		force_assert(host); /*(static analysis hint)*/
358 		if (-1 == (srv_socket->fd = fdevent_socket_cloexec(AF_UNIX, SOCK_STREAM, 0))) {
359 			log_perror(srv->errh, __FILE__, __LINE__, "socket");
360 			return -1;
361 		}
362 		if (0 == connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
363 			log_error(srv->errh, __FILE__, __LINE__,
364 			  "server socket is still in use: %s", host);
365 			return -1;
366 		}
367 
368 		/* connect failed */
369 		switch(errno) {
370 		case ECONNREFUSED:
371 			unlink(host);
372 			break;
373 		case ENOENT:
374 			break;
375 		default:
376 			log_perror(srv->errh, __FILE__, __LINE__,
377 			  "testing socket failed: %s", host);
378 			return -1;
379 		}
380 
381 		if (-1 == fdevent_fcntl_set_nb(srv_socket->fd)) {
382 			log_perror(srv->errh, __FILE__, __LINE__, "fcntl");
383 			return -1;
384 		}
385 	} else
386 #endif
387 	{
388 		if (-1 == (srv_socket->fd = fdevent_socket_nb_cloexec(family, SOCK_STREAM, IPPROTO_TCP))) {
389 			log_perror(srv->errh, __FILE__, __LINE__, "socket");
390 			return -1;
391 		}
392 
393 #ifdef HAVE_IPV6
394 		if (set_v6only) {
395 				int val = (set_v6only > 0);
396 				if (-1 == setsockopt(srv_socket->fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val))) {
397 					log_perror(srv->errh, __FILE__, __LINE__, "setsockopt(IPV6_V6ONLY)");
398 					return -1;
399 				}
400 		}
401 #endif
402 	}
403 
404 	/* */
405 	srv->cur_fds = srv_socket->fd;
406 
407 	if (fdevent_set_so_reuseaddr(srv_socket->fd, 1) < 0) {
408 		log_perror(srv->errh, __FILE__, __LINE__, "setsockopt(SO_REUSEADDR)");
409 		return -1;
410 	}
411 
412 	if (family != AF_UNIX) {
413 		if (fdevent_set_tcp_nodelay(srv_socket->fd, 1) < 0) {
414 			log_perror(srv->errh, __FILE__, __LINE__, "setsockopt(TCP_NODELAY)");
415 			return -1;
416 		}
417 	}
418 
419 	if (-1 != stdin_fd) { } else
420 	if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
421 		log_perror(srv->errh, __FILE__, __LINE__,
422 		  "can't bind to socket: %s", host);
423 		return -1;
424 	}
425 
426 	if (-1 != stdin_fd) { } else
427 	if (AF_UNIX == family && s->socket_perms) {
428 		mode_t m = 0;
429 		for (char *str = s->socket_perms->ptr; *str; ++str) {
430 			m <<= 3;
431 			m |= (*str - '0');
432 		}
433 		if (0 != m && -1 == chmod(host, m)) {
434 			log_perror(srv->errh, __FILE__, __LINE__,
435 			  "chmod(\"%s\", %s)", host, s->socket_perms->ptr);
436 			return -1;
437 		}
438 	}
439 
440 	if (-1 != stdin_fd) { } else
441 	if (-1 == listen(srv_socket->fd, s->listen_backlog)) {
442 		log_perror(srv->errh, __FILE__, __LINE__, "listen");
443 		return -1;
444 	}
445 
446 	if (s->ssl_enabled) {
447 	}
448 #ifdef TCP_DEFER_ACCEPT
449 	else if (s->defer_accept) {
450 		int v = s->defer_accept;
451 		if (-1 == setsockopt(srv_socket->fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &v, sizeof(v))) {
452 			log_perror(srv->errh, __FILE__, __LINE__, "can't set TCP_DEFER_ACCEPT");
453 		}
454 	}
455 #endif
456 #if defined(__FreeBSD__) || defined(__NetBSD__) \
457  || defined(__OpenBSD__) || defined(__DragonFly__)
458 #ifdef SO_ACCEPTFILTER
459 	else if (s->bsd_accept_filter
460 		   && (buffer_is_equal_string(s->bsd_accept_filter, CONST_STR_LEN("httpready"))
461 			|| buffer_is_equal_string(s->bsd_accept_filter, CONST_STR_LEN("dataready")))) {
462 		/* FreeBSD accf_http filter */
463 		struct accept_filter_arg afa;
464 		memset(&afa, 0, sizeof(afa));
465 		strncpy(afa.af_name, s->bsd_accept_filter->ptr, sizeof(afa.af_name)-1);
466 		if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)) < 0) {
467 			if (errno != ENOENT) {
468 				log_perror(srv->errh, __FILE__, __LINE__,
469 				  "can't set accept-filter '%s'", s->bsd_accept_filter->ptr);
470 			}
471 		}
472 	}
473 #endif
474 #endif
475 
476 	return 0;
477 }
478 
479 int network_close(server *srv) {
480 	for (uint32_t i = 0; i < srv->srv_sockets.used; ++i) {
481 		server_socket *srv_socket = srv->srv_sockets.ptr[i];
482 		if (srv_socket->fd != -1) {
483 			network_unregister_sock(srv, srv_socket);
484 			close(srv_socket->fd);
485 		}
486 
487 		buffer_free(srv_socket->srv_token);
488 
489 		free(srv_socket);
490 	}
491 
492 	free(srv->srv_sockets.ptr);
493 	srv->srv_sockets.ptr = NULL;
494 	srv->srv_sockets.used = 0;
495 	srv->srv_sockets.size = 0;
496 
497 	for (uint32_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
498 		server_socket *srv_socket = srv->srv_sockets_inherited.ptr[i];
499 		if (srv_socket->fd != -1 && srv_socket->sidx != (unsigned short)~0u) {
500 			close(srv_socket->fd);
501 		}
502 
503 		buffer_free(srv_socket->srv_token);
504 
505 		free(srv_socket);
506 	}
507 
508 	free(srv->srv_sockets_inherited.ptr);
509 	srv->srv_sockets_inherited.ptr = NULL;
510 	srv->srv_sockets_inherited.used = 0;
511 	srv->srv_sockets_inherited.size = 0;
512 
513 	return 0;
514 }
515 
516 void network_socket_activation_to_env (server * const srv) {
517     /* set up listening sockets for systemd socket activation
518      * and ensure FD_CLOEXEC flag is not set on listen fds */
519     int fd = 3; /* #define SD_LISTEN_FDS_START 3 */
520     for (uint32_t n = 0, i; n < srv->srv_sockets.used; ++n) {
521         server_socket *srv_socket = srv->srv_sockets.ptr[n];
522         if (srv_socket->fd < fd) continue;
523         if (srv_socket->fd == fd) {
524             fdevent_clrfd_cloexec(fd);
525             ++fd;
526             continue;
527         }
528         /* (expecting ordered list, but check if fd is later in list)*/
529         for (i = n+1; i < srv->srv_sockets.used; ++i) {
530             if (fd == srv->srv_sockets.ptr[i]->fd)
531                 break;
532         }
533         if (i < srv->srv_sockets.used) {
534             fdevent_clrfd_cloexec(fd);
535             ++fd;
536             --n; /* loop to reprocess this entry */
537             continue;
538         }
539 
540         /* dup2() removes FD_CLOEXEC on newfd */
541         if (fd != dup2(srv_socket->fd, fd)) continue;
542         ++fd;
543         /* old fd will be closed upon execv() due to its FD_CLOEXEC flag
544          * (if not already closed by another dup2() over it) */
545     }
546     fd -= 3; /* now num fds; #define SD_LISTEN_FDS_START 3 */
547     if (0 == fd) return; /*(no active sockets?)*/
548     buffer * const tb = srv->tmp_buf;
549     buffer_clear(tb);
550     buffer_append_int(tb, fd);
551     setenv("LISTEN_FDS", tb->ptr, 1);
552     buffer_clear(tb);
553     buffer_append_int(tb, srv->pid); /* getpid() */
554     setenv("LISTEN_PID", tb->ptr, 1);
555 }
556 
557 static int network_socket_activation_nfds(server *srv, network_socket_config *s, int nfds) {
558     buffer *host = buffer_init();
559     socklen_t addr_len;
560     sock_addr addr;
561     int rc = 0;
562     nfds += 3; /* #define SD_LISTEN_FDS_START 3 */
563     for (int fd = 3; fd < nfds; ++fd) {
564         addr_len = sizeof(sock_addr);
565         if (-1 == (rc = getsockname(fd, (struct sockaddr *)&addr, &addr_len))) {
566             log_perror(srv->errh, __FILE__, __LINE__,
567               "socket activation getsockname()");
568             break;
569         }
570         network_host_normalize_addr_str(host, &addr);
571         rc = network_server_init(srv, s, host, 0, fd);
572         if (0 != rc) break;
573         srv->srv_sockets.ptr[srv->srv_sockets.used-1]->sidx = (unsigned short)~0u;
574     }
575     buffer_free(host);
576     memcpy(&srv->srv_sockets_inherited, &srv->srv_sockets, sizeof(server_socket_array));
577     memset(&srv->srv_sockets, 0, sizeof(server_socket_array));
578     return rc;
579 }
580 
581 static int network_socket_activation_from_env(server *srv, network_socket_config *s) {
582     char *listen_pid = getenv("LISTEN_PID");
583     char *listen_fds = getenv("LISTEN_FDS");
584     pid_t lpid = listen_pid ? (pid_t)strtoul(listen_pid,NULL,10) : 0;
585     int nfds = listen_fds ? atoi(listen_fds) : 0;
586     int rc = (nfds > 0 && nfds < 5000
587               && (lpid == getpid()
588                  #ifndef _WIN32
589                   || (0 == strncmp(listen_pid, "parent:", 7)
590                       && getppid() == (pid_t)strtoul(listen_pid+7,NULL,10))
591                  #endif
592                  ))
593       ? network_socket_activation_nfds(srv, s, nfds)
594       : 0;
595     unsetenv("LISTEN_PID");
596     unsetenv("LISTEN_FDS");
597     unsetenv("LISTEN_FDNAMES");
598     /*(upon graceful restart, unsetenv will result in no-op above)*/
599     return rc;
600 }
601 
602 int network_init(server *srv, int stdin_fd) {
603     /*(network params used during setup (from $SERVER["socket"] condition))*/
604     static const config_plugin_keys_t cpk[] = {
605       { CONST_STR_LEN("ssl.engine"),
606         T_CONFIG_BOOL,
607         T_CONFIG_SCOPE_CONNECTION }
608      ,{ CONST_STR_LEN("server.listen-backlog"),
609         T_CONFIG_INT,
610         T_CONFIG_SCOPE_CONNECTION }
611      ,{ CONST_STR_LEN("server.socket-perms"),
612         T_CONFIG_STRING,
613         T_CONFIG_SCOPE_CONNECTION }
614      ,{ CONST_STR_LEN("server.bsd-accept-filter"),
615         T_CONFIG_STRING,
616         T_CONFIG_SCOPE_CONNECTION }
617      ,{ CONST_STR_LEN("server.defer-accept"),
618         T_CONFIG_BOOL,
619         T_CONFIG_SCOPE_CONNECTION }
620      ,{ CONST_STR_LEN("server.use-ipv6"),
621         T_CONFIG_BOOL,
622         T_CONFIG_SCOPE_CONNECTION }
623      ,{ CONST_STR_LEN("server.set-v6only"),
624         T_CONFIG_BOOL,
625         T_CONFIG_SCOPE_CONNECTION }
626      ,{ CONST_STR_LEN("server.v4mapped"),
627         T_CONFIG_BOOL,
628         T_CONFIG_SCOPE_CONNECTION }
629     #if 0 /* TODO: more integration needed ... */
630      ,{ CONST_STR_LEN("mbedtls.engine"),
631         T_CONFIG_BOOL,
632         T_CONFIG_SCOPE_CONNECTION }
633     #endif
634      ,{ NULL, 0,
635         T_CONFIG_UNSET,
636         T_CONFIG_SCOPE_UNSET }
637     };
638 
639   #ifdef __WIN32
640     WSADATA wsaData;
641     WORD wVersionRequested = MAKEWORD(2, 2);
642     if (0 != WSAStartup(wVersionRequested, &wsaData)) {
643         /* Tell the user that we could not find a usable WinSock DLL */
644         return -1;
645     }
646   #endif
647 
648     if (0 != network_write_init(srv)) return -1;
649 
650     network_plugin_data np;
651     memset(&np, 0, sizeof(network_plugin_data));
652     network_plugin_data *p = &np;
653 
654     if (!config_plugin_values_init(srv, p, cpk, "network"))
655         return HANDLER_ERROR;
656 
657     p->defaults.listen_backlog = 1024;
658     p->defaults.defer_accept = 0;
659     p->defaults.use_ipv6 = 0;
660     p->defaults.set_v6only = 1;
661     p->defaults.v4mapped = -1; /*(-1 for unset; not 0 or 1)*/
662 
663     /* initialize p->defaults from global config context */
664     if (p->nconfig > 0 && p->cvlist->v.u2[1]) {
665         const config_plugin_value_t *cpv = p->cvlist + p->cvlist->v.u2[0];
666         if (-1 != cpv->k_id)
667             network_merge_config(&p->defaults, cpv);
668     }
669 
670     int rc = 0;
671     do {
672 
673         if (srv->srvconf.systemd_socket_activation) {
674             for (uint32_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
675                 srv->srv_sockets_inherited.ptr[i]->sidx = (unsigned short)~0u;
676             }
677             rc = network_socket_activation_from_env(srv, &p->defaults);
678             if (0 != rc) break;
679             if (0 == srv->srv_sockets_inherited.used) {
680                 srv->srvconf.systemd_socket_activation = 0;
681             }
682         }
683 
684         /* special-case srv->srvconf.bindhost = "/dev/stdin" (see server.c) */
685         if (-1 != stdin_fd) {
686             buffer *b = buffer_init();
687             buffer_copy_buffer(b, srv->srvconf.bindhost);
688             /*assert(buffer_eq_slen(b, CONST_STR_LEN("/dev/stdin")));*/
689             rc = (0 == srv->srv_sockets.used)
690               ? network_server_init(srv, &p->defaults, b, 0, stdin_fd)
691               : close(stdin_fd);/*(graceful restart listening to "/dev/stdin")*/
692             buffer_free(b);
693             if (0 != rc) break;
694         }
695 
696         /* check for $SERVER["socket"] */
697         for (uint32_t i = 1; i < srv->config_context->used; ++i) {
698             config_cond_info cfginfo;
699             config_get_config_cond_info(&cfginfo, i);
700             if (COMP_SERVER_SOCKET != cfginfo.comp) continue;/* not our stage */
701 
702             buffer *host_token;
703             *(const buffer **)&host_token = cfginfo.string;
704             /*(cfginfo.string is modified during config)*/
705 
706             memcpy(&p->conf, &p->defaults, sizeof(network_socket_config));
707             for (int j = !p->cvlist[0].v.u2[1]; j < p->nconfig; ++j) {
708                 if ((int)i != p->cvlist[j].k_id) continue;
709                 const config_plugin_value_t *cpv =
710                   p->cvlist + p->cvlist[j].v.u2[0];
711                 network_merge_config(&p->conf, cpv);
712                 break;
713             }
714 
715             if (cfginfo.cond == CONFIG_COND_EQ) {
716                 rc = network_server_init(srv, &p->conf, host_token, i, -1);
717                 if (0 != rc) break;
718             }
719             else if (cfginfo.cond == CONFIG_COND_NE) {
720                 socklen_t addr_len = sizeof(sock_addr);
721                 sock_addr addr;
722                 rc = network_host_parse_addr(srv, &addr, &addr_len,
723                                              host_token, p->conf.use_ipv6);
724                 if (0 != rc) break;
725                 network_host_normalize_addr_str(host_token, &addr);
726             }
727         }
728         if (0 != rc) break;
729 
730         /* process srv->srvconf.bindhost
731          * init global config for server.bindhost and server.port after
732          * initializing $SERVER["socket"] so that if bindhost and port match
733          * another $SERVER["socket"], the $SERVER["socket"] config is used,
734          * as the $SERVER["socket"] config inherits from the global scope and
735          * can then be overridden.  (bindhost = "/dev/stdin" is handled above)
736          * (skip if systemd socket activation is enabled and bindhost is empty;
737          *  do not additionally listen on "*") */
738         if ((!srv->srvconf.systemd_socket_activation || srv->srvconf.bindhost)
739             && -1 == stdin_fd) {
740             buffer *b = buffer_init();
741             if (srv->srvconf.bindhost)
742                 buffer_copy_buffer(b, srv->srvconf.bindhost);
743             /*(skip adding port if unix socket path)*/
744             if (!b->ptr || b->ptr[0] != '/') {
745                 buffer_append_string_len(b, CONST_STR_LEN(":"));
746                 buffer_append_int(b, srv->srvconf.port);
747             }
748           #ifdef __COVERITY__
749             force_assert(b->ptr);
750           #endif
751 
752             rc = network_server_init(srv, &p->defaults, b, 0, -1);
753             buffer_free(b);
754             if (0 != rc) break;
755         }
756 
757         if (srv->srvconf.systemd_socket_activation) {
758             /* activate any inherited sockets not explicitly listed in config */
759             server_socket *srv_socket;
760             for (uint32_t i = 0; i < srv->srv_sockets_inherited.used; ++i) {
761                     if ((unsigned short)~0u
762                         != srv->srv_sockets_inherited.ptr[i]->sidx)
763                         continue;
764                     srv->srv_sockets_inherited.ptr[i]->sidx = 0;
765                 srv_socket = calloc(1, sizeof(server_socket));
766                 force_assert(NULL != srv_socket);
767                 memcpy(srv_socket, srv->srv_sockets_inherited.ptr[i],
768                        sizeof(server_socket));
769                 const buffer * const srv_token = srv_socket->srv_token;
770                 buffer_copy_buffer((srv_socket->srv_token = buffer_init()),
771                                    srv_token);
772                 srv_socket->srv_token_colon =
773                   network_srv_token_colon(srv_socket->srv_token);
774                 network_srv_sockets_append(srv, srv_socket);
775             }
776         }
777 
778     } while (0);
779 
780     free(p->cvlist);
781     return rc;
782 }
783 
784 void network_unregister_sock(server *srv, server_socket *srv_socket) {
785 	fdnode *fdn = srv_socket->fdn;
786 	if (NULL == fdn) return;
787 	fdevent_fdnode_event_del(srv->ev, fdn);
788 	fdevent_unregister(srv->ev, fdn->fd);
789 	srv_socket->fdn = NULL;
790 }
791 
792 int network_register_fdevents(server *srv) {
793 	if (-1 == fdevent_reset(srv->ev)) {
794 		return -1;
795 	}
796 
797 	if (srv->sockets_disabled) return 0; /* lighttpd -1 (one-shot mode) */
798 
799 	/* register fdevents after reset */
800 	for (uint32_t i = 0; i < srv->srv_sockets.used; ++i) {
801 		server_socket *srv_socket = srv->srv_sockets.ptr[i];
802 
803 		srv_socket->fdn = fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
804 		fdevent_fdnode_event_set(srv->ev, srv_socket->fdn, FDEVENT_IN);
805 	}
806 	return 0;
807 }
808