core.c revision 6de8046f8f7e07cd83895a528df25d977e502c76
967e5f3c25249c779575864692935627004d3f9eChristian Maeder/* Copyright 2001-2004 The Apache Software Foundation
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * Licensed under the Apache License, Version 2.0 (the "License");
75a6279dbae159d018ef812185416cf6df386c10Till Mossakowski * you may not use this file except in compliance with the License.
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * You may obtain a copy of the License at
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * http://www.apache.org/licenses/LICENSE-2.0
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * Unless required by applicable law or agreed to in writing, software
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * distributed under the License is distributed on an "AS IS" BASIS,
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * See the License for the specific language governing permissions and
967e5f3c25249c779575864692935627004d3f9eChristian Maeder * limitations under the License.
8b9fda012e5ee53b7b2320c0638896a0ff6e99f3Christian Maeder#include "apr_thread_proc.h" /* for RLIMIT stuff */
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder#include "http_protocol.h" /* For index_of_response(). Grump. */
dea4c92f0c061d589c542d0640a18dab36dfbb46Christian Maeder#include "http_main.h" /* For the default_handler below... */
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder/* LimitXMLRequestBody handling */
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder#define AP_DEFAULT_LIMIT_XML_BODY ((size_t)1000000)
4fb19f237193a3bd6778f8aee3b6dd8da5856665Christian MaederAP_IMPLEMENT_HOOK_RUN_ALL(int, get_mgmt_items,
7a879b08ae0ca30006f9be887a73212b07f10204Christian Maeder (apr_pool_t *p, const char *val, apr_hash_t *ht),
e1839fb37a3a2ccd457464cb0dcc5efd466dbe22Christian Maeder/* Server core module... This module provides support for really basic
e1839fb37a3a2ccd457464cb0dcc5efd466dbe22Christian Maeder * server operations, including options and commands which control the
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder * operation of other modules. Consider this the bureaucracy module.
2a598ff0c1b7b51c33aee7029b43bc5cfcbea6b8Christian Maeder * The core module also defines handlers, etc., do handle just enough
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder * to allow a server with the core module ONLY to actually serve documents
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder * (though it slaps DefaultType on all of 'em); this was useful in testing,
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder * but may not be worth preserving.
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder * This file could almost be mod_core.c, except for the stuff which affects
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder * the http_conf_globals.
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian Maeder/* Handles for core filters */
5e26bfc8d7b18cf3a3fa7b919b4450fb669f37a5Christian MaederAP_DECLARE_DATA ap_filter_rec_t *ap_subreq_core_filter_handle;
e7ce154edb906685b3fa7f6c0a764e18a4658068Christian MaederAP_DECLARE_DATA ap_filter_rec_t *ap_core_output_filter_handle;
e7ce154edb906685b3fa7f6c0a764e18a4658068Christian MaederAP_DECLARE_DATA ap_filter_rec_t *ap_content_length_filter_handle;
07b72edb610ee53b4832d132e96b0a3d8423f8ebChristian MaederAP_DECLARE_DATA ap_filter_rec_t *ap_net_time_filter_handle;
07b72edb610ee53b4832d132e96b0a3d8423f8ebChristian MaederAP_DECLARE_DATA ap_filter_rec_t *ap_core_input_filter_handle;
e7ce154edb906685b3fa7f6c0a764e18a4658068Christian Maederstatic void *create_core_dir_config(apr_pool_t *a, char *dir)
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder conf = (core_dir_config *)apr_pcalloc(a, sizeof(core_dir_config));
e7ce154edb906685b3fa7f6c0a764e18a4658068Christian Maeder /* conf->r and conf->d[_*] are initialized by dirsection() or left NULL */
4fb19f237193a3bd6778f8aee3b6dd8da5856665Christian Maeder conf->opts = dir ? OPT_UNSET : OPT_UNSET|OPT_ALL;
4fb19f237193a3bd6778f8aee3b6dd8da5856665Christian Maeder conf->opts_add = conf->opts_remove = OPT_NONE;
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder conf->override = dir ? OR_UNSET : OR_UNSET|OR_ALL;
967e5f3c25249c779575864692935627004d3f9eChristian Maeder conf->use_canonical_name = USE_CANONICAL_NAME_UNSET;
a578ec30cded5e396a7ce9a3b469e8cd3a88246aChristian Maeder conf->hostname_lookups = HOSTNAME_LOOKUP_UNSET;
e1839fb37a3a2ccd457464cb0dcc5efd466dbe22Christian Maeder#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
a89e661aad28f1b39f4fc9f9f9a4d46074234123Christian Maeder conf->sec_file = apr_array_make(a, 2, sizeof(ap_conf_vector_t *));
07b72edb610ee53b4832d132e96b0a3d8423f8ebChristian Maeder conf->add_default_charset = ADD_DEFAULT_CHARSET_UNSET;
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder conf->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder /* Overriding all negotiation
842eedc62639561781b6c33533d1949693ef6cc5Christian Maeder * Flag for use of inodes in ETags.
842eedc62639561781b6c33533d1949693ef6cc5Christian Maeder conf->enable_sendfile = ENABLE_SENDFILE_UNSET;
4fb19f237193a3bd6778f8aee3b6dd8da5856665Christian Maeder return (void *)conf;
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder * Overlay one hash table of ct_output_filters onto another
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maederstatic void *merge_ct_filters(apr_pool_t *p,
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder const ap_filter_rec_t *overlay_info = (const ap_filter_rec_t *)overlay_val;
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder const ap_filter_rec_t *base_info = (const ap_filter_rec_t *)base_val;
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder new = apr_pcalloc(p, sizeof(ap_filter_rec_t));
0a8ea95bcf0e3f84fed0b725c049ec2a956a4a28Christian Maeder new->name = apr_pstrdup(p, overlay_info->name);
967e5f3c25249c779575864692935627004d3f9eChristian Maeder /* We can't have dups. */
dedabc954aa15f6ad0764472a9434dc6dafe3db2Christian Maeder if (!strcasecmp(base_info->name, f->name)) {
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder f = apr_pcalloc(p, sizeof(ap_filter_rec_t));
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maederstatic void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder core_dir_config *base = (core_dir_config *)basev;
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder core_dir_config *new = (core_dir_config *)newv;
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder /* Create this conf by duplicating the base, replacing elements
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder * (or creating copies for merging) where new-> values exist.
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder conf = (core_dir_config *)apr_palloc(a, sizeof(core_dir_config));
4fb19f237193a3bd6778f8aee3b6dd8da5856665Christian Maeder memcpy(conf, base, sizeof(core_dir_config));
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder /* there was no explicit setting of new->opts, so we merge
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder * preserve the invariant (opts_add & opts_remove) == 0
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder conf->opts_add = (conf->opts_add & ~new->opts_remove) | new->opts_add;
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder conf->opts_remove = (conf->opts_remove & ~new->opts_add)
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder conf->opts = (conf->opts & ~conf->opts_remove) | conf->opts_add;
2dfc7b04f2db681992ca04175f2beb0f127c9844Christian Maeder if ((base->opts & OPT_INCNOEXEC) && (new->opts & OPT_INCLUDES)) {
7221c71b38c871ce66eee4537cb681d468308dfbChristian Maeder conf->opts = (conf->opts & ~OPT_INCNOEXEC) | OPT_INCLUDES;
4fb19f237193a3bd6778f8aee3b6dd8da5856665Christian Maeder /* otherwise we just copy, because an explicit opts setting
4fb19f237193a3bd6778f8aee3b6dd8da5856665Christian Maeder * overrides all earlier +/- modifiers
07b72edb610ee53b4832d132e96b0a3d8423f8ebChristian Maeder conf->ap_default_type = new->ap_default_type;
for (i = 0; i < RESPONSE_CODES; ++i) {
#ifdef RLIMIT_CPU
#ifdef RLIMIT_NPROC
NULL);
return (void*)conf;
#ifdef GPROF
return (void *)conf;
return conf;
&core_module);
&core_module);
struct reorder_sort_rec {
int orig_index;
int nelts;
if (!nelts) {
for (i = 0; i < nelts; ++i) {
for (i = 0; i < nelts; ++i) {
&core_module);
&core_module);
&core_module);
&core_module);
&core_module);
&core_module);
&core_module);
&core_module);
return NULL;
while (sa) {
int hostname_lookups;
int ignored_str_is_ip;
*str_is_ip = 0;
if (dir_config) {
== APR_SUCCESS) {
return NULL;
return NULL;
if (ident_lookup) {
return ident_lookup(r);
return NULL;
core_dir_config *d;
&core_module);
#if APR_HAVE_IPV6
return plain_server_name;
core_dir_config *d =
ap_default_port(r);
ap_default_port(r);
return port;
request_rec *r)
core_dir_config *d =
return d->limit_req_body;
* Commands... this module handles almost all of the NCSA httpd.conf
* commands, but most of the old srm.conf is in the the modules.
const char *what)
return dirp;
return NULL;
unsigned forbidden)
return NULL;
return NULL;
const char *arg)
return err;
return NULL;
#ifdef GPROF
return err;
return NULL;
return err;
return NULL;
const char *arg)
return err;
arg);
return NULL;
const char *string)
int idx;
return err;
* http_protocol.c relies on to distinguish between
return NULL;
return err;
return NULL;
char action;
action = *(w++);
else if (first) {
first = 0;
return NULL;
const char *args_p)
char action;
char *token;
const char *args;
int valid;
int first;
int explicit;
explicit = 0;
token++;
if (first) {
first = 0;
valid = 0;
valid = 0;
if (! valid) {
NULL);
if (explicit) {
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
return NULL;
return NULL;
require_line *r;
if (!c->ap_requires) {
return NULL;
void *dummy,
const char *arg)
const char *limited_methods;
const char *errmsg;
return err;
while (limited_methods[0]) {
int methnum;
return errmsg;
#ifdef WIN32
#define USE_ICASE 0
const char *errmsg;
return err;
if (!arg) {
char *newpath;
return errmsg;
conf->r = r;
return NULL;
const char *errmsg;
return err;
return errmsg;
conf->r = r;
return NULL;
const char *errmsg;
return err;
if (!old_path) {
char *newpath;
return errmsg;
conf->r = r;
return NULL;
if (not) {
arg++;
const char *retval;
return retval;
char **defines;
const char *endp;
int not = 0;
arg++;
const char *retval;
return retval;
/* httpd.conf commands... beginning with the <VirtualHost> business */
const char *arg)
const char *errmsg;
return err;
if (errmsg) {
return errmsg;
s->lookup_defaults);
return errmsg;
const char *arg)
while (*arg) {
return NULL;
const char *arg)
return err;
return NULL;
const char *portstr;
int port;
return err;
if (portstr) {
portstr++;
port = 0;
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
return NULL;
return err;
return NULL;
return err;
return NULL;
const char *arg)
return err;
return NULL;
const char *arg)
return err;
return NULL;
return err;
return NULL;
return NULL;
const char *arg)
return err;
return NULL;
const char *name)
if (!conffile) {
return NULL;
char *str;
return err;
return NULL;
&core_module);
const char *word1)
return NULL;
static int version_locked = 0;
enum server_token_type {
version_locked = 0;
return APR_SUCCESS;
if (! version_locked) {
const char *arg)
return err;
return NULL;
const char *arg)
int lim;
return err;
if (lim < 0) {
return NULL;
const char *arg)
int lim;
return err;
if (lim < 0) {
NULL);
return NULL;
const char *arg)
int lim;
return err;
if (lim < 0) {
NULL);
return NULL;
const char *arg)
char *errp;
return err;
* Instead we have an idiotic define in httpd.h that prevents
return NULL;
const char *arg)
return err;
return NULL;
return AP_DEFAULT_LIMIT_XML_BODY;
#if !defined (RLIMIT_CPU) || !(defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)) || !defined (RLIMIT_NPROC)
return NULL;
#ifdef RLIMIT_CPU
return NULL;
#if defined(RLIMIT_AS)
return NULL;
#ifdef RLIMIT_NPROC
return NULL;
&core_module);
if (limit <= 0) {
if (arg2) {
if (limit <= 0) {
return NULL;
&core_module);
log_backtrace(r);
log_backtrace(r);
const char *filter_name;
if (old) {
while (*arg &&
if (old) {
if (!new) {
return NULL;
const char *ctype;
&core_module);
if (ctype) {
while (ct_filter) {
*nbytes = 0;
*nbytes += n;
bytes_written += n;
return rv;
if (n < cnt) {
return APR_SUCCESS;
#if APR_HAS_SENDFILE
#ifdef AP_DEBUG
== APR_SUCCESS)
*bytes_sent = 0;
flags);
tmplen = 0;
file_bytes_left = 0;
file_offset = 0;
tmplen = 0;
apr_int32_t i;
*nbytes = 0;
sendlen = 0;
return rv;
#ifdef GPROF
"Set to on or off for PATH_INFO to be accepted by handlers, or default for the per-handler preference"),
#ifdef RLIMIT_CPU
#ifdef RLIMIT_NPROC
* #defined them in mpm.h.
#ifdef AP_MPM_WANT_SET_PIDFILE
#ifdef AP_MPM_WANT_SET_SCOREBOARD
#ifdef AP_MPM_WANT_SET_LOCKFILE
#ifdef AP_MPM_WANT_SET_MAX_REQUESTS
#ifdef AP_MPM_WANT_SET_COREDUMPDIR
#ifdef AP_MPM_WANT_SET_MAX_MEM_FREE
{ NULL }
if (r->proxyreq) {
return HTTP_FORBIDDEN;
return HTTP_BAD_REQUEST;
/* skip all leading /'s (e.g. http://localhost///foo)
++path;
!= APR_SUCCESS) {
return HTTP_FORBIDDEN;
/* skip all leading /'s (e.g. http://localhost///foo)
++path;
!= APR_SUCCESS) {
return HTTP_FORBIDDEN;
return OK;
int access_status;
return access_status;
return access_status;
return OK;
&core_module);
return OK;
apr_bucket *e;
core_dir_config *d;
int errstatus;
int bld_content_md5;
&core_module);
return errstatus;
return HTTP_NOT_FOUND;
return HTTP_NOT_FOUND;
return HTTP_NOT_FOUND;
r->method);
return HTTP_METHOD_NOT_ALLOWED;
#if APR_HAS_SENDFILE
? 0 : APR_SENDFILE_ENABLED)
return HTTP_FORBIDDEN;
ap_set_etag(r);
return errstatus;
if (bld_content_md5) {
#if APR_HAS_SENDFILE
c->bucket_alloc);
#if APR_HAS_MMAP
(void)apr_bucket_file_enable_mmap(e, 0);
return HTTP_NOT_IMPLEMENTED;
return ap_send_http_options(r);
return HTTP_METHOD_NOT_ALLOWED;
typedef struct net_time_filter_ctx {
int first_line;
if (!ctx) {
if (keptalive) {
#define BRIGADE_NORMALIZE(b) \
apr_bucket *d; \
d = APR_BUCKET_NEXT(e); \
apr_bucket_delete(e); \
e = APR_BUCKET_NEXT(e); \
apr_bucket *e;
const char *str;
return APR_SUCCESS;
if (!ctx)
return APR_EOF;
return APR_EOF;
return rv;
apr_bucket *e;
return APR_EOF;
return rv;
c = str;
if (*c == APR_ASCII_LF)
return APR_SUCCESS;
return APR_SUCCESS;
apr_bucket *e;
APR_BRIGADE_INSERT_TAIL(b, e);
return APR_SUCCESS;
apr_bucket *e;
return APR_SUCCESS;
return rv;
APR_BRIGADE_INSERT_TAIL(b, e);
return APR_SUCCESS;
return rv;
e = APR_BUCKET_NEXT(e))
return rv;
return APR_SUCCESS;
conn_rec *c = f->c;
if (ctx->b) {
b = ctx->b;
while (b && !APR_BRIGADE_EMPTY(b)) {
apr_bucket *e;
for (e = APR_BRIGADE_FIRST(b);
e != APR_BRIGADE_SENTINEL(b);
e = APR_BUCKET_NEXT(e))
last_e = e;
if (APR_BUCKET_IS_EOS(e)) {
if (APR_BUCKET_IS_FLUSH(e)) {
if (e != APR_BRIGADE_LAST(b)) {
else if (APR_BUCKET_IS_FILE(e)
if (fd) {
const char *str;
apr_size_t n;
if (!fd) {
if (last_merged_bucket) {
temp_brig = b;
b = bb;
f->c->bucket_alloc);
while (temp != e) {
apr_bucket *d;
d = temp;
nvec = 0;
nbytes = 0;
nvec++;
nvec++;
e = temp;
last_e = e;
nvec++;
nbytes += n;
int file_bucket_saved = 0;
const char *buf;
return HTTP_INTERNAL_SERVER_ERROR;
return APR_SUCCESS;
if (fd) {
#if APR_HAS_SENDFILE
if (nvec) {
if (nvec_trailers) {
#if APR_HAS_SENDFILE
&bytes_sent);
if (more)
return APR_SUCCESS;
b = more;
return APR_SUCCESS;
return OK;
&core_module);
if (filters) {
if (filters) {
return APR_SUCCESS;
return num_request_notes++;
return NULL;
if (!req_cfg) {
return NULL;
sizeof(void *) * num_request_notes);
if (r->main) {
if (!r->prev) {
return OK;
!= APR_SUCCESS) {
return NULL;
!= APR_SUCCESS) {
return NULL;
net->c = c;
return DONE;