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