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