From: Paul Querna Date: Tue, 14 Jun 2005 09:21:18 +0000 (+0000) Subject: Merge the listen-protocol sandbox branch to trunk. X-Git-Tag: 2.1.5~12 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6a23d6ebeb82bb83f7ab3ebbd10f07dc77423939;p=apache Merge the listen-protocol sandbox branch to trunk. I will be adding documentation for the new directives hopefully in the next day or so. * server/core.c: Added 'Protocol' to the core module config Added ap_{set,get}_server_protocol API. Added new directive: 'AcceptFilter'. Enable 'httpready' by default on systems that support it. Use dataready filters for others. * server/listen.c: Attempt to inherit protocols from Listener Records to Server configs. The 'Listen' directive can now optionally take a protocol arg Move bits that determined which accept filter is applied to core.c. Added bits to find the correct accept filter based on the core's configuration. * include/{ap_listen.h,http_core.h}: Add Protocol to respective structures. * include/http_core.h: Add the accf_map table to the core_server_config structure * include/ap_mmn.h: Minor MMN Bump for the new interfacces. * modules/ssl/ssl_engine_init.c: Use the new protocol framework to enable mod_ssl for 'https' websites. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@190563 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index c8b7ec4621..672b804caa 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,14 @@ Changes with Apache 2.1.5 [Remove entries to the current 2.0 section below, when backported] + *) mod_ssl: Setting the Protocol to 'https' can replace the use of the + 'SSLEngine on' command. [Paul Querna] + + *) core: Refactor the mapping of Accept Filters to Sockets. Add the + AcceptFilter and Protocol directives to aid in mapping filter types. + Extend the Listen directive to optionally take a protocol name. + [Paul Querna] + *) mod_disk_cache: Support storing multiple variations of one URL. PR 35211. [Paul Querna] diff --git a/include/ap_listen.h b/include/ap_listen.h index 7f456c569d..d98949f379 100644 --- a/include/ap_listen.h +++ b/include/ap_listen.h @@ -53,7 +53,10 @@ struct ap_listen_rec { * Is this socket currently active */ int active; -/* more stuff here, like which protocol is bound to the port */ + /** + * The default protocol for this listening socket. + */ + const char* protocol; }; /** @@ -82,7 +85,8 @@ AP_DECLARE(int) ap_setup_listeners(server_rec *s); * called. */ AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd, void *dummy, const char *arg); -AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, const char *ips); +AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, + int argc, char *const argv[]); AP_DECLARE_NONSTD(const char *) ap_set_send_buffer_size(cmd_parms *cmd, void *dummy, const char *arg); AP_DECLARE_NONSTD(const char *) ap_set_receive_buffer_size(cmd_parms *cmd, @@ -92,8 +96,8 @@ AP_DECLARE_NONSTD(const char *) ap_set_receive_buffer_size(cmd_parms *cmd, #define LISTEN_COMMANDS \ AP_INIT_TAKE1("ListenBacklog", ap_set_listenbacklog, NULL, RSRC_CONF, \ "Maximum length of the queue of pending connections, as used by listen(2)"), \ -AP_INIT_TAKE1("Listen", ap_set_listener, NULL, RSRC_CONF, \ - "A port number or a numeric IP address and a port number"), \ +AP_INIT_TAKE_ARGV("Listen", ap_set_listener, NULL, RSRC_CONF, \ + "A port number or a numeric IP address and a port number, and an optional protocol"), \ AP_INIT_TAKE1("SendBufferSize", ap_set_send_buffer_size, NULL, RSRC_CONF, \ "Send buffer size in bytes"), \ AP_INIT_TAKE1("ReceiveBufferSize", ap_set_receive_buffer_size, NULL, \ diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 96245efe0d..f6e3c72208 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -95,6 +95,7 @@ * 20050305.0 (2.1.4-dev) added pid and generation fields to worker_score * 20050305.1 (2.1.5-dev) added ap_vhost_iterate_given_conn. * 20050305.2 (2.1.5-dev) added AP_INIT_TAKE_ARGV. + * 20050305.3 (2.1.5-dev) added Protocol Framework. */ #define MODULE_MAGIC_COOKIE 0x41503230UL /* "AP20" */ @@ -102,7 +103,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20050305 #endif -#define MODULE_MAGIC_NUMBER_MINOR 2 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 3 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/http_core.h b/include/http_core.h index 175055d51c..e22b7bb909 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -548,6 +548,9 @@ typedef struct { /* recursion backstopper */ int redirect_limit; /* maximum number of internal redirects */ int subreq_limit; /* maximum nesting level of subrequests */ + + const char *protocol; + apr_table_t *accf_map; } core_server_config; /* for AddOutputFiltersByType in core.c */ @@ -573,6 +576,8 @@ apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *b); #endif /* CORE_PRIVATE */ +AP_DECLARE(const char*) ap_get_server_protocol(server_rec* s); +AP_DECLARE(void) ap_set_server_protocol(server_rec* s, const char* proto); /* ---------------------------------------------------------------------- * diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index 90094df44f..148c07c889 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -207,6 +207,10 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, sc->vhost_id = ssl_util_vhostid(p, s); sc->vhost_id_len = strlen(sc->vhost_id); + if (strcmp("https", ap_get_server_protocol(s)) == 0) { + sc->enabled = SSL_ENABLED_TRUE; + } + /* If sc->enabled is UNSET, then SSL is optional on this vhost */ /* Fix up stuff that may not have been set */ if (sc->enabled == SSL_ENABLED_UNSET) { @@ -879,7 +883,8 @@ static void ssl_init_server_certs(server_rec *s, if (!(have_rsa || have_dsa)) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "Oops, no RSA or DSA server certificate found?!"); + "Oops, no RSA or DSA server certificate found " + "for '%s:%d'?!", s->server_hostname, s->port); ssl_die(); } diff --git a/server/core.c b/server/core.c index 34acc9922c..2bf34fbe28 100644 --- a/server/core.c +++ b/server/core.c @@ -460,6 +460,28 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s) conf->redirect_limit = 0; /* 0 == unset */ conf->subreq_limit = 0; + conf->protocol = NULL; + conf->accf_map = apr_table_make(a, 5); + +#ifdef APR_TCP_DEFER_ACCEPT + apr_table_set(conf->accf_map, "http", "data"); + apr_table_set(conf->accf_map, "https", "data"); +#endif + +#if APR_HAS_SO_ACCEPTFILTER +#ifndef ACCEPT_FILTER_NAME +#define ACCEPT_FILTER_NAME "httpready" +#ifdef __FreeBSD_version +#if __FreeBSD_version < 411000 /* httpready broken before 4.1.1 */ +#undef ACCEPT_FILTER_NAME +#define ACCEPT_FILTER_NAME "dataready" +#endif +#endif +#endif + apr_table_set(conf->accf_map, "http", ACCEPT_FILTER_NAME); + apr_table_set(conf->accf_map, "https", "dataready"); +#endif + return (void *)conf; } @@ -480,6 +502,10 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv) conf->ap_document_root = base->ap_document_root; } + if (!conf->protocol) { + conf->protocol = base->protocol; + } + conf->sec_dir = apr_array_append(p, base->sec_dir, virt->sec_dir); conf->sec_url = apr_array_append(p, base->sec_url, virt->sec_url); @@ -490,7 +516,6 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv) conf->subreq_limit = virt->subreq_limit ? virt->subreq_limit : base->subreq_limit; - return conf; } @@ -2182,6 +2207,60 @@ static const char *set_server_alias(cmd_parms *cmd, void *dummy, return NULL; } +static const char *set_accf_map(cmd_parms *cmd, void *dummy, + const char *iproto, const char* iaccf) +{ + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + core_server_config *conf = ap_get_module_config(cmd->server->module_config, + &core_module); + char* proto; + char* accf; + if (err != NULL) { + return err; + } + + proto = apr_pstrdup(cmd->pool, iproto); + ap_str_tolower(proto); + accf = apr_pstrdup(cmd->pool, iaccf); + ap_str_tolower(accf); + apr_table_set(conf->accf_map, proto, accf); + + return NULL; +} + +AP_DECLARE(const char*) ap_get_server_protocol(server_rec* s) +{ + core_server_config *conf = ap_get_module_config(s->module_config, + &core_module); + return conf->protocol; +} + +AP_DECLARE(void) ap_set_server_protocol(server_rec* s, const char* proto) +{ + core_server_config *conf = ap_get_module_config(s->module_config, + &core_module); + conf->protocol = proto; +} + +static const char *set_protocol(cmd_parms *cmd, void *dummy, + const char *arg) +{ + const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT); + core_server_config *conf = ap_get_module_config(cmd->server->module_config, + &core_module); + char* proto; + + if (err != NULL) { + return err; + } + + proto = apr_pstrdup(cmd->pool, arg); + ap_str_tolower(proto); + conf->protocol = proto; + + return NULL; +} + static const char *set_server_string_slot(cmd_parms *cmd, void *dummy, const char *arg) { @@ -3120,6 +3199,10 @@ AP_INIT_TAKE1("EnableSendfile", set_enable_sendfile, NULL, OR_FILEINFO, /* Old server config file commands */ +AP_INIT_TAKE1("Protocol", set_protocol, NULL, RSRC_CONF, + "Set the Protocol for httpd to use."), +AP_INIT_TAKE2("AcceptFilter", set_accf_map, NULL, RSRC_CONF, + "Set the Accept Filter to use for a protocol"), AP_INIT_TAKE1("Port", ap_set_deprecated, NULL, RSRC_CONF, "Port was replaced with Listen in Apache 2.0"), AP_INIT_TAKE1("HostnameLookups", set_hostname_lookups, NULL, diff --git a/server/listen.c b/server/listen.c index 64b7505484..6a3ee9e7bf 100644 --- a/server/listen.c +++ b/server/listen.c @@ -24,6 +24,7 @@ #include "ap_config.h" #include "httpd.h" #include "http_config.h" +#include "http_core.h" #include "ap_listen.h" #include "http_log.h" #include "mpm.h" @@ -167,32 +168,6 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server) } #endif -#if APR_HAS_SO_ACCEPTFILTER -#ifndef ACCEPT_FILTER_NAME -#define ACCEPT_FILTER_NAME "httpready" -#ifdef __FreeBSD_version -#if __FreeBSD_version < 411000 /* httpready broken before 4.1.1 */ -#undef ACCEPT_FILTER_NAME -#define ACCEPT_FILTER_NAME "dataready" -#endif -#endif -#endif - stat = apr_socket_accept_filter(s, ACCEPT_FILTER_NAME, ""); - if (stat != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(stat)) { - ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p, - "Failed to enable the '%s' Accept Filter", - ACCEPT_FILTER_NAME); - } -#else -#ifdef APR_TCP_DEFER_ACCEPT - stat = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 1); - if (stat != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(stat)) { - ap_log_perror(APLOG_MARK, APLOG_WARNING, stat, p, - "Failed to enable APR_TCP_DEFER_ACCEPT"); - } -#endif -#endif - server->sd = s; server->active = 1; @@ -205,6 +180,62 @@ static apr_status_t make_sock(apr_pool_t *p, ap_listen_rec *server) return APR_SUCCESS; } +static const char* find_accf_name(server_rec *s, const char *proto) +{ + const char* accf; + core_server_config *conf = ap_get_module_config(s->module_config, + &core_module); + if (!proto) { + return NULL; + } + + accf = apr_table_get(conf->accf_map, proto); + + if (accf && !strcmp("none", accf)) { + return NULL; + } + + return accf; +} + +static void ap_apply_accept_filter(apr_pool_t *p, ap_listen_rec *lis, + server_rec *server) +{ + apr_socket_t *s = lis->sd; + const char *accf; + apr_status_t rv; + const char *proto; + + proto = lis->protocol; + + if (!proto) { + proto = ap_get_server_protocol(server); + } + + + accf = find_accf_name(server, proto); + + if (accf) { +#if APR_HAS_SO_ACCEPTFILTER + rv = apr_socket_accept_filter(s, apr_pstrdup(p, accf), + apr_pstrdup(p,"")); + if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) { + ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p, + "Failed to enable the '%s' Accept Filter", + accf); + } +#else +#ifdef APR_TCP_DEFER_ACCEPT + rv = apr_socket_opt_set(s, APR_TCP_DEFER_ACCEPT, 1); + if (rv != APR_SUCCESS && !APR_STATUS_IS_ENOTIMPL(rv)) { + ap_log_perror(APLOG_MARK, APLOG_WARNING, rv, p, + "Failed to enable APR_TCP_DEFER_ACCEPT"); + } +#endif +#endif + } +} + static apr_status_t close_listeners_on_exec(void *v) { ap_listen_rec *lr; @@ -218,7 +249,8 @@ static apr_status_t close_listeners_on_exec(void *v) } -static const char *alloc_listener(process_rec *process, char *addr, apr_port_t port) +static const char *alloc_listener(process_rec *process, char *addr, + apr_port_t port, const char* proto) { ap_listen_rec **walk, *last; apr_status_t status; @@ -279,6 +311,7 @@ static const char *alloc_listener(process_rec *process, char *addr, apr_port_t p new->active = 0; new->next = 0; new->bind_addr = sa; + new->protocol = apr_pstrdup(process->pool, proto); /* Go to the next sockaddr. */ sa = sa->next; @@ -451,8 +484,37 @@ static int open_listeners(apr_pool_t *pool) AP_DECLARE(int) ap_setup_listeners(server_rec *s) { + server_rec *ls; + server_addr_rec *addr; ap_listen_rec *lr; int num_listeners = 0; + const char* proto; + int found; + + for (ls = s; ls; ls = ls->next) { + proto = ap_get_server_protocol(ls); + if (!proto) { + found = 0; + /* No protocol was set for this vhost, + * use the default for this listener. + */ + for (addr = ls->addrs; addr && !found; addr = addr->next) { + for (lr = ap_listeners; lr; lr = lr->next) { + if (apr_sockaddr_equal(lr->bind_addr, addr->host_addr) && + lr->bind_addr->port == addr->host_port) { + ap_set_server_protocol(ls, lr->protocol); + found = 1; + break; + } + } + } + + if (!found) { + /* TODO: set protocol defaults per-Port, eg 25=smtp */ + ap_set_server_protocol(ls, "http"); + } + } + } if (open_listeners(s->process->pool)) { return 0; @@ -460,6 +522,20 @@ AP_DECLARE(int) ap_setup_listeners(server_rec *s) for (lr = ap_listeners; lr; lr = lr->next) { num_listeners++; + found = 0; + for (ls = s; ls && !found; ls = ls->next) { + for (addr = ls->addrs; addr && !found; addr = addr->next) { + if (apr_sockaddr_equal(lr->bind_addr, addr->host_addr) && + lr->bind_addr->port == addr->host_port) { + found = 1; + ap_apply_accept_filter(s->process->pool, lr, ls); + } + } + } + + if (!found) { + ap_apply_accept_filter(s->process->pool, lr, s); + } } return num_listeners; @@ -474,9 +550,9 @@ AP_DECLARE(void) ap_listen_pre_config(void) AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, - const char *ips) + int argc, char *const argv[]) { - char *host, *scope_id; + char *host, *scope_id, *proto; apr_port_t port; apr_status_t rv; const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); @@ -485,7 +561,11 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, return err; } - rv = apr_parse_addr_port(&host, &scope_id, &port, ips, cmd->pool); + if (argc < 1 || argc > 2) { + return "Listen requires 1 or 2 arguments."; + } + + rv = apr_parse_addr_port(&host, &scope_id, &port, argv[0], cmd->pool); if (rv != APR_SUCCESS) { return "Invalid address or port"; } @@ -503,7 +583,15 @@ AP_DECLARE_NONSTD(const char *) ap_set_listener(cmd_parms *cmd, void *dummy, return "Port must be specified"; } - return alloc_listener(cmd->server->process, host, port); + if (argc != 2) { + proto = "http"; + } + else { + proto = apr_pstrdup(cmd->pool, argv[1]); + ap_str_tolower(proto); + } + + return alloc_listener(cmd->server->process, host, port, proto); } AP_DECLARE_NONSTD(const char *) ap_set_listenbacklog(cmd_parms *cmd,