vhost.c revision b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44c
57221209d11b05aa0373cc3892d5df89ba96ebf9Christian Maeder/* ====================================================================
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly *
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
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu Prodescu * are met:
53bd0c89aa4743dc41a6394db5a90717c1ca4517Liam O'Reilly *
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 *
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.
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly *
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/)."
e90dc723887d541f809007ae81c9bb73ced9592eChristian Maeder *
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.
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder *
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 *
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/)."
d5833d2ee7bafcbf2fdd2bdfd9a728c769b100c7Christian Maeder *
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 *
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 *
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder */
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder/*
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * http_vhost.c: functions pertaining to virtual host addresses
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * (configuration and run-time)
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder */
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder#define CORE_PRIVATE
4314e26a12954cb1c9be4dea10aa8103edac5bbbChristian Maeder#include "httpd.h"
d5833d2ee7bafcbf2fdd2bdfd9a728c769b100c7Christian Maeder#include "http_config.h"
d5833d2ee7bafcbf2fdd2bdfd9a728c769b100c7Christian Maeder#include "http_log.h"
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly#include "http_vhost.h"
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly#include "http_protocol.h"
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly#include "http_core.h"
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder#include "ap_config.h"
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder/*
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * After all the definitions there's an explanation of how it's all put
d5833d2ee7bafcbf2fdd2bdfd9a728c769b100c7Christian Maeder * together.
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder */
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly/* meta-list of name-vhosts. Each server_rec can be in possibly multiple
fa373bc327620e08861294716b4454be8d25669fChristian Maeder * lists of name-vhosts.
fa373bc327620e08861294716b4454be8d25669fChristian Maeder */
fa373bc327620e08861294716b4454be8d25669fChristian Maedertypedef struct name_chain name_chain;
fa373bc327620e08861294716b4454be8d25669fChristian Maederstruct name_chain {
fa373bc327620e08861294716b4454be8d25669fChristian Maeder name_chain *next;
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};
fa373bc327620e08861294716b4454be8d25669fChristian Maeder
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.
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder */
d5833d2ee7bafcbf2fdd2bdfd9a728c769b100c7Christian Maedertypedef struct ipaddr_chain ipaddr_chain;
7857a35e3af533dfbd0f0e18638ebd211e6358a0Christian Maederstruct ipaddr_chain {
7857a35e3af533dfbd0f0e18638ebd211e6358a0Christian Maeder ipaddr_chain *next;
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};
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder
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 */
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder#ifndef IPHASH_TABLE_SIZE
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder#define IPHASH_TABLE_SIZE 256
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder#endif
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder
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 *
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maeder * Note that after config time this is constant, so it is thread-safe.
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder */
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maederstatic ipaddr_chain *iphash_table[IPHASH_TABLE_SIZE];
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maeder/* dump out statistics about the hash function */
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maeder/* #define IPHASH_STATISTICS */
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maeder
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder/* list of the _default_ servers */
648fe1220044aac847acbdfbc4155af5556063ebChristian Maederstatic ipaddr_chain *default_list;
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder/* list of the NameVirtualHost addresses */
648fe1220044aac847acbdfbc4155af5556063ebChristian Maederstatic server_addr_rec *name_vhost_list;
648fe1220044aac847acbdfbc4155af5556063ebChristian Maederstatic server_addr_rec **name_vhost_list_tail;
4314e26a12954cb1c9be4dea10aa8103edac5bbbChristian Maeder
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder/*
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * How it's used:
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder *
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.
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder *
4314e26a12954cb1c9be4dea10aa8103edac5bbbChristian Maeder * If that ipaddr_chain has names == NULL then you're done, it's an ip-vhost.
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder *
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 *
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * If there was no ip address match in the iphash_table then do a lookup
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder * in the default_list.
e0f1794e365dd347e97b37d7d22b2fce27296fa1Christian Maeder *
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 */
7857a35e3af533dfbd0f0e18638ebd211e6358a0Christian Maeder
7857a35e3af533dfbd0f0e18638ebd211e6358a0Christian Maeder
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder/* called at the beginning of the config */
648fe1220044aac847acbdfbc4155af5556063ebChristian Maedervoid ap_init_vhost_config(ap_context_t *p)
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder{
7857a35e3af533dfbd0f0e18638ebd211e6358a0Christian Maeder memset(iphash_table, 0, sizeof(iphash_table));
7857a35e3af533dfbd0f0e18638ebd211e6358a0Christian Maeder default_list = NULL;
7857a35e3af533dfbd0f0e18638ebd211e6358a0Christian Maeder name_vhost_list = NULL;
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder name_vhost_list_tail = &name_vhost_list;
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder}
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder/*
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
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder */
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reillystatic const char *get_addresses(ap_context_t *p, char *w, server_addr_rec ***paddr,
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly unsigned port)
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly{
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly struct hostent *hep;
f21c7417bdd1c0282025cba0f5cb0ff5bc5c98eeLiam O'Reilly unsigned long my_addr;
f21c7417bdd1c0282025cba0f5cb0ff5bc5c98eeLiam O'Reilly server_addr_rec *sar;
f21c7417bdd1c0282025cba0f5cb0ff5bc5c98eeLiam O'Reilly char *t;
f21c7417bdd1c0282025cba0f5cb0ff5bc5c98eeLiam O'Reilly int i, is_an_ip_addr;
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly if (*w == 0)
f21c7417bdd1c0282025cba0f5cb0ff5bc5c98eeLiam O'Reilly return NULL;
f21c7417bdd1c0282025cba0f5cb0ff5bc5c98eeLiam O'Reilly
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly t = strchr(w, ':');
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly if (t) {
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly if (strcmp(t + 1, "*") == 0) {
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly port = 0;
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly }
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly else if ((i = atoi(t + 1))) {
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly port = i;
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly }
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly else {
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly return ":port must be numeric";
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly }
f21c7417bdd1c0282025cba0f5cb0ff5bc5c98eeLiam O'Reilly *t = 0;
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly }
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly is_an_ip_addr = 0;
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly if (strcmp(w, "*") == 0) {
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly my_addr = htonl(INADDR_ANY);
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly is_an_ip_addr = 1;
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly }
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly else if (strcasecmp(w, "_default_") == 0
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly || strcmp(w, "255.255.255.255") == 0) {
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly my_addr = DEFAULT_VHOST_ADDR;
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly is_an_ip_addr = 1;
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly }
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly else if ((my_addr = ap_inet_addr(w)) != INADDR_NONE) {
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly is_an_ip_addr = 1;
7d96b1ef2b8597330aedee6713615ec15508edcfLiam O'Reilly }
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly if (is_an_ip_addr) {
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly sar = ap_pcalloc(p, sizeof(server_addr_rec));
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly **paddr = sar;
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly *paddr = &sar->next;
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly sar->host_addr.s_addr = my_addr;
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly sar->host_port = port;
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly sar->virthost = ap_pstrdup(p, w);
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly if (t != NULL)
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly *t = ':';
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly return NULL;
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly }
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly hep = gethostbyname(w);
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly
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);
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly if (t != NULL)
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly *t = ':';
f19dc06364e8d6ea36f7c170e1f7a0677de63184Liam O'Reilly return NULL;
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder }
fa373bc327620e08861294716b4454be8d25669fChristian Maeder
fa373bc327620e08861294716b4454be8d25669fChristian Maeder for (i = 0; hep->h_addr_list[i]; ++i) {
fa373bc327620e08861294716b4454be8d25669fChristian Maeder sar = ap_pcalloc(p, sizeof(server_addr_rec));
fa373bc327620e08861294716b4454be8d25669fChristian Maeder **paddr = sar;
fa373bc327620e08861294716b4454be8d25669fChristian Maeder *paddr = &sar->next;
fa373bc327620e08861294716b4454be8d25669fChristian Maeder sar->host_addr = *(struct in_addr *) hep->h_addr_list[i];
fa373bc327620e08861294716b4454be8d25669fChristian Maeder sar->host_port = port;
fa373bc327620e08861294716b4454be8d25669fChristian Maeder sar->virthost = ap_pstrdup(p, w);
fa373bc327620e08861294716b4454be8d25669fChristian Maeder }
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder
fa373bc327620e08861294716b4454be8d25669fChristian Maeder if (t != NULL)
fa373bc327620e08861294716b4454be8d25669fChristian Maeder *t = ':';
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder return NULL;
fa373bc327620e08861294716b4454be8d25669fChristian Maeder}
fa373bc327620e08861294716b4454be8d25669fChristian Maeder
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder
fa373bc327620e08861294716b4454be8d25669fChristian Maeder/* parse the <VirtualHost> addresses */
fa373bc327620e08861294716b4454be8d25669fChristian Maederconst char *ap_parse_vhost_addrs(ap_context_t *p, const char *hostname, server_rec *s)
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder{
fa373bc327620e08861294716b4454be8d25669fChristian Maeder server_addr_rec **addrs;
fa373bc327620e08861294716b4454be8d25669fChristian Maeder const char *err;
fa373bc327620e08861294716b4454be8d25669fChristian Maeder
fa373bc327620e08861294716b4454be8d25669fChristian Maeder /* start the list of addreses */
fa373bc327620e08861294716b4454be8d25669fChristian Maeder addrs = &s->addrs;
fa373bc327620e08861294716b4454be8d25669fChristian Maeder while (hostname[0]) {
fa373bc327620e08861294716b4454be8d25669fChristian Maeder err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port);
fa373bc327620e08861294716b4454be8d25669fChristian Maeder if (err) {
fa373bc327620e08861294716b4454be8d25669fChristian Maeder *addrs = NULL;
fa373bc327620e08861294716b4454be8d25669fChristian Maeder return err;
fa373bc327620e08861294716b4454be8d25669fChristian Maeder }
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder }
fa373bc327620e08861294716b4454be8d25669fChristian Maeder /* terminate the list */
fa373bc327620e08861294716b4454be8d25669fChristian Maeder *addrs = NULL;
fa373bc327620e08861294716b4454be8d25669fChristian Maeder if (s->addrs) {
fa373bc327620e08861294716b4454be8d25669fChristian Maeder if (s->addrs->host_port) {
fa373bc327620e08861294716b4454be8d25669fChristian Maeder /* override the default port which is inherited from main_server */
fa373bc327620e08861294716b4454be8d25669fChristian Maeder s->port = s->addrs->host_port;
fa373bc327620e08861294716b4454be8d25669fChristian Maeder }
fa373bc327620e08861294716b4454be8d25669fChristian Maeder }
fa373bc327620e08861294716b4454be8d25669fChristian Maeder return NULL;
fa373bc327620e08861294716b4454be8d25669fChristian Maeder}
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder
fa373bc327620e08861294716b4454be8d25669fChristian Maederconst char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *arg)
fa373bc327620e08861294716b4454be8d25669fChristian Maeder{
fa373bc327620e08861294716b4454be8d25669fChristian Maeder /* use whatever port the main server has at this point */
fa373bc327620e08861294716b4454be8d25669fChristian Maeder return get_addresses(cmd->pool, arg, &name_vhost_list_tail,
56899f6457976a2ee20f6a23f088cb5655b15715Liam O'Reilly cmd->server->port);
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder}
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder
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
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder */
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder#ifdef IPHASH_STATISTICS
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maederstatic int iphash_compare(const void *a, const void *b)
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder{
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder return (*(const int *) b - *(const int *) a);
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder}
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maederstatic void dump_iphash_statistics(server_rec *main_s)
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maeder{
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder unsigned count[IPHASH_TABLE_SIZE];
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder int i;
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder ipaddr_chain *src;
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder unsigned total;
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder char buf[HUGE_STRING_LEN];
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly char *p;
66bc8d6e69cde43f1ccbeb76104cf7b8038acd6cChristian Maeder
66bc8d6e69cde43f1ccbeb76104cf7b8038acd6cChristian Maeder total = 0;
66bc8d6e69cde43f1ccbeb76104cf7b8038acd6cChristian Maeder for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
66bc8d6e69cde43f1ccbeb76104cf7b8038acd6cChristian Maeder count[i] = 0;
66bc8d6e69cde43f1ccbeb76104cf7b8038acd6cChristian Maeder for (src = iphash_table[i]; src; src = src->next) {
66bc8d6e69cde43f1ccbeb76104cf7b8038acd6cChristian Maeder ++count[i];
66bc8d6e69cde43f1ccbeb76104cf7b8038acd6cChristian Maeder if (i < IPHASH_TABLE_SIZE) {
ace03c3051e5c5144e43ae78cae73f6a29dde6d5Christian Maeder /* don't count the slop buckets in the total */
ace03c3051e5c5144e43ae78cae73f6a29dde6d5Christian Maeder ++total;
ace03c3051e5c5144e43ae78cae73f6a29dde6d5Christian Maeder }
ace03c3051e5c5144e43ae78cae73f6a29dde6d5Christian Maeder }
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder }
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder qsort(count, IPHASH_TABLE_SIZE, sizeof(count[0]), iphash_compare);
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder p = buf + ap_snprintf(buf, sizeof(buf),
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder "iphash: total hashed = %u, avg chain = %u, "
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder "chain lengths (count x len):",
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly total, total / IPHASH_TABLE_SIZE);
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly total = 1;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly for (i = 1; i < IPHASH_TABLE_SIZE; ++i) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly if (count[i - 1] != count[i]) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly p += ap_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder total, count[i - 1]);
8e9c3881fb6e710b1e08bf5ac8ff9d393df2e74eChristian Maeder total = 1;
8e9c3881fb6e710b1e08bf5ac8ff9d393df2e74eChristian Maeder }
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder else {
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder ++total;
7830e8fa7442fb7452af7ecdba102bc297ae367eChristian Maeder }
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly }
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly p += ap_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
580f1724640a78be687e79d0ec95dd2665e77e91Liam O'Reilly total, count[IPHASH_TABLE_SIZE - 1]);
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, main_s, buf);
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder}
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder#endif
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder
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 *
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.
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder *
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder * Hash function provided by David Hankins.
2a5b885d9350ec6dd8bc4992ee91d2f68aa592f4Christian Maeder */
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maederstatic ap_inline unsigned hash_inaddr(unsigned key)
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder{
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder key ^= (key >> 16);
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE;
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder}
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maederstatic ipaddr_chain *new_ipaddr_chain(ap_context_t *p,
a00461fcf7432205a79a0f12dbe6c1ebc58bc000Christian Maeder server_rec *s, server_addr_rec *sar)
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly{
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ipaddr_chain *new;
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly new = ap_palloc(p, sizeof(*new));
57221209d11b05aa0373cc3892d5df89ba96ebf9Christian Maeder new->names = NULL;
57221209d11b05aa0373cc3892d5df89ba96ebf9Christian Maeder new->server = s;
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder new->sar = sar;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly new->next = NULL;
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maeder return new;
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder}
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maeder
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reillystatic name_chain *new_name_chain(ap_context_t *p, server_rec *s, server_addr_rec *sar)
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly{
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly name_chain *new;
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder new = ap_palloc(p, sizeof(*new));
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly new->server = s;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly new->sar = sar;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly new->next = NULL;
57221209d11b05aa0373cc3892d5df89ba96ebf9Christian Maeder return new;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly}
57221209d11b05aa0373cc3892d5df89ba96ebf9Christian Maeder
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reillystatic ap_inline ipaddr_chain *find_ipaddr(struct in_addr *server_ip,
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly unsigned port)
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly{
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly unsigned bucket;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ipaddr_chain *trav;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly unsigned addr;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly /* scan the hash ap_table_t for an exact match first */
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly addr = server_ip->s_addr;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly bucket = hash_inaddr(addr);
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly for (trav = iphash_table[bucket]; trav; trav = trav->next) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly server_addr_rec *sar = trav->sar;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly if ((sar->host_addr.s_addr == addr)
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly && (sar->host_port == 0 || sar->host_port == port
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly || port == 0)) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly return trav;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly return NULL;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly}
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reillystatic ipaddr_chain *find_default_server(unsigned port)
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly{
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly server_addr_rec *sar;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ipaddr_chain *trav;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly for (trav = default_list; trav; trav = trav->next) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly sar = trav->sar;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly if (sar->host_port == 0 || sar->host_port == port) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly /* match! */
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly return trav;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly return NULL;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly}
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly
57221209d11b05aa0373cc3892d5df89ba96ebf9Christian Maederstatic void dump_vhost_config(ap_file_t *f)
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly{
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly int i;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ipaddr_chain *ic;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly name_chain *nc;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly char buf[MAX_STRING_LEN];
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly
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) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly if (ic->sar->host_port == 0) {
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly ap_snprintf(buf, sizeof(buf), "%pA:*", &ic->sar->host_addr);
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly else {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ap_snprintf(buf, sizeof(buf), "%pA:%u", &ic->sar->host_addr,
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ic->sar->host_port);
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly if (ic->names == NULL) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ap_fprintf(f, "%-22s %s (%s:%u)\n", buf,
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ic->server->server_hostname, ic->server->defn_name,
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ic->server->defn_line_number);
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly continue;
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ap_fprintf(f, "%-22s is a NameVirtualHost\n"
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly "%22s default server %s (%s:%u)\n",
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly buf, "", ic->server->server_hostname,
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ic->server->defn_name, ic->server->defn_line_number);
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly for (nc = ic->names; nc; nc = nc->next) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly if (nc->sar->host_port) {
d5833d2ee7bafcbf2fdd2bdfd9a728c769b100c7Christian Maeder ap_fprintf(f, "%22s port %u ", "", nc->sar->host_port);
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly }
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder else {
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder ap_fprintf(f, "%22s port * ", "");
d5833d2ee7bafcbf2fdd2bdfd9a728c769b100c7Christian Maeder }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ap_fprintf(f, "namevhost %s (%s:%u)\n",
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder nc->server->server_hostname,
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder nc->server->defn_name,
d5833d2ee7bafcbf2fdd2bdfd9a728c769b100c7Christian Maeder nc->server->defn_line_number);
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly }
d5833d2ee7bafcbf2fdd2bdfd9a728c769b100c7Christian Maeder }
d5833d2ee7bafcbf2fdd2bdfd9a728c769b100c7Christian Maeder if (default_list) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ap_fprintf(f, "_default_ servers:\n");
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly for (ic = default_list; ic; ic = ic->next) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly if (ic->sar->host_port == 0) {
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ap_fprintf(f, "port * ");
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly }
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder else {
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder ap_fprintf(f, "port %u ", ic->sar->host_port);
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder }
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ap_fprintf(f, "server %s (%s:%u)\n",
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ic->server->server_hostname, ic->server->defn_name,
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly ic->server->defn_line_number);
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder }
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder }
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder}
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder
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{
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder server_addr_rec *sar;
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly int has_default_vhost_addr;
57221209d11b05aa0373cc3892d5df89ba96ebf9Christian Maeder server_rec *s;
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder int i;
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder ipaddr_chain **iphash_table_tail[IPHASH_TABLE_SIZE];
57221209d11b05aa0373cc3892d5df89ba96ebf9Christian Maeder
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder /* terminate the name_vhost list */
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly *name_vhost_list_tail = NULL;
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder /* Main host first */
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly s = main_s;
57221209d11b05aa0373cc3892d5df89ba96ebf9Christian Maeder
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder if (!s->server_hostname) {
648fe1220044aac847acbdfbc4155af5556063ebChristian Maeder s->server_hostname = ap_get_local_host(p);
57221209d11b05aa0373cc3892d5df89ba96ebf9Christian Maeder }
bcd914850de931848b86d7728192a149f9c0108bChristian Maeder
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly /* initialize the tails */
33bdce26495121cdbce30331ef90a1969126a840Liam O'Reilly for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
9aeda2b3ae8ce0b018955521e4ca835a8ba8a27bLiam O'Reilly iphash_table_tail[i] = &iphash_table[i];
eb48217dfa67ddb87b8fbd846de293d0636bd578Christian Maeder }
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly
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.
05cc55892e6c93bdd7b9c3f100ab1bb65fe6a21eLiam O'Reilly */
for (sar = name_vhost_list; sar; sar = sar->next) {
unsigned bucket = hash_inaddr(sar->host_addr.s_addr);
ipaddr_chain *new = new_ipaddr_chain(p, NULL, sar);
*iphash_table_tail[bucket] = new;
iphash_table_tail[bucket] = &new->next;
/* Notice that what we've done is insert an ipaddr_chain with
* both server and names NULL. Remember that.
*/
}
/* The next things to go into the hash ap_table_t are the virtual hosts
* themselves. They're listed off of main_s->next in the reverse
* order they occured in the config file, so we insert them at
* the iphash_table_tail but don't advance the tail.
*/
for (s = main_s->next; s; s = s->next) {
has_default_vhost_addr = 0;
for (sar = s->addrs; sar; sar = sar->next) {
ipaddr_chain *ic;
if (sar->host_addr.s_addr == DEFAULT_VHOST_ADDR
|| sar->host_addr.s_addr == INADDR_ANY) {
/* add it to default bucket for each appropriate sar
* since we need to do a port test
*/
ipaddr_chain *other;
other = find_default_server(sar->host_port);
if (other && other->sar->host_port != 0) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, main_s,
"_default_ VirtualHost overlap on port %u,"
" the first has precedence", sar->host_port);
}
has_default_vhost_addr = 1;
ic = new_ipaddr_chain(p, s, sar);
ic->next = default_list;
default_list = ic;
}
else {
/* see if it matches something we've already got */
ic = find_ipaddr(&sar->host_addr, sar->host_port);
/* the first time we encounter a NameVirtualHost address
* ic->server will be NULL, on subsequent encounters
* ic->names will be non-NULL.
*/
if (ic && (ic->names || ic->server == NULL)) {
name_chain *nc = new_name_chain(p, s, sar);
nc->next = ic->names;
ic->names = nc;
ic->server = s;
if (sar->host_port != ic->sar->host_port) {
/* one of the two is a * port, the other isn't */
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, main_s,
"VirtualHost %s:%u -- mixing * "
"ports and non-* ports with "
"a NameVirtualHost address is not supported,"
" proceeding with undefined results",
sar->virthost, sar->host_port);
}
}
else if (ic) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, main_s,
"VirtualHost %s:%u overlaps with "
"VirtualHost %s:%u, the first has precedence, "
"perhaps you need a NameVirtualHost directive",
sar->virthost, sar->host_port,
ic->sar->virthost, ic->sar->host_port);
ic->sar = sar;
ic->server = s;
}
else {
unsigned bucket = hash_inaddr(sar->host_addr.s_addr);
ic = new_ipaddr_chain(p, s, sar);
ic->next = *iphash_table_tail[bucket];
*iphash_table_tail[bucket] = ic;
}
}
}
/* Ok now we want to set up a server_hostname if the user was
* silly enough to forget one.
* XXX: This is silly we should just crash and burn.
*/
if (!s->server_hostname) {
if (has_default_vhost_addr) {
s->server_hostname = main_s->server_hostname;
}
else if (!s->addrs) {
/* what else can we do? at this point this vhost has
no configured name, probably because they used
DNS in the VirtualHost statement. It's disabled
anyhow by the host matching code. -djg */
s->server_hostname =
ap_pstrdup(p, "bogus_host_without_forward_dns");
}
else {
struct hostent *h;
if ((h = gethostbyaddr((char *) &(s->addrs->host_addr),
sizeof(struct in_addr), AF_INET))) {
s->server_hostname = ap_pstrdup(p, (char *) h->h_name);
}
else {
/* again, what can we do? They didn't specify a
ServerName, and their DNS isn't working. -djg */
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, main_s,
"Failed to resolve server name "
"for %s (check DNS) -- or specify an explicit "
"ServerName",
inet_ntoa(s->addrs->host_addr));
s->server_hostname =
ap_pstrdup(p, "bogus_host_without_reverse_dns");
}
}
}
}
/* now go through and delete any NameVirtualHosts that didn't have any
* hosts associated with them. Lamers.
*/
for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
ipaddr_chain **pic = &iphash_table[i];
while (*pic) {
ipaddr_chain *ic = *pic;
if (ic->server == NULL) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, main_s,
"NameVirtualHost %s:%u has no VirtualHosts",
ic->sar->virthost, ic->sar->host_port);
*pic = ic->next;
}
else if (ic->names == NULL) {
/* if server != NULL and names == NULL then we're done
* looking at NameVirtualHosts
*/
break;
}
else {
pic = &ic->next;
}
}
}
#ifdef IPHASH_STATISTICS
dump_iphash_statistics(main_s);
#endif
if (getenv("DUMP_VHOSTS")) {
ap_file_t *thefile = NULL;
ap_open_stderr(&thefile, p);
dump_vhost_config(thefile);
}
}
/*****************************************************************************
* run-time vhost matching functions
*/
/* Lowercase and remove any trailing dot and/or :port from the hostname,
* and check that it is sane.
*/
static void fix_hostname(request_rec *r)
{
char *host = ap_palloc(r->pool, strlen(r->hostname) + 1);
const char *src;
char *dst;
/* check and copy the host part */
src = r->hostname;
dst = host;
while (*src) {
if (!isalnum(*src) && *src != '.' && *src != '-') {
if (*src == ':')
break;
else
goto bad;
} else {
*dst++ = *src++;
}
}
/* check the port part */
if (*src++ == ':') {
while (*src) {
if (!isdigit(*src++)) {
goto bad;
}
}
}
/* strip trailing gubbins */
if (dst > host && dst[-1] == '.') {
dst[-1] = '\0';
} else {
dst[0] = '\0';
}
r->hostname = host;
return;
bad:
r->status = HTTP_BAD_REQUEST;
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
"Client sent malformed Host header");
return;
}
/* return 1 if host matches ServerName or ServerAliases */
static int matches_aliases(server_rec *s, const char *host)
{
int i;
ap_array_header_t *names;
/* match ServerName */
if (!strcasecmp(host, s->server_hostname)) {
return 1;
}
/* search all the aliases from ServerAlias directive */
names = s->names;
if (names) {
char **name = (char **) names->elts;
for (i = 0; i < names->nelts; ++i) {
if(!name[i]) continue;
if (!strcasecmp(host, name[i]))
return 1;
}
}
names = s->wild_names;
if (names) {
char **name = (char **) names->elts;
for (i = 0; i < names->nelts; ++i) {
if(!name[i]) continue;
if (!ap_strcasecmp_match(host, name[i]))
return 1;
}
}
return 0;
}
/* Suppose a request came in on the same socket as this r, and included
* a header "Host: host:port", would it map to r->server? It's more
* than just that though. When we do the normal matches for each request
* we don't even bother considering Host: etc on non-namevirtualhosts,
* we just call it a match. But here we require the host:port to match
* the ServerName and/or ServerAliases.
*/
API_EXPORT(int) ap_matches_request_vhost(request_rec *r, const char *host,
unsigned port)
{
server_rec *s;
server_addr_rec *sar;
s = r->server;
/* search all the <VirtualHost> values */
/* XXX: If this is a NameVirtualHost then we may not be doing the Right Thing
* consider:
*
* NameVirtualHost 10.1.1.1
* <VirtualHost 10.1.1.1>
* ServerName v1
* </VirtualHost>
* <VirtualHost 10.1.1.1>
* ServerName v2
* </VirtualHost>
*
* Suppose r->server is v2, and we're asked to match "10.1.1.1". We'll say
* "yup it's v2", when really it isn't... if a request came in for 10.1.1.1
* it would really go to v1.
*/
for (sar = s->addrs; sar; sar = sar->next) {
if ((sar->host_port == 0 || port == sar->host_port)
&& !strcasecmp(host, sar->virthost)) {
return 1;
}
}
/* the Port has to match now, because the rest don't have ports associated
* with them. */
if (port != s->port) {
return 0;
}
return matches_aliases(s, host);
}
static void check_hostalias(request_rec *r)
{
/*
* Even if the request has a Host: header containing a port we ignore
* that port. We always use the physical port of the socket. There
* are a few reasons for this:
*
* - the default of 80 or 443 for SSL is easier to handle this way
* - there is less of a possibility of a security problem
* - it simplifies the data structure
* - the client may have no idea that a proxy somewhere along the way
* translated the request to another ip:port
* - except for the addresses from the VirtualHost line, none of the other
* names we'll match have ports associated with them
*/
const char *host = r->hostname;
unsigned port = ntohs(r->connection->local_addr.sin_port);
server_rec *s;
server_rec *last_s;
name_chain *src;
last_s = NULL;
/* Recall that the name_chain is a list of server_addr_recs, some of
* whose ports may not match. Also each server may appear more than
* once in the chain -- specifically, it will appear once for each
* address from its VirtualHost line which matched. We only want to
* do the full ServerName/ServerAlias comparisons once for each
* server, fortunately we know that all the VirtualHost addresses for
* a single server are adjacent to each other.
*/
for (src = r->connection->vhost_lookup_data; src; src = src->next) {
server_addr_rec *sar;
/* We only consider addresses on the name_chain which have a matching
* port
*/
sar = src->sar;
if (sar->host_port != 0 && port != sar->host_port) {
continue;
}
s = src->server;
/* does it match the virthost from the sar? */
if (!strcasecmp(host, sar->virthost)) {
goto found;
}
if (s == last_s) {
/* we've already done ServerName and ServerAlias checks for this
* vhost
*/
continue;
}
last_s = s;
if (matches_aliases(s, host)) {
goto found;
}
}
return;
found:
/* s is the first matching server, we're done */
r->server = s;
}
static void check_serverpath(request_rec *r)
{
server_rec *s;
server_rec *last_s;
name_chain *src;
/* use AP func here. */
unsigned port = ntohs(r->connection->local_addr.sin_port);
/*
* This is in conjunction with the ServerPath code in http_core, so we
* get the right host attached to a non- Host-sending request.
*
* See the comment in check_hostalias about how each vhost can be
* listed multiple times.
*/
last_s = NULL;
for (src = r->connection->vhost_lookup_data; src; src = src->next) {
/* We only consider addresses on the name_chain which have a matching
* port
*/
if (src->sar->host_port != 0 && port != src->sar->host_port) {
continue;
}
s = src->server;
if (s == last_s) {
continue;
}
last_s = s;
if (s->path && !strncmp(r->uri, s->path, s->pathlen) &&
(s->path[s->pathlen - 1] == '/' ||
r->uri[s->pathlen] == '/' ||
r->uri[s->pathlen] == '\0')) {
r->server = s;
return;
}
}
}
void ap_update_vhost_from_headers(request_rec *r)
{
/* must set this for HTTP/1.1 support */
if (r->hostname || (r->hostname = ap_table_get(r->headers_in, "Host"))) {
fix_hostname(r);
if (r->status != HTTP_OK)
return;
}
/* check if we tucked away a name_chain */
if (r->connection->vhost_lookup_data) {
if (r->hostname)
check_hostalias(r);
else
check_serverpath(r);
}
}
/* Called for a new connection which has a known local_addr. Note that the
* new connection is assumed to have conn->server == main server.
*/
void ap_update_vhost_given_ip(conn_rec *conn)
{
ipaddr_chain *trav;
unsigned port = ntohs(conn->local_addr.sin_port);
/* scan the hash ap_table_t for an exact match first */
trav = find_ipaddr(&conn->local_addr.sin_addr, port);
if (trav) {
/* save the name_chain for later in case this is a name-vhost */
conn->vhost_lookup_data = trav->names;
conn->base_server = trav->server;
return;
}
/* There's certainly no name-vhosts with this address, they would have
* been matched above.
*/
conn->vhost_lookup_data = NULL;
/* maybe there's a default server matching this port */
trav = find_default_server(port);
if (trav) {
conn->base_server = trav->server;
}
/* otherwise we're stuck with just the main server */
}