/* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2000-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . * * Portions of this software are based upon public domain software * originally written at the National Center for Supercomputing Applications, * University of Illinois, Urbana-Champaign. */ /* * mod_sockopts: control SO_RCVBUF and TCP_DEFER_ACCEPT * * v1.0 * * author: dean gaudet */ // dunno why ap_check_cmd_context is private... #define CORE_PRIVATE #include "httpd.h" #include "http_config.h" #include "http_log.h" #include "http_request.h" #include "http_conf_globals.h" #include #include #include #include typedef struct { int receive_buffer_size; int tcp_defer_accept; unsigned receive_buffer_size_set : 1; unsigned tcp_defer_accept_set : 1; } sockopts_config; module MODULE_VAR_EXPORT sockopts_module; static const char *set_receive_buffer_size(cmd_parms *cmd, void *dummy, char *arg) { sockopts_config *config = ap_get_module_config(cmd->server->module_config, &sockopts_module); int s = atoi(arg); const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } if (s < 512 && s != 0) { return "ReceiveBufferSize must be >= 512 bytes, or 0 for system default."; } config->receive_buffer_size = s; config->receive_buffer_size_set = 1; return NULL; } static const char *set_tcp_defer_accept(cmd_parms *cmd, void *dummy, char *arg) { #ifdef TCP_DEFER_ACCEPT sockopts_config *config = ap_get_module_config(cmd->server->module_config, &sockopts_module); int s = atoi(arg); const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } config->tcp_defer_accept = s; config->tcp_defer_accept_set = 1; return NULL; #else return "TCP_DEFER_ACCEPT not supported on your platform"; #endif } static void *sockopts_create_config(pool *p, server_rec *s) { return ap_pcalloc(p, sizeof(sockopts_config)); } static void *sockopts_merge_config(pool *p, void *parentv, void *childv) { sockopts_config *parent = (sockopts_config *) parentv; sockopts_config *child = (sockopts_config *) childv; sockopts_config *config; config = (sockopts_config *)ap_palloc(p, sizeof(*config)); *config = *parent; if (child->receive_buffer_size_set) { config->receive_buffer_size_set = 1; config->receive_buffer_size = child->receive_buffer_size; } if (child->tcp_defer_accept_set) { config->tcp_defer_accept_set = 1; config->tcp_defer_accept = child->tcp_defer_accept; } return config; } static void sockopts_init(server_rec *s, pool *p) { sockopts_config *config = ap_get_module_config(s->module_config, &sockopts_module); listen_rec *lr; int val; lr = ap_listeners; if (lr == NULL) { return; } do { // apache initialization sequence is such a mess... we end up // in here once before any listeners have been allocated... so // we don't want to try to setsockopt then. if (lr->fd != -1) { if (config->receive_buffer_size_set) { val = config->receive_buffer_size; if (setsockopt(lr->fd, SOL_SOCKET, SO_RCVBUF, (char *)&val, sizeof(int)) < 0) { ap_log_error(APLOG_MARK, APLOG_WARNING, s, "failed to setsockopt(SOL_SOCKET, SO_RCVBUF)"); } } #ifdef TCP_DEFER_ACCEPT if (config->tcp_defer_accept_set) { val = config->tcp_defer_accept; if (setsockopt(lr->fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, (char *)&val, sizeof(int)) < 0) { ap_log_error(APLOG_MARK, APLOG_WARNING, s, "failed to setsockopt(IPPROTO_TCP, TCP_DEFER_ACCEPT)"); } } #endif } lr = lr->next; } while (lr && lr != ap_listeners); } static const command_rec sockopts_cmds[] = { { "ReceiveBufferSize", set_receive_buffer_size, NULL, RSRC_CONF, TAKE1, "Receive buffer size in bytes" }, { "TCPDeferAccept", set_tcp_defer_accept, NULL, RSRC_CONF, TAKE1, "TCP_DEFER_ACCEPT setting in seconds (see tcp(7))" }, {NULL} }; module MODULE_VAR_EXPORT sockopts_module = { STANDARD_MODULE_STUFF, sockopts_init, /* module initializer */ NULL, /* per-directory config creator */ NULL, /* dir config merger */ sockopts_create_config, /* server config creator */ sockopts_merge_config, /* server config merger */ sockopts_cmds, /* command table */ NULL, /* [9] list of handlers */ NULL, /* [2] filename-to-URI translation */ NULL, /* [5] check/validate user_id */ NULL, /* [6] check user_id is valid *here* */ NULL, /* [4] check access by host address */ NULL, /* [7] MIME type checker/setter */ NULL, /* [8] fixups */ NULL /* [10] logger */ #if MODULE_MAGIC_NUMBER >= 19970103 ,NULL /* [3] header parser */ #endif #if MODULE_MAGIC_NUMBER >= 19970719 ,NULL /* process initializer */ #endif #if MODULE_MAGIC_NUMBER >= 19970728 ,NULL /* process exit/cleanup */ #endif #if MODULE_MAGIC_NUMBER >= 19970902 ,NULL /* [1] post read_request handling */ #endif };