vhost.c revision e08076ca56e6cb68b30846b9e9339061058aae6d
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor/* Licensed to the Apache Software Foundation (ASF) under one or more
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * contributor license agreements. See the NOTICE file distributed with
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * this work for additional information regarding copyright ownership.
a99c5d4cc3cab6a62b04d52000dbc22ce1fa2d94coar * The ASF licenses this file to You under the Apache License, Version 2.0
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * (the "License"); you may not use this file except in compliance with
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * the License. You may obtain a copy of the License at
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * Unless required by applicable law or agreed to in writing, software
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * distributed under the License is distributed on an "AS IS" BASIS,
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * See the License for the specific language governing permissions and
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * limitations under the License.
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * @brief functions pertaining to virtual host addresses
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * (configuration and run-time)
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * After all the definitions there's an explanation of how it's all put
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * together.
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor/* meta-list of name-vhosts. Each server_rec can be in possibly multiple
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * lists of name-vhosts.
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor server_addr_rec *sar; /* the record causing it to be in
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * this chain (needed for port comparisons) */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor server_rec *server; /* the server to use on a match */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor/* meta-list of ip addresses. Each server_rec can be in possibly multiple
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * hash chains since it can have multiple ips.
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor server_addr_rec *sar; /* the record causing it to be in
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * this chain (need for both ip addr and port
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * comparisons) */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor server_rec *server; /* the server to use if this matches */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor name_chain *names; /* if non-NULL then a list of name-vhosts
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * sharing this address */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor/* This defines the size of the hash table used for hashing ip addresses
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * of virtual hosts. It must be a power of two.
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor/* A (n) bucket hash table, each entry has a pointer to a server rec and
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * a pointer to the other entries in that bucket. Each individual address,
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * even for virtualhosts with multiple addresses, has an entry in this hash
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * table. There are extra buckets for _default_, and name-vhost entries.
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * Note that after config time this is constant, so it is thread-safe.
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor/* dump out statistics about the hash function */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor/* #define IPHASH_STATISTICS */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor/* list of the _default_ servers */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor/* list of the NameVirtualHost addresses */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor/* whether a config error was seen */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzorstatic int config_error = 0;
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor/* config check function */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzorstatic int vhost_check_config(apr_pool_t *p, apr_pool_t *plog,
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * How it's used:
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * The ip address determines which chain in iphash_table is interesting, then
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * a comparison is done down that chain to find the first ipaddr_chain whose
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * sar matches the address:port pair.
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * If that ipaddr_chain has names == NULL then you're done, it's an ip-vhost.
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * Otherwise it's a name-vhost list, and the default is the server in the
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * ipaddr_chain record. We tuck away the ipaddr_chain record in the
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * conn_rec field vhost_lookup_data. Later on after the headers we get a
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * second chance, and we use the name_chain to figure out what name-vhost
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * matches the headers.
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * If there was no ip address match in the iphash_table then do a lookup
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * in the default_list.
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * How it's put together ... well you should be able to figure that out
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * from how it's used. Or something like that.
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor/* called at the beginning of the config */
2dda612e9e4715a5deca6a897b50b937d0403f16lgentis ap_hook_check_config(vhost_check_config, NULL, NULL, APR_HOOK_MIDDLE);
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * Parses a host of the form <address>[:port]
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * paddr is used to create a list in the order of input
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * **paddr is the ->next pointer of the last entry (or s->addrs)
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * *paddr is the variable used to keep track of **paddr between calls
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * port is the default port to assume
32f5dfaca53f31a4ccb791a811607367ce16e832gryzorstatic const char *get_addresses(apr_pool_t *p, const char *w_,
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor /* apr_parse_addr_port() doesn't understand ":*" so handle that first. */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor wlen = strlen(w); /* wlen must be > 0 at this point */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor rv = apr_parse_addr_port(&host, &scope_id, &port, w, p);
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor /* If the string is "80", apr_parse_addr_port() will be happy and set
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor * host to NULL and port to 80, so watch out for that.
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor return "The address or port is invalid";
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor return "Missing address for VirtualHost";
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor return "Scope ids are not supported";
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor rv = apr_sockaddr_info_get(&my_addr, "0.0.0.0", APR_INET, port, 0, p);
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor return "Could not resolve address '0.0.0.0' -- "
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor "check resolver configuration.";
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor rv = apr_sockaddr_info_get(&my_addr, "255.255.255.255", APR_INET, port, 0, p);
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor return "Could not resolve address '255.255.255.255' -- "
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor "check resolver configuration.";
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor rv = apr_sockaddr_info_get(&my_addr, host, APR_UNSPEC, port, 0, p);
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor "Could not resolve host name %s -- ignoring!", host);
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor /* Remember all addresses for the host */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor/* parse the <VirtualHost> addresses */
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor const char *hostname,
32f5dfaca53f31a4ccb791a811607367ce16e832gryzor const char *err;
while (hostname[0]) {
if (err) {
return err;
if (s->addrs) {
return NULL;
void *dummy,
const char *arg)
#ifdef IPHASH_STATISTICS
static int iphash_compare(const void *a, const void *b)
unsigned total;
total = 0;
for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
count[i] = 0;
++count[i];
if (i < IPHASH_TABLE_SIZE) {
++total;
++total;
unsigned key;
return new;
return new;
unsigned bucket;
return trav;
return NULL;
return trav;
return NULL;
int len;
if (name[i]) {
if (name[i]) {
for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
if (default_list) {
while (*pic) {
server_rec *s;
s = main_s;
if (!s->server_hostname) {
for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
if (!ic) {
if (!s->server_hostname) {
if (has_default_vhost_addr) {
else if (!s->addrs) {
s->server_hostname =
char *hostname;
char *ipaddr_str;
s->server_hostname =
for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
#ifdef IPHASH_STATISTICS
char *dst;
if (!*r->hostname) {
goto bad;
if (port) {
goto bad;
goto bad;
bad:
if (names) {
if(!name[i]) continue;
if (names) {
if(!name[i]) continue;
server_rec *s;
s = r->server;
server_rec *s;
* do the full ServerName/ServerAlias comparisons once for each
goto found;
if (s == last_s) {
last_s = s;
goto found;
r->server = s;
server_rec *s;
if (s == last_s) {
last_s = s;
r->server = s;
fix_hostname(r);
if (r->hostname)
check_hostalias(r);
check_serverpath(r);
void* baton)
server_rec *s;
int rv = 0;
if (s == last_s) {
last_s = s;
if (rv != 0) {
return rv;
if (trav) {
if (trav) {