diff options
Diffstat (limited to 'src/network.c')
-rw-r--r-- | src/network.c | 236 |
1 files changed, 118 insertions, 118 deletions
diff --git a/src/network.c b/src/network.c index 5b21b83..ba024aa 100644 --- a/src/network.c +++ b/src/network.c @@ -21,9 +21,9 @@ #include "sys-socket.h" #ifdef USE_OPENSSL -# include <openssl/ssl.h> -# include <openssl/err.h> -# include <openssl/rand.h> +# include <openssl/ssl.h> +# include <openssl/err.h> +# include <openssl/rand.h> #endif handler_t network_server_handle_fdevent(void *s, void *context, int revents) { @@ -31,11 +31,11 @@ handler_t network_server_handle_fdevent(void *s, void *context, int revents) { server_socket *srv_socket = (server_socket *)context; connection *con; int loops = 0; - + UNUSED(context); - + if (revents != FDEVENT_IN) { - log_error_write(srv, __FILE__, __LINE__, "sdd", + log_error_write(srv, __FILE__, __LINE__, "sdd", "strange event for server socket", srv_socket->fd, revents); @@ -44,12 +44,12 @@ handler_t network_server_handle_fdevent(void *s, void *context, int revents) { /* accept()s at most 100 connections directly * - * we jump out after 100 to give the waiting connections a chance */ + * we jump out after 100 to give the waiting connections a chance */ for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) { handler_t r; - + connection_state_machine(srv, con); - + switch(r = plugins_call_handle_joblist(srv, con)) { case HANDLER_FINISHED: case HANDLER_GO_ON: @@ -72,7 +72,7 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { buffer *b; int is_unix_domain_socket = 0; int fd; - + #ifdef SO_ACCEPTFILTER struct accept_filter_arg afa; #endif @@ -81,9 +81,9 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { WORD wVersionRequested; WSADATA wsaData; int err; - + wVersionRequested = MAKEWORD( 2, 2 ); - + err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { /* Tell the user that we could not find a usable */ @@ -91,37 +91,37 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { return -1; } #endif - + srv_socket = calloc(1, sizeof(*srv_socket)); srv_socket->fd = -1; - + srv_socket->srv_token = buffer_init(); buffer_copy_string_buffer(srv_socket->srv_token, host_token); - + b = buffer_init(); buffer_copy_string_buffer(b, host_token); - - /* ipv4:port + + /* ipv4:port * [ipv6]:port */ if (NULL == (sp = strrchr(b->ptr, ':'))) { log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b); - + return -1; } - + host = b->ptr; - + /* check for [ and ] */ if (b->ptr[0] == '[' && *(sp-1) == ']') { *(sp-1) = '\0'; host++; - + s->use_ipv6 = 1; } - + *(sp++) = '\0'; - + port = strtol(sp, NULL, 10); if (host[0] == '/') { @@ -129,17 +129,17 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { is_unix_domain_socket = 1; } else if (port == 0 || port > 65535) { log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port); - + return -1; } - + if (*host == '\0') host = NULL; if (is_unix_domain_socket) { #ifdef HAVE_SYS_UN_H srv_socket->addr.plain.sa_family = AF_UNIX; - + if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) { log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno)); return -1; @@ -154,7 +154,7 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { #ifdef HAVE_IPV6 if (s->use_ipv6) { srv_socket->addr.plain.sa_family = AF_INET6; - + if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) { log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno)); return -1; @@ -162,7 +162,7 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { srv_socket->use_ipv6 = 1; } #endif - + if (srv_socket->fd == -1) { srv_socket->addr.plain.sa_family = AF_INET; if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) { @@ -170,16 +170,16 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { return -1; } } - + /* */ srv->cur_fds = srv_socket->fd; - + val = 1; if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) { log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno)); return -1; } - + switch(srv_socket->addr.plain.sa_family) { #ifdef HAVE_IPV6 case AF_INET6: @@ -190,23 +190,23 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { } else { struct addrinfo hints, *res; int r; - + memset(&hints, 0, sizeof(hints)); - + hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; - + if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) { - log_error_write(srv, __FILE__, __LINE__, - "sssss", "getaddrinfo failed: ", + log_error_write(srv, __FILE__, __LINE__, + "sssss", "getaddrinfo failed: ", gai_strerror(r), "'", host, "'"); - + return -1; } - + memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen); - + freeaddrinfo(res); } srv_socket->addr.ipv6.sin6_port = htons(port); @@ -221,33 +221,33 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { } else { struct hostent *he; if (NULL == (he = gethostbyname(host))) { - log_error_write(srv, __FILE__, __LINE__, - "sds", "gethostbyname failed: ", + log_error_write(srv, __FILE__, __LINE__, + "sds", "gethostbyname failed: ", h_errno, host); return -1; } - + if (he->h_addrtype != AF_INET) { log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype); return -1; } - + if (he->h_length != sizeof(struct in_addr)) { log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length); return -1; } - + memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length); } srv_socket->addr.ipv4.sin_port = htons(port); - + addr_len = sizeof(struct sockaddr_in); - + break; case AF_UNIX: srv_socket->addr.un.sun_family = AF_UNIX; strcpy(srv_socket->addr.un.sun_path, host); - + #ifdef SUN_LEN addr_len = SUN_LEN(&srv_socket->addr.un); #else @@ -259,8 +259,8 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) { close(fd); - log_error_write(srv, __FILE__, __LINE__, "ss", - "server socket is still in use:", + log_error_write(srv, __FILE__, __LINE__, "ss", + "server socket is still in use:", host); @@ -275,8 +275,8 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { case ENOENT: break; default: - log_error_write(srv, __FILE__, __LINE__, "sds", - "testing socket failed:", + log_error_write(srv, __FILE__, __LINE__, "sds", + "testing socket failed:", host, strerror(errno)); return -1; @@ -285,47 +285,47 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { break; default: addr_len = 0; - + return -1; } - + if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) { switch(srv_socket->addr.plain.sa_family) { case AF_UNIX: - log_error_write(srv, __FILE__, __LINE__, "sds", - "can't bind to socket:", + log_error_write(srv, __FILE__, __LINE__, "sds", + "can't bind to socket:", host, strerror(errno)); break; default: - log_error_write(srv, __FILE__, __LINE__, "ssds", - "can't bind to port:", + log_error_write(srv, __FILE__, __LINE__, "ssds", + "can't bind to port:", host, port, strerror(errno)); break; } return -1; } - + if (-1 == listen(srv_socket->fd, 128 * 8)) { log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno)); return -1; } - + if (s->is_ssl) { #ifdef USE_OPENSSL if (srv->ssl_is_init == 0) { SSL_load_error_strings(); SSL_library_init(); srv->ssl_is_init = 1; - + if (0 == RAND_status()) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "not enough entropy in the pool"); return -1; } } - + if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return -1; } @@ -347,34 +347,34 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { return -1; } } - + if (buffer_is_empty(s->ssl_pemfile)) { log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set"); return -1; } - + if (!buffer_is_empty(s->ssl_ca_file)) { if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) { - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file); return -1; } } - + if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) { - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); return -1; } - + if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) { - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); return -1; } - + if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) { - log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:", "Private key does not match the certificate public key, reason:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); @@ -385,15 +385,15 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { srv_socket->ssl_ctx = s->ssl_ctx; #else - + buffer_free(srv_socket->srv_token); free(srv_socket); - + buffer_free(b); - - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "ssl requested but openssl support is not compiled in"); - + return -1; #endif } else { @@ -411,10 +411,10 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { } #endif } - + srv_socket->is_ssl = s->is_ssl; srv_socket->fde_ndx = -1; - + if (srv->srv_sockets.size == 0) { srv->srv_sockets.size = 4; srv->srv_sockets.used = 0; @@ -423,11 +423,11 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { srv->srv_sockets.size += 4; srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket)); } - + srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket; - + buffer_free(b); - + return 0; } @@ -435,24 +435,24 @@ int network_close(server *srv) { size_t i; for (i = 0; i < srv->srv_sockets.used; i++) { server_socket *srv_socket = srv->srv_sockets.ptr[i]; - + if (srv_socket->fd != -1) { /* check if server fd are already registered */ if (srv_socket->fde_ndx != -1) { fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd); fdevent_unregister(srv->ev, srv_socket->fd); } - + close(srv_socket->fd); } - + buffer_free(srv_socket->srv_token); - + free(srv_socket); } - + free(srv->srv_sockets.ptr); - + return 0; } @@ -469,11 +469,11 @@ int network_init(server *srv) { buffer *b; size_t i; network_backend_t backend; - - struct nb_map { - network_backend_t nb; - const char *name; - } network_backends[] = { + + struct nb_map { + network_backend_t nb; + const char *name; + } network_backends[] = { /* lowest id wins */ #if defined USE_LINUX_SENDFILE { NETWORK_BACKEND_LINUX_SENDFILE, "linux-sendfile" }, @@ -490,18 +490,18 @@ int network_init(server *srv) { { NETWORK_BACKEND_WRITE, "write" }, { NETWORK_BACKEND_UNSET, NULL } }; - + b = buffer_init(); - + buffer_copy_string_buffer(b, srv->srvconf.bindhost); buffer_append_string(b, ":"); buffer_append_long(b, srv->srvconf.port); - + if (0 != network_server_init(srv, b, srv->config_storage[0])) { return -1; } buffer_free(b); - + #ifdef USE_OPENSSL srv->network_ssl_backend_write = network_write_chunkqueue_openssl; #endif @@ -521,8 +521,8 @@ int network_init(server *srv) { if (NULL == network_backends[i].name) { /* we don't know it */ - log_error_write(srv, __FILE__, __LINE__, "sb", - "server.network-backend has a unknown value:", + log_error_write(srv, __FILE__, __LINE__, "sb", + "server.network-backend has a unknown value:", srv->srvconf.network_backend); return -1; @@ -540,17 +540,17 @@ int network_init(server *srv) { #endif #ifdef USE_LINUX_SENDFILE case NETWORK_BACKEND_LINUX_SENDFILE: - srv->network_backend_write = network_write_chunkqueue_linuxsendfile; + srv->network_backend_write = network_write_chunkqueue_linuxsendfile; break; #endif #ifdef USE_FREEBSD_SENDFILE case NETWORK_BACKEND_FREEBSD_SENDFILE: - srv->network_backend_write = network_write_chunkqueue_freebsdsendfile; + srv->network_backend_write = network_write_chunkqueue_freebsdsendfile; break; #endif #ifdef USE_SOLARIS_SENDFILEV case NETWORK_BACKEND_SOLARIS_SENDFILEV: - srv->network_backend_write = network_write_chunkqueue_solarissendfilev; + srv->network_backend_write = network_write_chunkqueue_solarissendfilev; break; #endif default: @@ -562,13 +562,13 @@ int network_init(server *srv) { data_config *dc = (data_config *)srv->config_context->data[i]; specific_config *s = srv->config_storage[i]; size_t j; - + /* not our stage */ if (COMP_SERVER_SOCKET != dc->comp) continue; - + if (dc->cond != CONFIG_COND_EQ) { log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"]."); - + return -1; } @@ -579,26 +579,26 @@ int network_init(server *srv) { break; } } - + if (j == srv->srv_sockets.used) { if (0 != network_server_init(srv, dc->string, s)) return -1; } } - + return 0; } int network_register_fdevents(server *srv) { size_t i; - + if (-1 == fdevent_reset(srv->ev)) { return -1; } - + /* register fdevents after reset */ for (i = 0; i < srv->srv_sockets.used; i++) { server_socket *srv_socket = srv->srv_sockets.ptr[i]; - + fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket); fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN); } @@ -608,7 +608,7 @@ int network_register_fdevents(server *srv) { int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) { int ret = -1; off_t written = 0; -#ifdef TCP_CORK +#ifdef TCP_CORK int corked = 0; #endif server_socket *srv_socket = con->srv_socket; @@ -621,11 +621,11 @@ int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) { joblist_append(srv, con); return 1; - } + } written = cq->bytes_out; -#ifdef TCP_CORK +#ifdef TCP_CORK /* Linux: put a cork into the socket as we want to combine the write() calls * but only if we really have multiple chunks */ @@ -634,7 +634,7 @@ int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) { setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked)); } #endif - + if (srv_socket->is_ssl) { #ifdef USE_OPENSSL ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq); @@ -642,12 +642,12 @@ int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) { } else { ret = srv->network_backend_write(srv, con, con->fd, cq); } - + if (ret >= 0) { chunkqueue_remove_finished_chunks(cq); ret = chunkqueue_is_empty(cq) ? 0 : 1; } - + #ifdef TCP_CORK if (corked) { corked = 0; @@ -660,13 +660,13 @@ int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) { con->bytes_written_cur_second += written; *(con->conf.global_bytes_per_second_cnt_ptr) += written; - + if (con->conf.kbytes_per_second && (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) { /* we reached the traffic limit */ con->traffic_limit_reached = 1; joblist_append(srv, con); - } + } return ret; } |