Annotation of embedaddon/lighttpd/src/network.c, revision 1.1.1.3
1.1.1.3 ! misho 1: #include "first.h"
! 2:
1.1 misho 3: #include "network.h"
4: #include "fdevent.h"
5: #include "log.h"
6: #include "connections.h"
7: #include "plugin.h"
8: #include "joblist.h"
9: #include "configfile.h"
10:
11: #include "network_backends.h"
12: #include "sys-mmap.h"
13: #include "sys-socket.h"
14:
15: #include <sys/types.h>
16: #include <sys/stat.h>
17: #include <sys/time.h>
18:
19: #include <errno.h>
20: #include <fcntl.h>
21: #include <unistd.h>
22: #include <string.h>
23: #include <stdlib.h>
24: #include <assert.h>
25:
26: #ifdef USE_OPENSSL
27: # include <openssl/ssl.h>
28: # include <openssl/err.h>
29: # include <openssl/rand.h>
30: # ifndef OPENSSL_NO_DH
31: # include <openssl/dh.h>
32: # endif
33: # include <openssl/bn.h>
34:
35: # if OPENSSL_VERSION_NUMBER >= 0x0090800fL
36: # ifndef OPENSSL_NO_ECDH
37: # include <openssl/ecdh.h>
38: # endif
39: # endif
40: #endif
41:
42: #ifdef USE_OPENSSL
43: static void ssl_info_callback(const SSL *ssl, int where, int ret) {
44: UNUSED(ret);
45:
46: if (0 != (where & SSL_CB_HANDSHAKE_START)) {
47: connection *con = SSL_get_app_data(ssl);
48: ++con->renegotiations;
49: }
50: }
51: #endif
52:
1.1.1.3 ! misho 53: void
! 54: network_accept_tcp_nagle_disable (const int fd)
! 55: {
! 56: static int noinherit_tcpnodelay = -1;
! 57: int opt;
! 58:
! 59: if (!noinherit_tcpnodelay) /* TCP_NODELAY inherited from listen socket */
! 60: return;
! 61:
! 62: if (noinherit_tcpnodelay < 0) {
! 63: socklen_t optlen = sizeof(opt);
! 64: if (0 == getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen)) {
! 65: noinherit_tcpnodelay = !opt;
! 66: if (opt) /* TCP_NODELAY inherited from listen socket */
! 67: return;
! 68: }
! 69: }
! 70:
! 71: opt = 1;
! 72: (void)setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
! 73: }
! 74:
1.1 misho 75: static handler_t network_server_handle_fdevent(server *srv, void *context, int revents) {
76: server_socket *srv_socket = (server_socket *)context;
77: connection *con;
78: int loops = 0;
79:
80: UNUSED(context);
81:
82: if (0 == (revents & FDEVENT_IN)) {
83: log_error_write(srv, __FILE__, __LINE__, "sdd",
84: "strange event for server socket",
85: srv_socket->fd,
86: revents);
87: return HANDLER_ERROR;
88: }
89:
90: /* accept()s at most 100 connections directly
91: *
92: * we jump out after 100 to give the waiting connections a chance */
93: for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) {
94: connection_state_machine(srv, con);
95: }
96: return HANDLER_GO_ON;
97: }
98:
99: #if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
100: static int network_ssl_servername_callback(SSL *ssl, int *al, server *srv) {
101: const char *servername;
102: connection *con = (connection *) SSL_get_app_data(ssl);
103: UNUSED(al);
104:
105: buffer_copy_string(con->uri.scheme, "https");
106:
107: if (NULL == (servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
108: #if 0
109: /* this "error" just means the client didn't support it */
110: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
111: "failed to get TLS server name");
112: #endif
113: return SSL_TLSEXT_ERR_NOACK;
114: }
115: buffer_copy_string(con->tlsext_server_name, servername);
116: buffer_to_lower(con->tlsext_server_name);
117:
118: /* Sometimes this is still set, confusing COMP_HTTP_HOST */
119: buffer_reset(con->uri.authority);
120:
121: config_cond_cache_reset(srv, con);
122: config_setup_connection(srv, con);
123:
1.1.1.3 ! misho 124: con->conditional_is_valid[COMP_SERVER_SOCKET] = 1;
! 125: con->conditional_is_valid[COMP_HTTP_SCHEME] = 1;
! 126: con->conditional_is_valid[COMP_HTTP_HOST] = 1;
! 127: config_patch_connection(srv, con);
1.1 misho 128:
1.1.1.2 misho 129: if (NULL == con->conf.ssl_pemfile_x509 || NULL == con->conf.ssl_pemfile_pkey) {
130: /* x509/pkey available <=> pemfile was set <=> pemfile got patched: so this should never happen, unless you nest $SERVER["socket"] */
1.1 misho 131: log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
1.1.1.2 misho 132: "no certificate/private key for TLS server name", con->tlsext_server_name);
1.1 misho 133: return SSL_TLSEXT_ERR_ALERT_FATAL;
134: }
135:
1.1.1.2 misho 136: /* first set certificate! setting private key checks whether certificate matches it */
137: if (!SSL_use_certificate(ssl, con->conf.ssl_pemfile_x509)) {
138: log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:",
139: "failed to set certificate for TLS server name", con->tlsext_server_name,
140: ERR_error_string(ERR_get_error(), NULL));
141: return SSL_TLSEXT_ERR_ALERT_FATAL;
142: }
143:
144: if (!SSL_use_PrivateKey(ssl, con->conf.ssl_pemfile_pkey)) {
145: log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:",
146: "failed to set private key for TLS server name", con->tlsext_server_name,
147: ERR_error_string(ERR_get_error(), NULL));
1.1 misho 148: return SSL_TLSEXT_ERR_ALERT_FATAL;
149: }
150:
1.1.1.2 misho 151: if (con->conf.ssl_verifyclient) {
152: if (NULL == con->conf.ssl_ca_file_cert_names) {
153: log_error_write(srv, __FILE__, __LINE__, "ssb:s", "SSL:",
154: "can't verify client without ssl.ca-file for TLS server name", con->tlsext_server_name,
155: ERR_error_string(ERR_get_error(), NULL));
156: return SSL_TLSEXT_ERR_ALERT_FATAL;
157: }
158:
159: SSL_set_client_CA_list(ssl, SSL_dup_CA_list(con->conf.ssl_ca_file_cert_names));
160: /* forcing verification here is really not that useful - a client could just connect without SNI */
161: SSL_set_verify(
162: ssl,
163: SSL_VERIFY_PEER | (con->conf.ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0),
164: NULL
165: );
166: SSL_set_verify_depth(ssl, con->conf.ssl_verifyclient_depth);
1.1.1.3 ! misho 167: } else {
! 168: SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
1.1.1.2 misho 169: }
170:
1.1 misho 171: return SSL_TLSEXT_ERR_OK;
172: }
173: #endif
174:
175: static int network_server_init(server *srv, buffer *host_token, specific_config *s) {
176: int val;
177: socklen_t addr_len;
178: server_socket *srv_socket;
179: unsigned int port = 0;
180: const char *host;
181: buffer *b;
1.1.1.3 ! misho 182: int err;
1.1 misho 183:
184: #ifdef __WIN32
185: WORD wVersionRequested;
186: WSADATA wsaData;
187:
188: wVersionRequested = MAKEWORD( 2, 2 );
189:
190: err = WSAStartup( wVersionRequested, &wsaData );
191: if ( err != 0 ) {
192: /* Tell the user that we could not find a usable */
193: /* WinSock DLL. */
194: return -1;
195: }
196: #endif
1.1.1.3 ! misho 197: err = -1;
1.1 misho 198:
199: srv_socket = calloc(1, sizeof(*srv_socket));
1.1.1.3 ! misho 200: force_assert(NULL != srv_socket);
! 201: srv_socket->addr.plain.sa_family = AF_INET; /* default */
1.1 misho 202: srv_socket->fd = -1;
203: srv_socket->fde_ndx = -1;
204:
205: srv_socket->srv_token = buffer_init();
1.1.1.3 ! misho 206: buffer_copy_buffer(srv_socket->srv_token, host_token);
1.1 misho 207:
208: b = buffer_init();
1.1.1.3 ! misho 209: buffer_copy_buffer(b, host_token);
1.1 misho 210:
211: host = b->ptr;
212:
213: if (host[0] == '/') {
214: /* host is a unix-domain-socket */
215: #ifdef HAVE_SYS_UN_H
216: srv_socket->addr.plain.sa_family = AF_UNIX;
217: #else
218: log_error_write(srv, __FILE__, __LINE__, "s",
219: "ERROR: Unix Domain sockets are not supported.");
220: goto error_free_socket;
221: #endif
1.1.1.3 ! misho 222: } else {
! 223: /* ipv4:port
! 224: * [ipv6]:port
! 225: */
! 226: size_t len = buffer_string_length(b);
! 227: char *sp = NULL;
! 228: if (0 == len) {
! 229: log_error_write(srv, __FILE__, __LINE__, "s", "value of $SERVER[\"socket\"] must not be empty");
! 230: goto error_free_socket;
! 231: }
! 232: if ((b->ptr[0] == '[' && b->ptr[len-1] == ']') || NULL == (sp = strrchr(b->ptr, ':'))) {
! 233: /* use server.port if set in config, or else default from config_set_defaults() */
! 234: port = srv->srvconf.port;
! 235: sp = b->ptr + len; /* point to '\0' at end of string so end of IPv6 address can be found below */
! 236: } else {
! 237: /* found ip:port separator at *sp; port doesn't end in ']', so *sp hopefully doesn't split an IPv6 address */
! 238: *sp = '\0';
! 239: port = strtol(sp+1, NULL, 10);
! 240: }
1.1 misho 241:
1.1.1.3 ! misho 242: /* check for [ and ] */
! 243: if (b->ptr[0] == '[' && *(sp-1) == ']') {
! 244: *(sp-1) = '\0';
! 245: host++;
1.1 misho 246:
1.1.1.3 ! misho 247: s->use_ipv6 = 1;
1.1 misho 248: }
249:
1.1.1.3 ! misho 250: if (port == 0 || port > 65535) {
! 251: log_error_write(srv, __FILE__, __LINE__, "sd", "port not set or out of range:", port);
! 252:
1.1 misho 253: goto error_free_socket;
254: }
255: }
256:
1.1.1.3 ! misho 257: if (*host == '\0') host = NULL;
1.1 misho 258:
1.1.1.3 ! misho 259: #ifdef HAVE_IPV6
! 260: if (s->use_ipv6) {
! 261: srv_socket->addr.plain.sa_family = AF_INET6;
1.1 misho 262: }
1.1.1.3 ! misho 263: #endif
1.1 misho 264:
265: switch(srv_socket->addr.plain.sa_family) {
266: #ifdef HAVE_IPV6
267: case AF_INET6:
268: memset(&srv_socket->addr, 0, sizeof(struct sockaddr_in6));
269: srv_socket->addr.ipv6.sin6_family = AF_INET6;
270: if (host == NULL) {
271: srv_socket->addr.ipv6.sin6_addr = in6addr_any;
272: 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");
273: } else {
274: struct addrinfo hints, *res;
275: int r;
276:
277: memset(&hints, 0, sizeof(hints));
278:
279: hints.ai_family = AF_INET6;
280: hints.ai_socktype = SOCK_STREAM;
281: hints.ai_protocol = IPPROTO_TCP;
282:
283: if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) {
1.1.1.3 ! misho 284: hints.ai_family = AF_INET;
! 285: if (
! 286: #ifdef EAI_ADDRFAMILY
! 287: EAI_ADDRFAMILY == r &&
! 288: #endif
! 289: 0 == getaddrinfo(host, NULL, &hints, &res)) {
! 290: memcpy(&srv_socket->addr.ipv4, res->ai_addr, res->ai_addrlen);
! 291: srv_socket->addr.ipv4.sin_family = AF_INET;
! 292: srv_socket->addr.ipv4.sin_port = htons(port);
! 293: addr_len = sizeof(struct sockaddr_in);
! 294: /*assert(addr_len == res->ai_addrlen);*/
! 295: freeaddrinfo(res);
! 296: break;
! 297: }
! 298:
1.1 misho 299: log_error_write(srv, __FILE__, __LINE__,
300: "sssss", "getaddrinfo failed: ",
301: gai_strerror(r), "'", host, "'");
302:
303: goto error_free_socket;
304: }
305:
306: memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
307:
308: freeaddrinfo(res);
309: }
310: srv_socket->addr.ipv6.sin6_port = htons(port);
311: addr_len = sizeof(struct sockaddr_in6);
312: break;
313: #endif
314: case AF_INET:
315: memset(&srv_socket->addr, 0, sizeof(struct sockaddr_in));
316: srv_socket->addr.ipv4.sin_family = AF_INET;
317: if (host == NULL) {
318: srv_socket->addr.ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
319: } else {
320: struct hostent *he;
321: if (NULL == (he = gethostbyname(host))) {
322: log_error_write(srv, __FILE__, __LINE__,
323: "sds", "gethostbyname failed: ",
324: h_errno, host);
325: goto error_free_socket;
326: }
327:
328: if (he->h_addrtype != AF_INET) {
329: log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
330: goto error_free_socket;
331: }
332:
333: if (he->h_length != sizeof(struct in_addr)) {
334: log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
335: goto error_free_socket;
336: }
337:
338: memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
339: }
340: srv_socket->addr.ipv4.sin_port = htons(port);
341: addr_len = sizeof(struct sockaddr_in);
342: break;
1.1.1.3 ! misho 343: #ifdef HAVE_SYS_UN_H
1.1 misho 344: case AF_UNIX:
1.1.1.3 ! misho 345: memset(&srv_socket->addr, 0, sizeof(struct sockaddr_un));
! 346: srv_socket->addr.un.sun_family = AF_UNIX;
1.1.1.2 misho 347: {
348: size_t hostlen = strlen(host) + 1;
349: if (hostlen > sizeof(srv_socket->addr.un.sun_path)) {
350: log_error_write(srv, __FILE__, __LINE__, "sS", "unix socket filename too long:", host);
351: goto error_free_socket;
352: }
353: memcpy(srv_socket->addr.un.sun_path, host, hostlen);
1.1 misho 354:
1.1.1.3 ! misho 355: #if defined(SUN_LEN)
! 356: addr_len = SUN_LEN(&srv_socket->addr.un);
1.1 misho 357: #else
1.1.1.3 ! misho 358: /* stevens says: */
! 359: addr_len = hostlen + sizeof(srv_socket->addr.un.sun_family);
1.1 misho 360: #endif
1.1.1.3 ! misho 361: }
1.1 misho 362:
1.1.1.3 ! misho 363: break;
! 364: #endif
! 365: default:
! 366: goto error_free_socket;
! 367: }
! 368:
! 369: if (srv->srvconf.preflight_check) {
! 370: err = 0;
! 371: goto error_free_socket;
! 372: }
! 373:
! 374: if (srv->sockets_disabled) { /* lighttpd -1 (one-shot mode) */
! 375: #ifdef USE_OPENSSL
! 376: if (s->ssl_enabled) srv_socket->ssl_ctx = s->ssl_ctx;
! 377: #endif
! 378: goto srv_sockets_append;
! 379: }
1.1 misho 380:
1.1.1.3 ! misho 381: #ifdef HAVE_SYS_UN_H
! 382: if (AF_UNIX == srv_socket->addr.plain.sa_family) {
! 383: /* check if the socket exists and try to connect to it. */
! 384: force_assert(host); /*(static analysis hint)*/
! 385: if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
! 386: log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
! 387: goto error_free_socket;
! 388: }
! 389: if (0 == connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
1.1 misho 390: log_error_write(srv, __FILE__, __LINE__, "ss",
391: "server socket is still in use:",
392: host);
393:
394:
395: goto error_free_socket;
396: }
397:
398: /* connect failed */
399: switch(errno) {
400: case ECONNREFUSED:
401: unlink(host);
402: break;
403: case ENOENT:
404: break;
405: default:
406: log_error_write(srv, __FILE__, __LINE__, "sds",
407: "testing socket failed:",
408: host, strerror(errno));
409:
410: goto error_free_socket;
411: }
1.1.1.3 ! misho 412: } else
! 413: #endif
! 414: {
! 415: if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
! 416: log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
! 417: goto error_free_socket;
! 418: }
1.1 misho 419:
1.1.1.3 ! misho 420: #ifdef HAVE_IPV6
! 421: if (AF_INET6 == srv_socket->addr.plain.sa_family
! 422: && host != NULL) {
! 423: if (s->set_v6only) {
! 424: val = 1;
! 425: if (-1 == setsockopt(srv_socket->fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val))) {
! 426: log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt(IPV6_V6ONLY) failed:", strerror(errno));
! 427: goto error_free_socket;
! 428: }
! 429: } else {
! 430: 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");
! 431: }
! 432: }
! 433: #endif
! 434: }
! 435:
! 436: /* set FD_CLOEXEC now, fdevent_fcntl_set is called later; needed for pipe-logger forks */
! 437: fd_close_on_exec(srv_socket->fd);
! 438:
! 439: /* */
! 440: srv->cur_fds = srv_socket->fd;
! 441:
! 442: val = 1;
! 443: if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
! 444: log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt(SO_REUSEADDR) failed:", strerror(errno));
1.1 misho 445: goto error_free_socket;
446: }
447:
1.1.1.3 ! misho 448: if (srv_socket->addr.plain.sa_family != AF_UNIX) {
! 449: val = 1;
! 450: if (setsockopt(srv_socket->fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) < 0) {
! 451: log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt(TCP_NODELAY) failed:", strerror(errno));
! 452: goto error_free_socket;
! 453: }
! 454: }
! 455:
1.1 misho 456: if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
457: switch(srv_socket->addr.plain.sa_family) {
458: case AF_UNIX:
459: log_error_write(srv, __FILE__, __LINE__, "sds",
460: "can't bind to socket:",
461: host, strerror(errno));
462: break;
463: default:
464: log_error_write(srv, __FILE__, __LINE__, "ssds",
465: "can't bind to port:",
466: host, port, strerror(errno));
467: break;
468: }
469: goto error_free_socket;
470: }
471:
1.1.1.3 ! misho 472: if (-1 == listen(srv_socket->fd, s->listen_backlog)) {
1.1 misho 473: log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
474: goto error_free_socket;
475: }
476:
477: if (s->ssl_enabled) {
478: #ifdef USE_OPENSSL
479: if (NULL == (srv_socket->ssl_ctx = s->ssl_ctx)) {
480: log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
481: goto error_free_socket;
482: }
483: #else
484:
485: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
486: "ssl requested but openssl support is not compiled in");
487:
488: goto error_free_socket;
489: #endif
490: #ifdef TCP_DEFER_ACCEPT
491: } else if (s->defer_accept) {
492: int v = s->defer_accept;
493: if (-1 == setsockopt(srv_socket->fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &v, sizeof(v))) {
494: log_error_write(srv, __FILE__, __LINE__, "ss", "can't set TCP_DEFER_ACCEPT: ", strerror(errno));
495: }
496: #endif
1.1.1.3 ! misho 497: #if defined(__FreeBSD__) || defined(__NetBSD__) \
! 498: || defined(__OpenBSD__) || defined(__DragonflyBSD__)
! 499: } else if (!buffer_is_empty(s->bsd_accept_filter)
! 500: && (buffer_is_equal_string(s->bsd_accept_filter, CONST_STR_LEN("httpready"))
! 501: || buffer_is_equal_string(s->bsd_accept_filter, CONST_STR_LEN("dataready")))) {
1.1 misho 502: #ifdef SO_ACCEPTFILTER
503: /* FreeBSD accf_http filter */
504: struct accept_filter_arg afa;
505: memset(&afa, 0, sizeof(afa));
1.1.1.3 ! misho 506: strncpy(afa.af_name, s->bsd_accept_filter->ptr, sizeof(afa.af_name));
1.1 misho 507: if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)) < 0) {
508: if (errno != ENOENT) {
1.1.1.3 ! misho 509: log_error_write(srv, __FILE__, __LINE__, "SBss", "can't set accept-filter '", s->bsd_accept_filter, "':", strerror(errno));
1.1 misho 510: }
511: }
512: #endif
1.1.1.3 ! misho 513: #endif
1.1 misho 514: }
515:
1.1.1.3 ! misho 516: srv_sockets_append:
1.1 misho 517: srv_socket->is_ssl = s->ssl_enabled;
518:
519: if (srv->srv_sockets.size == 0) {
520: srv->srv_sockets.size = 4;
521: srv->srv_sockets.used = 0;
1.1.1.2 misho 522: srv->srv_sockets.ptr = malloc(srv->srv_sockets.size * sizeof(server_socket*));
1.1.1.3 ! misho 523: force_assert(NULL != srv->srv_sockets.ptr);
1.1 misho 524: } else if (srv->srv_sockets.used == srv->srv_sockets.size) {
525: srv->srv_sockets.size += 4;
1.1.1.2 misho 526: srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket*));
1.1.1.3 ! misho 527: force_assert(NULL != srv->srv_sockets.ptr);
1.1 misho 528: }
529:
530: srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
531:
532: buffer_free(b);
533:
534: return 0;
535:
536: error_free_socket:
537: if (srv_socket->fd != -1) {
538: /* check if server fd are already registered */
539: if (srv_socket->fde_ndx != -1) {
540: fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
541: fdevent_unregister(srv->ev, srv_socket->fd);
542: }
543:
544: close(srv_socket->fd);
545: }
546: buffer_free(srv_socket->srv_token);
547: free(srv_socket);
548:
549: buffer_free(b);
550:
1.1.1.3 ! misho 551: return err; /* -1 if error; 0 if srv->srvconf.preflight_check successful */
1.1 misho 552: }
553:
554: int network_close(server *srv) {
555: size_t i;
556: for (i = 0; i < srv->srv_sockets.used; i++) {
557: server_socket *srv_socket = srv->srv_sockets.ptr[i];
558:
559: if (srv_socket->fd != -1) {
560: /* check if server fd are already registered */
561: if (srv_socket->fde_ndx != -1) {
562: fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
563: fdevent_unregister(srv->ev, srv_socket->fd);
564: }
565:
566: close(srv_socket->fd);
567: }
568:
569: buffer_free(srv_socket->srv_token);
570:
571: free(srv_socket);
572: }
573:
574: free(srv->srv_sockets.ptr);
575:
576: return 0;
577: }
578:
579: typedef enum {
580: NETWORK_BACKEND_UNSET,
581: NETWORK_BACKEND_WRITE,
582: NETWORK_BACKEND_WRITEV,
1.1.1.3 ! misho 583: NETWORK_BACKEND_SENDFILE,
1.1 misho 584: } network_backend_t;
585:
1.1.1.2 misho 586: #ifdef USE_OPENSSL
587: static X509* x509_load_pem_file(server *srv, const char *file) {
588: BIO *in;
589: X509 *x = NULL;
590:
591: in = BIO_new(BIO_s_file());
592: if (NULL == in) {
593: log_error_write(srv, __FILE__, __LINE__, "S", "SSL: BIO_new(BIO_s_file()) failed");
594: goto error;
595: }
596:
597: if (BIO_read_filename(in,file) <= 0) {
598: log_error_write(srv, __FILE__, __LINE__, "SSS", "SSL: BIO_read_filename('", file,"') failed");
599: goto error;
600: }
601: x = PEM_read_bio_X509(in, NULL, NULL, NULL);
602:
603: if (NULL == x) {
604: log_error_write(srv, __FILE__, __LINE__, "SSS", "SSL: couldn't read X509 certificate from '", file,"'");
605: goto error;
606: }
607:
608: BIO_free(in);
609: return x;
610:
611: error:
612: if (NULL != in) BIO_free(in);
613: return NULL;
614: }
615:
616: static EVP_PKEY* evp_pkey_load_pem_file(server *srv, const char *file) {
617: BIO *in;
618: EVP_PKEY *x = NULL;
619:
620: in=BIO_new(BIO_s_file());
621: if (NULL == in) {
622: log_error_write(srv, __FILE__, __LINE__, "s", "SSL: BIO_new(BIO_s_file()) failed");
623: goto error;
624: }
625:
626: if (BIO_read_filename(in,file) <= 0) {
627: log_error_write(srv, __FILE__, __LINE__, "SSS", "SSL: BIO_read_filename('", file,"') failed");
628: goto error;
629: }
630: x = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
631:
632: if (NULL == x) {
633: log_error_write(srv, __FILE__, __LINE__, "SSS", "SSL: couldn't read private key from '", file,"'");
634: goto error;
635: }
636:
637: BIO_free(in);
638: return x;
639:
640: error:
641: if (NULL != in) BIO_free(in);
642: return NULL;
643: }
644:
645: static int network_openssl_load_pemfile(server *srv, size_t ndx) {
646: specific_config *s = srv->config_storage[ndx];
647:
648: #ifdef OPENSSL_NO_TLSEXT
649: {
650: data_config *dc = (data_config *)srv->config_context->data[ndx];
651: if ((ndx > 0 && (COMP_SERVER_SOCKET != dc->comp || dc->cond != CONFIG_COND_EQ))
652: || !s->ssl_enabled) {
653: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
654: "ssl.pemfile only works in SSL socket binding context as openssl version does not support TLS extensions");
655: return -1;
656: }
657: }
658: #endif
659:
660: if (NULL == (s->ssl_pemfile_x509 = x509_load_pem_file(srv, s->ssl_pemfile->ptr))) return -1;
661: if (NULL == (s->ssl_pemfile_pkey = evp_pkey_load_pem_file(srv, s->ssl_pemfile->ptr))) return -1;
662:
663: if (!X509_check_private_key(s->ssl_pemfile_x509, s->ssl_pemfile_pkey)) {
664: log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
665: "Private key does not match the certificate public key, reason:",
666: ERR_error_string(ERR_get_error(), NULL),
667: s->ssl_pemfile);
668: return -1;
669: }
670:
671: return 0;
672: }
673: #endif
674:
1.1 misho 675: int network_init(server *srv) {
676: buffer *b;
1.1.1.2 misho 677: size_t i, j;
1.1 misho 678: network_backend_t backend;
679:
680: #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
681: #ifndef OPENSSL_NO_ECDH
682: EC_KEY *ecdh;
683: int nid;
684: #endif
685: #endif
686:
687: #ifdef USE_OPENSSL
688: # ifndef OPENSSL_NO_DH
689: DH *dh;
690: # endif
691: BIO *bio;
692:
693: /* 1024-bit MODP Group with 160-bit prime order subgroup (RFC5114)
694: * -----BEGIN DH PARAMETERS-----
695: * MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y
696: * mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4
697: * +qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV
698: * w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0
699: * sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR
700: * jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA=
701: * -----END DH PARAMETERS-----
702: */
703:
704: static const unsigned char dh1024_p[]={
705: 0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E,
706: 0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6,
707: 0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86,
708: 0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0,
709: 0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C,
710: 0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70,
711: 0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA,
712: 0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0,
713: 0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF,
714: 0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08,
715: 0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71,
716: };
717:
718: static const unsigned char dh1024_g[]={
719: 0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42,
720: 0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F,
721: 0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E,
722: 0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13,
723: 0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F,
724: 0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1,
725: 0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08,
726: 0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A,
727: 0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59,
728: 0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24,
729: 0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5,
730: };
731: #endif
732:
733: struct nb_map {
734: network_backend_t nb;
735: const char *name;
736: } network_backends[] = {
737: /* lowest id wins */
1.1.1.3 ! misho 738: #if defined USE_SENDFILE
! 739: { NETWORK_BACKEND_SENDFILE, "sendfile" },
! 740: #endif
1.1 misho 741: #if defined USE_LINUX_SENDFILE
1.1.1.3 ! misho 742: { NETWORK_BACKEND_SENDFILE, "linux-sendfile" },
1.1 misho 743: #endif
744: #if defined USE_FREEBSD_SENDFILE
1.1.1.3 ! misho 745: { NETWORK_BACKEND_SENDFILE, "freebsd-sendfile" },
1.1 misho 746: #endif
747: #if defined USE_SOLARIS_SENDFILEV
1.1.1.3 ! misho 748: { NETWORK_BACKEND_SENDFILE, "solaris-sendfilev" },
1.1 misho 749: #endif
750: #if defined USE_WRITEV
1.1.1.3 ! misho 751: { NETWORK_BACKEND_WRITEV, "writev" },
1.1 misho 752: #endif
1.1.1.3 ! misho 753: { NETWORK_BACKEND_WRITE, "write" },
! 754: { NETWORK_BACKEND_UNSET, NULL }
1.1 misho 755: };
756:
757: #ifdef USE_OPENSSL
758: /* load SSL certificates */
759: for (i = 0; i < srv->config_context->used; i++) {
760: specific_config *s = srv->config_storage[i];
761: #ifndef SSL_OP_NO_COMPRESSION
762: # define SSL_OP_NO_COMPRESSION 0
763: #endif
1.1.1.3 ! misho 764: #ifndef SSL_MODE_RELEASE_BUFFERS /* OpenSSL >= 1.0.0 */
! 765: #define SSL_MODE_RELEASE_BUFFERS 0
! 766: #endif
1.1 misho 767: long ssloptions =
768: SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_NO_COMPRESSION;
769:
1.1.1.3 ! misho 770: if (buffer_string_is_empty(s->ssl_pemfile) && buffer_string_is_empty(s->ssl_ca_file)) continue;
1.1 misho 771:
772: if (srv->ssl_is_init == 0) {
773: SSL_load_error_strings();
774: SSL_library_init();
775: OpenSSL_add_all_algorithms();
776: srv->ssl_is_init = 1;
777:
778: if (0 == RAND_status()) {
779: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
780: "not enough entropy in the pool");
781: return -1;
782: }
783: }
784:
1.1.1.3 ! misho 785: if (!buffer_string_is_empty(s->ssl_pemfile)) {
1.1.1.2 misho 786: #ifdef OPENSSL_NO_TLSEXT
787: data_config *dc = (data_config *)srv->config_context->data[i];
788: if (COMP_HTTP_HOST == dc->comp) {
789: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
790: "can't use ssl.pemfile with $HTTP[\"host\"], openssl version does not support TLS extensions");
791: return -1;
792: }
793: #endif
794: if (network_openssl_load_pemfile(srv, i)) return -1;
795: }
796:
797:
1.1.1.3 ! misho 798: if (!buffer_string_is_empty(s->ssl_ca_file)) {
1.1.1.2 misho 799: s->ssl_ca_file_cert_names = SSL_load_client_CA_file(s->ssl_ca_file->ptr);
800: if (NULL == s->ssl_ca_file_cert_names) {
801: log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
802: ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
803: }
804: }
805:
1.1.1.3 ! misho 806: if (buffer_string_is_empty(s->ssl_pemfile) || !s->ssl_enabled) continue;
1.1.1.2 misho 807:
1.1 misho 808: if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
809: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
810: ERR_error_string(ERR_get_error(), NULL));
811: return -1;
812: }
813:
1.1.1.2 misho 814: /* completely useless identifier; required for client cert verification to work with sessions */
815: if (0 == SSL_CTX_set_session_id_context(s->ssl_ctx, (const unsigned char*) CONST_STR_LEN("lighttpd"))) {
816: log_error_write(srv, __FILE__, __LINE__, "ss:s", "SSL:",
817: "failed to set session context",
818: ERR_error_string(ERR_get_error(), NULL));
819: return -1;
820: }
821:
1.1 misho 822: if (s->ssl_empty_fragments) {
823: #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
824: ssloptions &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
825: #else
826: ssloptions &= ~0x00000800L; /* hardcode constant */
827: log_error_write(srv, __FILE__, __LINE__, "ss", "WARNING: SSL:",
828: "'insert empty fragments' not supported by the openssl version used to compile lighttpd with");
829: #endif
830: }
831:
832: SSL_CTX_set_options(s->ssl_ctx, ssloptions);
833: SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback);
834:
835: if (!s->ssl_use_sslv2) {
836: /* disable SSLv2 */
1.1.1.3 ! misho 837: if ((SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2)) != SSL_OP_NO_SSLv2) {
1.1 misho 838: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
839: ERR_error_string(ERR_get_error(), NULL));
840: return -1;
841: }
842: }
843:
844: if (!s->ssl_use_sslv3) {
845: /* disable SSLv3 */
1.1.1.3 ! misho 846: if ((SSL_OP_NO_SSLv3 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv3)) != SSL_OP_NO_SSLv3) {
1.1 misho 847: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
848: ERR_error_string(ERR_get_error(), NULL));
849: return -1;
850: }
851: }
852:
1.1.1.3 ! misho 853: if (!buffer_string_is_empty(s->ssl_cipher_list)) {
1.1 misho 854: /* Disable support for low encryption ciphers */
855: if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) {
856: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
857: ERR_error_string(ERR_get_error(), NULL));
858: return -1;
859: }
860:
861: if (s->ssl_honor_cipher_order) {
862: SSL_CTX_set_options(s->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
863: }
864: }
865:
866: #ifndef OPENSSL_NO_DH
867: /* Support for Diffie-Hellman key exchange */
1.1.1.3 ! misho 868: if (!buffer_string_is_empty(s->ssl_dh_file)) {
1.1 misho 869: /* DH parameters from file */
870: bio = BIO_new_file((char *) s->ssl_dh_file->ptr, "r");
871: if (bio == NULL) {
872: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to open file", s->ssl_dh_file->ptr);
873: return -1;
874: }
875: dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
876: BIO_free(bio);
877: if (dh == NULL) {
878: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: PEM_read_bio_DHparams failed", s->ssl_dh_file->ptr);
879: return -1;
880: }
881: } else {
1.1.1.3 ! misho 882: BIGNUM *dh_p, *dh_g;
1.1 misho 883: /* Default DH parameters from RFC5114 */
884: dh = DH_new();
885: if (dh == NULL) {
886: log_error_write(srv, __FILE__, __LINE__, "s", "SSL: DH_new () failed");
887: return -1;
888: }
1.1.1.3 ! misho 889: dh_p = BN_bin2bn(dh1024_p,sizeof(dh1024_p), NULL);
! 890: dh_g = BN_bin2bn(dh1024_g,sizeof(dh1024_g), NULL);
! 891: if ((dh_p == NULL) || (dh_g == NULL)) {
1.1 misho 892: DH_free(dh);
893: log_error_write(srv, __FILE__, __LINE__, "s", "SSL: BN_bin2bn () failed");
894: return -1;
895: }
1.1.1.3 ! misho 896: #if OPENSSL_VERSION_NUMBER < 0x10100000L \
! 897: || defined(LIBRESSL_VERSION_NUMBER)
! 898: dh->p = dh_p;
! 899: dh->g = dh_g;
! 900: dh->length = 160;
! 901: #else
! 902: DH_set0_pqg(dh, dh_p, NULL, dh_g);
! 903: DH_set_length(dh, 160);
! 904: #endif
1.1 misho 905: }
906: SSL_CTX_set_tmp_dh(s->ssl_ctx,dh);
907: SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_DH_USE);
908: DH_free(dh);
909: #else
1.1.1.3 ! misho 910: if (!buffer_string_is_empty(s->ssl_dh_file)) {
1.1 misho 911: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: openssl compiled without DH support, can't load parameters from", s->ssl_dh_file->ptr);
912: }
913: #endif
914:
915: #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
916: #ifndef OPENSSL_NO_ECDH
917: /* Support for Elliptic-Curve Diffie-Hellman key exchange */
1.1.1.3 ! misho 918: if (!buffer_string_is_empty(s->ssl_ec_curve)) {
1.1 misho 919: /* OpenSSL only supports the "named curves" from RFC 4492, section 5.1.1. */
920: nid = OBJ_sn2nid((char *) s->ssl_ec_curve->ptr);
921: if (nid == 0) {
922: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unknown curve name", s->ssl_ec_curve->ptr);
923: return -1;
924: }
925: } else {
926: /* Default curve */
927: nid = OBJ_sn2nid("prime256v1");
928: }
929: ecdh = EC_KEY_new_by_curve_name(nid);
930: if (ecdh == NULL) {
931: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to create curve", s->ssl_ec_curve->ptr);
932: return -1;
933: }
934: SSL_CTX_set_tmp_ecdh(s->ssl_ctx,ecdh);
935: SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_ECDH_USE);
936: EC_KEY_free(ecdh);
937: #endif
938: #endif
939:
1.1.1.2 misho 940: /* load all ssl.ca-files specified in the config into each SSL_CTX to be prepared for SNI */
941: for (j = 0; j < srv->config_context->used; j++) {
942: specific_config *s1 = srv->config_storage[j];
943:
1.1.1.3 ! misho 944: if (!buffer_string_is_empty(s1->ssl_ca_file)) {
1.1.1.2 misho 945: if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s1->ssl_ca_file->ptr, NULL)) {
1.1 misho 946: log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
1.1.1.2 misho 947: ERR_error_string(ERR_get_error(), NULL), s1->ssl_ca_file);
1.1 misho 948: return -1;
949: }
1.1.1.2 misho 950: }
951: }
952:
953: if (s->ssl_verifyclient) {
954: if (NULL == s->ssl_ca_file_cert_names) {
955: log_error_write(srv, __FILE__, __LINE__, "s",
956: "SSL: You specified ssl.verifyclient.activate but no ca_file"
1.1 misho 957: );
1.1.1.2 misho 958: return -1;
1.1 misho 959: }
1.1.1.2 misho 960: SSL_CTX_set_client_CA_list(s->ssl_ctx, SSL_dup_CA_list(s->ssl_ca_file_cert_names));
961: SSL_CTX_set_verify(
962: s->ssl_ctx,
963: SSL_VERIFY_PEER | (s->ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0),
964: NULL
1.1 misho 965: );
1.1.1.2 misho 966: SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth);
1.1 misho 967: }
968:
1.1.1.3 ! misho 969: if (1 != SSL_CTX_use_certificate(s->ssl_ctx, s->ssl_pemfile_x509)) {
1.1 misho 970: log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
971: ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
972: return -1;
973: }
974:
1.1.1.3 ! misho 975: if (1 != SSL_CTX_use_PrivateKey(s->ssl_ctx, s->ssl_pemfile_pkey)) {
1.1 misho 976: log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
977: ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
978: return -1;
979: }
980:
981: if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
982: log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
983: "Private key does not match the certificate public key, reason:",
984: ERR_error_string(ERR_get_error(), NULL),
985: s->ssl_pemfile);
986: return -1;
987: }
988: SSL_CTX_set_default_read_ahead(s->ssl_ctx, 1);
1.1.1.3 ! misho 989: SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx)
! 990: | SSL_MODE_ENABLE_PARTIAL_WRITE
! 991: | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
! 992: | SSL_MODE_RELEASE_BUFFERS);
1.1 misho 993:
994: # ifndef OPENSSL_NO_TLSEXT
995: if (!SSL_CTX_set_tlsext_servername_callback(s->ssl_ctx, network_ssl_servername_callback) ||
996: !SSL_CTX_set_tlsext_servername_arg(s->ssl_ctx, srv)) {
997: log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
998: "failed to initialize TLS servername callback, openssl library does not support TLS servername extension");
999: return -1;
1000: }
1001: # endif
1002: }
1003: #endif
1004:
1005: b = buffer_init();
1006:
1.1.1.3 ! misho 1007: buffer_copy_buffer(b, srv->srvconf.bindhost);
1.1 misho 1008: buffer_append_string_len(b, CONST_STR_LEN(":"));
1.1.1.3 ! misho 1009: buffer_append_int(b, srv->srvconf.port);
1.1 misho 1010:
1011: if (0 != network_server_init(srv, b, srv->config_storage[0])) {
1.1.1.2 misho 1012: buffer_free(b);
1.1 misho 1013: return -1;
1014: }
1015: buffer_free(b);
1016:
1017: #ifdef USE_OPENSSL
1018: srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
1019: #endif
1020:
1021: /* get a usefull default */
1022: backend = network_backends[0].nb;
1023:
1024: /* match name against known types */
1.1.1.3 ! misho 1025: if (!buffer_string_is_empty(srv->srvconf.network_backend)) {
1.1 misho 1026: for (i = 0; network_backends[i].name; i++) {
1027: /**/
1028: if (buffer_is_equal_string(srv->srvconf.network_backend, network_backends[i].name, strlen(network_backends[i].name))) {
1029: backend = network_backends[i].nb;
1030: break;
1031: }
1032: }
1033: if (NULL == network_backends[i].name) {
1034: /* we don't know it */
1035:
1036: log_error_write(srv, __FILE__, __LINE__, "sb",
1037: "server.network-backend has a unknown value:",
1038: srv->srvconf.network_backend);
1039:
1040: return -1;
1041: }
1042: }
1043:
1044: switch(backend) {
1045: case NETWORK_BACKEND_WRITE:
1046: srv->network_backend_write = network_write_chunkqueue_write;
1047: break;
1.1.1.3 ! misho 1048: #if defined(USE_WRITEV)
1.1 misho 1049: case NETWORK_BACKEND_WRITEV:
1050: srv->network_backend_write = network_write_chunkqueue_writev;
1051: break;
1052: #endif
1.1.1.3 ! misho 1053: #if defined(USE_SENDFILE)
! 1054: case NETWORK_BACKEND_SENDFILE:
! 1055: srv->network_backend_write = network_write_chunkqueue_sendfile;
1.1 misho 1056: break;
1057: #endif
1058: default:
1059: return -1;
1060: }
1061:
1062: /* check for $SERVER["socket"] */
1063: for (i = 1; i < srv->config_context->used; i++) {
1064: data_config *dc = (data_config *)srv->config_context->data[i];
1065: specific_config *s = srv->config_storage[i];
1066:
1067: /* not our stage */
1068: if (COMP_SERVER_SOCKET != dc->comp) continue;
1069:
1070: if (dc->cond != CONFIG_COND_EQ) continue;
1071:
1072: /* check if we already know this socket,
1073: * if yes, don't init it */
1074: for (j = 0; j < srv->srv_sockets.used; j++) {
1075: if (buffer_is_equal(srv->srv_sockets.ptr[j]->srv_token, dc->string)) {
1076: break;
1077: }
1078: }
1079:
1080: if (j == srv->srv_sockets.used) {
1081: if (0 != network_server_init(srv, dc->string, s)) return -1;
1082: }
1083: }
1084:
1085: return 0;
1086: }
1087:
1088: int network_register_fdevents(server *srv) {
1089: size_t i;
1090:
1091: if (-1 == fdevent_reset(srv->ev)) {
1092: return -1;
1093: }
1094:
1.1.1.3 ! misho 1095: if (srv->sockets_disabled) return 0; /* lighttpd -1 (one-shot mode) */
! 1096:
1.1 misho 1097: /* register fdevents after reset */
1098: for (i = 0; i < srv->srv_sockets.used; i++) {
1099: server_socket *srv_socket = srv->srv_sockets.ptr[i];
1100:
1101: fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
1102: fdevent_event_set(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
1103: }
1104: return 0;
1105: }
1106:
1107: int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq, off_t max_bytes) {
1108: int ret = -1;
1109: off_t written = 0;
1110: #ifdef TCP_CORK
1111: int corked = 0;
1112: #endif
1113: server_socket *srv_socket = con->srv_socket;
1114:
1115: if (con->conf.global_kbytes_per_second) {
1116: off_t limit = con->conf.global_kbytes_per_second * 1024 - *(con->conf.global_bytes_per_second_cnt_ptr);
1117: if (limit <= 0) {
1118: /* we reached the global traffic limit */
1119: con->traffic_limit_reached = 1;
1120:
1121: return 1;
1122: } else {
1123: if (max_bytes > limit) max_bytes = limit;
1124: }
1125: }
1126:
1127: if (con->conf.kbytes_per_second) {
1128: off_t limit = con->conf.kbytes_per_second * 1024 - con->bytes_written_cur_second;
1129: if (limit <= 0) {
1130: /* we reached the traffic limit */
1131: con->traffic_limit_reached = 1;
1132:
1133: return 1;
1134: } else {
1135: if (max_bytes > limit) max_bytes = limit;
1136: }
1137: }
1138:
1139: written = cq->bytes_out;
1140:
1141: #ifdef TCP_CORK
1142: /* Linux: put a cork into the socket as we want to combine the write() calls
1143: * but only if we really have multiple chunks
1144: */
1145: if (cq->first && cq->first->next) {
1146: corked = 1;
1.1.1.3 ! misho 1147: (void)setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
1.1 misho 1148: }
1149: #endif
1150:
1151: if (srv_socket->is_ssl) {
1152: #ifdef USE_OPENSSL
1153: ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq, max_bytes);
1154: #endif
1155: } else {
1156: ret = srv->network_backend_write(srv, con, con->fd, cq, max_bytes);
1157: }
1158:
1159: if (ret >= 0) {
1160: chunkqueue_remove_finished_chunks(cq);
1161: ret = chunkqueue_is_empty(cq) ? 0 : 1;
1162: }
1163:
1164: #ifdef TCP_CORK
1165: if (corked) {
1166: corked = 0;
1.1.1.3 ! misho 1167: (void)setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
1.1 misho 1168: }
1169: #endif
1170:
1171: written = cq->bytes_out - written;
1172: con->bytes_written += written;
1173: con->bytes_written_cur_second += written;
1174:
1175: *(con->conf.global_bytes_per_second_cnt_ptr) += written;
1176:
1177: return ret;
1178: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>