vhost.c revision b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44c
57221209d11b05aa0373cc3892d5df89ba96ebf9Christian Maeder/* ====================================================================
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly * Redistribution and use in source and binary forms, with or without
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly * modification, are permitted provided that the following conditions
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly * 1. Redistributions of source code must retain the above copyright
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly * notice, this list of conditions and the following disclaimer.
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly * 2. Redistributions in binary form must reproduce the above copyright
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly * notice, this list of conditions and the following disclaimer in
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly * the documentation and/or other materials provided with the
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly * distribution.
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly * 3. All advertising materials mentioning features or use of this
57221209d11b05aa0373cc3892d5df89ba96ebf9Christian Maeder * software must display the following acknowledgment:
66bc8d6e69cde43f1ccbeb76104cf7b8038acd6cChristian Maeder * "This product includes software developed by the Apache Group
66bc8d6e69cde43f1ccbeb76104cf7b8038acd6cChristian Maeder * for use in the Apache HTTP server project (http://www.apache.org/)."
d5833d2ee7bafcbf2fdd2bdfd9a728c769b100c7Christian Maeder * 4. The names "Apache Server" and "Apache Group" must not be used to
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly * endorse or promote products derived from this software without
56899f6457976a2ee20f6a23f088cb5655b15715Liam O'Reilly * prior written permission. For written permission, please contact
66bc8d6e69cde43f1ccbeb76104cf7b8038acd6cChristian Maeder * apache@apache.org.
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly * 5. Products derived from this software may not be called "Apache"
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly * nor may "Apache" appear in their names without prior written
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly * permission of the Apache Group.
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * 6. Redistributions of any form whatsoever must retain the following
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder * acknowledgment:
f21c7417bdd1c0282025cba0f5cb0ff5bc5c98eeLiam O'Reilly * "This product includes software developed by the Apache Group
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * for use in the Apache HTTP server project (http://www.apache.org/)."
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
c0833539c8cf577dd3f2497792fbdd818442744cChristian Maeder * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
fa373bc327620e08861294716b4454be8d25669fChristian Maeder * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
036ecbd8f721096321f47cf6a354a9d1bf3d032fChristian Maeder * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
fa373bc327620e08861294716b4454be8d25669fChristian Maeder * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
f21c7417bdd1c0282025cba0f5cb0ff5bc5c98eeLiam O'Reilly * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly * OF THE POSSIBILITY OF SUCH DAMAGE.
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly * ====================================================================
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly * This software consists of voluntary contributions made by many
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly * individuals on behalf of the Apache Group and was originally based
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly * on public domain software written at the National Center for
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * Supercomputing Applications, University of Illinois, Urbana-Champaign.
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * For more information on the Apache Group and the Apache HTTP server
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * project, please see <http://www.apache.org/>.
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * http_vhost.c: functions pertaining to virtual host addresses
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * (configuration and run-time)
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * After all the definitions there's an explanation of how it's all put
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly/* meta-list of name-vhosts. Each server_rec can be in possibly multiple
fa373bc327620e08861294716b4454be8d25669fChristian Maeder * lists of name-vhosts.
fa373bc327620e08861294716b4454be8d25669fChristian Maeder server_addr_rec *sar; /* the record causing it to be in
fa373bc327620e08861294716b4454be8d25669fChristian Maeder * this chain (needed for port comparisons) */
fa373bc327620e08861294716b4454be8d25669fChristian Maeder server_rec *server; /* the server to use on a match */
fa373bc327620e08861294716b4454be8d25669fChristian Maeder/* meta-list of ip addresses. Each server_rec can be in possibly multiple
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * hash chains since it can have multiple ips.
7857a35e3af533dfbd0f0e18638ebd211e6358a0Christian Maeder server_addr_rec *sar; /* the record causing it to be in
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly * this chain (need for both ip addr and port
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * comparisons) */
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder server_rec *server; /* the server to use if this matches */
7857a35e3af533dfbd0f0e18638ebd211e6358a0Christian Maeder name_chain *names; /* if non-NULL then a list of name-vhosts
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * sharing this address */
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder/* This defines the size of the hash ap_table_t used for hashing ip addresses
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * of virtual hosts. It must be a power of two.
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder/* A (n) bucket hash table, each entry has a pointer to a server rec and
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * a pointer to the other entries in that bucket. Each individual address,
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maeder * even for virtualhosts with multiple addresses, has an entry in this hash
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maeder * table. There are extra buckets for _default_, and name-vhost entries.
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maeder * Note that after config time this is constant, so it is thread-safe.
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maederstatic ipaddr_chain *iphash_table[IPHASH_TABLE_SIZE];
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maeder/* dump out statistics about the hash function */
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maeder/* #define IPHASH_STATISTICS */
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder/* list of the _default_ servers */
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder/* list of the NameVirtualHost addresses */
648fe1220044aac847acbdfbc4155af5556063ebChristian Maederstatic server_addr_rec **name_vhost_list_tail;
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * How it's used:
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * The ip address determines which chain in iphash_table is interesting, then
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * a comparison is done down that chain to find the first ipaddr_chain whose
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * sar matches the address:port pair.
4314e26a12954cb1c9be4dea10aa8103edac5bbbChristian Maeder * If that ipaddr_chain has names == NULL then you're done, it's an ip-vhost.
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * Otherwise it's a name-vhost list, and the default is the server in the
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * ipaddr_chain record. We tuck away the ipaddr_chain record in the
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly * conn_rec field vhost_lookup_data. Later on after the headers we get a
d5833d2ee7bafcbf2fdd2bdfd9a728c769b100c7Christian Maeder * second chance, and we use the name_chain to figure out what name-vhost
d5833d2ee7bafcbf2fdd2bdfd9a728c769b100c7Christian Maeder * matches the headers.
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * If there was no ip address match in the iphash_table then do a lookup
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * in the default_list.
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * How it's put together ... well you should be able to figure that out
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * from how it's used. Or something like that.
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder/* called at the beginning of the config */
7857a35e3af533dfbd0f0e18638ebd211e6358a0Christian Maeder memset(iphash_table, 0, sizeof(iphash_table));
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * Parses a host of the form <address>[:port]
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * paddr is used to create a list in the order of input
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * **paddr is the ->next pointer of the last entry (or s->addrs)
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * *paddr is the variable used to keep track of **paddr between calls
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * port is the default port to assume
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reillystatic const char *get_addresses(ap_context_t *p, char *w, server_addr_rec ***paddr,
f21c7417bdd1c0282025cba0f5cb0ff5bc5c98eeLiam O'Reilly unsigned long my_addr;
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly return ":port must be numeric";
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly else if ((my_addr = ap_inet_addr(w)) != INADDR_NONE) {
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, NULL,
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly "Cannot resolve host name %s --- ignoring!", w);
fa373bc327620e08861294716b4454be8d25669fChristian Maeder sar = ap_pcalloc(p, sizeof(server_addr_rec));
fa373bc327620e08861294716b4454be8d25669fChristian Maeder sar->host_addr = *(struct in_addr *) hep->h_addr_list[i];
fa373bc327620e08861294716b4454be8d25669fChristian Maeder/* parse the <VirtualHost> addresses */
fa373bc327620e08861294716b4454be8d25669fChristian Maederconst char *ap_parse_vhost_addrs(ap_context_t *p, const char *hostname, server_rec *s)
fa373bc327620e08861294716b4454be8d25669fChristian Maeder /* start the list of addreses */
fa373bc327620e08861294716b4454be8d25669fChristian Maeder err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port);
fa373bc327620e08861294716b4454be8d25669fChristian Maeder /* terminate the list */
fa373bc327620e08861294716b4454be8d25669fChristian Maeder /* override the default port which is inherited from main_server */
fa373bc327620e08861294716b4454be8d25669fChristian Maederconst char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *arg)
fa373bc327620e08861294716b4454be8d25669fChristian Maeder /* use whatever port the main server has at this point */
fa373bc327620e08861294716b4454be8d25669fChristian Maeder return get_addresses(cmd->pool, arg, &name_vhost_list_tail,
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder/* hash ap_table_t statistics, keep this in here for the beta period so
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder * we can find out if the hash function is ok
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maederstatic int iphash_compare(const void *a, const void *b)
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder return (*(const int *) b - *(const int *) a);
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maederstatic void dump_iphash_statistics(server_rec *main_s)
66bc8d6e69cde43f1ccbeb76104cf7b8038acd6cChristian Maeder for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
66bc8d6e69cde43f1ccbeb76104cf7b8038acd6cChristian Maeder for (src = iphash_table[i]; src; src = src->next) {
ace03c3051e5c5144e43ae78cae73f6a29dde6d5Christian Maeder /* don't count the slop buckets in the total */
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder qsort(count, IPHASH_TABLE_SIZE, sizeof(count[0]), iphash_compare);
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder "iphash: total hashed = %u, avg chain = %u, "
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder "chain lengths (count x len):",
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly p += ap_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly p += ap_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, main_s, buf);
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder/* This hashing function is designed to get good distribution in the cases
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder * where the server is handling entire "networks" of servers. i.e. a
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder * whack of /24s. This is probably the most common configuration for
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder * ISPs with large virtual servers.
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder * NOTE: This function is symmetric (i.e. collapses all 4 octets
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder * into one), so machine byte order (big/little endianness) does not matter.
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder * Hash function provided by David Hankins.
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maederstatic ap_inline unsigned hash_inaddr(unsigned key)
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE;
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maederstatic ipaddr_chain *new_ipaddr_chain(ap_context_t *p,
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reillystatic name_chain *new_name_chain(ap_context_t *p, server_rec *s, server_addr_rec *sar)
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reillystatic ap_inline ipaddr_chain *find_ipaddr(struct in_addr *server_ip,
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly /* scan the hash ap_table_t for an exact match first */
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly for (trav = iphash_table[bucket]; trav; trav = trav->next) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly && (sar->host_port == 0 || sar->host_port == port
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reillystatic ipaddr_chain *find_default_server(unsigned port)
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly for (trav = default_list; trav; trav = trav->next) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly if (sar->host_port == 0 || sar->host_port == port) {
dd7da1b5fedc05b92ba023ebd803e6f4a662503bChristian Maeder ap_fprintf(f, "VirtualHost configuration:\n");
dd7da1b5fedc05b92ba023ebd803e6f4a662503bChristian Maeder for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly for (ic = iphash_table[i]; ic; ic = ic->next) {
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly ap_snprintf(buf, sizeof(buf), "%pA:*", &ic->sar->host_addr);
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ap_snprintf(buf, sizeof(buf), "%pA:%u", &ic->sar->host_addr,
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ic->server->server_hostname, ic->server->defn_name,
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly "%22s default server %s (%s:%u)\n",
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ic->server->defn_name, ic->server->defn_line_number);
d5833d2ee7bafcbf2fdd2bdfd9a728c769b100c7Christian Maeder ap_fprintf(f, "%22s port %u ", "", nc->sar->host_port);
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder ap_fprintf(f, "port %u ", ic->sar->host_port);
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ic->server->server_hostname, ic->server->defn_name,
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder/* compile the tables and such we need to do the run-time vhost lookups */
bcd914850de931848b86d7728192a149f9c0108bChristian Maedervoid ap_fini_vhost_config(ap_context_t *p, server_rec *main_s)
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder ipaddr_chain **iphash_table_tail[IPHASH_TABLE_SIZE];
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder /* terminate the name_vhost list */
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder /* Main host first */
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly /* initialize the tails */
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly /* The first things to go into the hash ap_table_t are the NameVirtualHosts
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly * Since name_vhost_list is in the same order that the directives
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly * occured in the config file, we'll copy it in that order.
else if (ic) {
if (!s->server_hostname) {
if (has_default_vhost_addr) {
else if (!s->addrs) {
s->server_hostname =
struct hostent *h;
s->server_hostname =
for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
while (*pic) {
#ifdef IPHASH_STATISTICS
const char *src;
char *dst;
while (*src) {
goto bad;
while (*src) {
goto bad;
bad:
if (names) {
if(!name[i]) continue;
if (names) {
if(!name[i]) continue;
unsigned port)
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);
if (trav) {
if (trav) {