vhost.c revision ebc18d48bea83ee5ed7a1b4e30007e5192539829
af84459fbf938e508fd10b01cb8d699c79083813takashi/* ====================================================================
af84459fbf938e508fd10b01cb8d699c79083813takashi * The Apache Software License, Version 1.1
af84459fbf938e508fd10b01cb8d699c79083813takashi *
af84459fbf938e508fd10b01cb8d699c79083813takashi * Copyright (c) 2000 The Apache Software Foundation. All rights
af84459fbf938e508fd10b01cb8d699c79083813takashi * reserved.
af84459fbf938e508fd10b01cb8d699c79083813takashi *
af84459fbf938e508fd10b01cb8d699c79083813takashi * Redistribution and use in source and binary forms, with or without
96ad5d81ee4a2cc66a4ae19893efc8aa6d06fae7jailletc * modification, are permitted provided that the following conditions
af84459fbf938e508fd10b01cb8d699c79083813takashi * are met:
af84459fbf938e508fd10b01cb8d699c79083813takashi *
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * 1. Redistributions of source code must retain the above copyright
2e545ce2450a9953665f701bb05350f0d3f26275nd * notice, this list of conditions and the following disclaimer.
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen *
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * 2. Redistributions in binary form must reproduce the above copyright
af84459fbf938e508fd10b01cb8d699c79083813takashi * notice, this list of conditions and the following disclaimer in
af84459fbf938e508fd10b01cb8d699c79083813takashi * the documentation and/or other materials provided with the
af33a4994ae2ff15bc67d19ff1a7feb906745bf8rbowen * distribution.
3f08db06526d6901aa08c110b5bc7dde6bc39905nd *
af84459fbf938e508fd10b01cb8d699c79083813takashi * 3. The end-user documentation included with the redistribution,
af84459fbf938e508fd10b01cb8d699c79083813takashi * if any, must include the following acknowledgment:
af84459fbf938e508fd10b01cb8d699c79083813takashi * "This product includes software developed by the
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * Apache Software Foundation (http://www.apache.org/)."
af84459fbf938e508fd10b01cb8d699c79083813takashi * Alternately, this acknowledgment may appear in the software itself,
af84459fbf938e508fd10b01cb8d699c79083813takashi * if and wherever such third-party acknowledgments normally appear.
af84459fbf938e508fd10b01cb8d699c79083813takashi *
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung * 4. The names "Apache" and "Apache Software Foundation" must
af84459fbf938e508fd10b01cb8d699c79083813takashi * not be used to endorse or promote products derived from this
0a05fab9aadd37834734ffe106fc8ad4488fb3e3rbowen * software without prior written permission. For written
0a05fab9aadd37834734ffe106fc8ad4488fb3e3rbowen * permission, please contact apache@apache.org.
af84459fbf938e508fd10b01cb8d699c79083813takashi *
af84459fbf938e508fd10b01cb8d699c79083813takashi * 5. Products derived from this software may not be called "Apache",
78f97ce162b66a0dbfd7af4dcd9984f162569b04minfrin * nor may "Apache" appear in their name, without prior written
af84459fbf938e508fd10b01cb8d699c79083813takashi * permission of the Apache Software Foundation.
3c13a815670b54d1c17bf02954f7d2b066cde95cnd *
3c13a815670b54d1c17bf02954f7d2b066cde95cnd * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
af84459fbf938e508fd10b01cb8d699c79083813takashi * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
af84459fbf938e508fd10b01cb8d699c79083813takashi * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
af84459fbf938e508fd10b01cb8d699c79083813takashi * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
af84459fbf938e508fd10b01cb8d699c79083813takashi * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
5effc8b39fae5cd169d17f342bfc265705840014rbowen * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
5effc8b39fae5cd169d17f342bfc265705840014rbowen * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
5effc8b39fae5cd169d17f342bfc265705840014rbowen * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
5effc8b39fae5cd169d17f342bfc265705840014rbowen * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
af84459fbf938e508fd10b01cb8d699c79083813takashi * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
af84459fbf938e508fd10b01cb8d699c79083813takashi * SUCH DAMAGE.
af84459fbf938e508fd10b01cb8d699c79083813takashi * ====================================================================
af84459fbf938e508fd10b01cb8d699c79083813takashi *
af84459fbf938e508fd10b01cb8d699c79083813takashi * This software consists of voluntary contributions made by many
af84459fbf938e508fd10b01cb8d699c79083813takashi * individuals on behalf of the Apache Software Foundation. For more
5effc8b39fae5cd169d17f342bfc265705840014rbowen * information on the Apache Software Foundation, please see
5effc8b39fae5cd169d17f342bfc265705840014rbowen * <http://www.apache.org/>.
5effc8b39fae5cd169d17f342bfc265705840014rbowen *
5effc8b39fae5cd169d17f342bfc265705840014rbowen * Portions of this software are based upon public domain software
5effc8b39fae5cd169d17f342bfc265705840014rbowen * originally written at the National Center for Supercomputing Applications,
5effc8b39fae5cd169d17f342bfc265705840014rbowen * University of Illinois, Urbana-Champaign.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen/*
5effc8b39fae5cd169d17f342bfc265705840014rbowen * http_vhost.c: functions pertaining to virtual host addresses
5effc8b39fae5cd169d17f342bfc265705840014rbowen * (configuration and run-time)
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen#define CORE_PRIVATE
5effc8b39fae5cd169d17f342bfc265705840014rbowen#include "ap_config.h"
5effc8b39fae5cd169d17f342bfc265705840014rbowen#include "httpd.h"
5effc8b39fae5cd169d17f342bfc265705840014rbowen#include "http_config.h"
5effc8b39fae5cd169d17f342bfc265705840014rbowen#include "http_log.h"
5effc8b39fae5cd169d17f342bfc265705840014rbowen#include "http_vhost.h"
5effc8b39fae5cd169d17f342bfc265705840014rbowen#include "http_protocol.h"
5effc8b39fae5cd169d17f342bfc265705840014rbowen#include "http_core.h"
5effc8b39fae5cd169d17f342bfc265705840014rbowen#include "apr_strings.h"
5effc8b39fae5cd169d17f342bfc265705840014rbowen
1c26a593f62800795eddc6cbaf86090e0976e2efrbowen#ifdef HAVE_ARPA_INET_H
1c26a593f62800795eddc6cbaf86090e0976e2efrbowen#include <arpa/inet.h>
5effc8b39fae5cd169d17f342bfc265705840014rbowen#endif
5effc8b39fae5cd169d17f342bfc265705840014rbowen#ifdef HAVE_NETINET_IN_H
5effc8b39fae5cd169d17f342bfc265705840014rbowen#include <netinet/in.h>
5effc8b39fae5cd169d17f342bfc265705840014rbowen#endif
5effc8b39fae5cd169d17f342bfc265705840014rbowen#ifdef HAVE_SYS_SOCKET_H
5effc8b39fae5cd169d17f342bfc265705840014rbowen#include <sys/socket.h>
5effc8b39fae5cd169d17f342bfc265705840014rbowen#endif
5effc8b39fae5cd169d17f342bfc265705840014rbowen#ifdef HAVE_NETDB_H
5effc8b39fae5cd169d17f342bfc265705840014rbowen#include <netdb.h>
5effc8b39fae5cd169d17f342bfc265705840014rbowen#endif
5effc8b39fae5cd169d17f342bfc265705840014rbowen#ifdef HAVE_STRINGS_H
5effc8b39fae5cd169d17f342bfc265705840014rbowen#include <strings.h>
5effc8b39fae5cd169d17f342bfc265705840014rbowen#endif
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen/*
5effc8b39fae5cd169d17f342bfc265705840014rbowen * After all the definitions there's an explanation of how it's all put
5effc8b39fae5cd169d17f342bfc265705840014rbowen * together.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowen
af84459fbf938e508fd10b01cb8d699c79083813takashi/* meta-list of name-vhosts. Each server_rec can be in possibly multiple
af84459fbf938e508fd10b01cb8d699c79083813takashi * lists of name-vhosts.
af84459fbf938e508fd10b01cb8d699c79083813takashi */
af84459fbf938e508fd10b01cb8d699c79083813takashitypedef struct name_chain name_chain;
af84459fbf938e508fd10b01cb8d699c79083813takashistruct name_chain {
af84459fbf938e508fd10b01cb8d699c79083813takashi name_chain *next;
af84459fbf938e508fd10b01cb8d699c79083813takashi server_addr_rec *sar; /* the record causing it to be in
af84459fbf938e508fd10b01cb8d699c79083813takashi * this chain (needed for port comparisons) */
af84459fbf938e508fd10b01cb8d699c79083813takashi server_rec *server; /* the server to use on a match */
af84459fbf938e508fd10b01cb8d699c79083813takashi};
5effc8b39fae5cd169d17f342bfc265705840014rbowen
af84459fbf938e508fd10b01cb8d699c79083813takashi/* meta-list of ip addresses. Each server_rec can be in possibly multiple
af84459fbf938e508fd10b01cb8d699c79083813takashi * hash chains since it can have multiple ips.
af84459fbf938e508fd10b01cb8d699c79083813takashi */
5effc8b39fae5cd169d17f342bfc265705840014rbowentypedef struct ipaddr_chain ipaddr_chain;
5effc8b39fae5cd169d17f342bfc265705840014rbowenstruct ipaddr_chain {
5effc8b39fae5cd169d17f342bfc265705840014rbowen ipaddr_chain *next;
5effc8b39fae5cd169d17f342bfc265705840014rbowen server_addr_rec *sar; /* the record causing it to be in
5effc8b39fae5cd169d17f342bfc265705840014rbowen * this chain (need for both ip addr and port
5effc8b39fae5cd169d17f342bfc265705840014rbowen * comparisons) */
5effc8b39fae5cd169d17f342bfc265705840014rbowen server_rec *server; /* the server to use if this matches */
5effc8b39fae5cd169d17f342bfc265705840014rbowen name_chain *names; /* if non-NULL then a list of name-vhosts
5effc8b39fae5cd169d17f342bfc265705840014rbowen * sharing this address */
5effc8b39fae5cd169d17f342bfc265705840014rbowen};
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen/* This defines the size of the hash apr_table_t used for hashing ip addresses
5effc8b39fae5cd169d17f342bfc265705840014rbowen * of virtual hosts. It must be a power of two.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowen#ifndef IPHASH_TABLE_SIZE
5effc8b39fae5cd169d17f342bfc265705840014rbowen#define IPHASH_TABLE_SIZE 256
5effc8b39fae5cd169d17f342bfc265705840014rbowen#endif
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen/* A (n) bucket hash table, each entry has a pointer to a server rec and
5effc8b39fae5cd169d17f342bfc265705840014rbowen * a pointer to the other entries in that bucket. Each individual address,
5effc8b39fae5cd169d17f342bfc265705840014rbowen * even for virtualhosts with multiple addresses, has an entry in this hash
5effc8b39fae5cd169d17f342bfc265705840014rbowen * table. There are extra buckets for _default_, and name-vhost entries.
5effc8b39fae5cd169d17f342bfc265705840014rbowen *
5effc8b39fae5cd169d17f342bfc265705840014rbowen * Note that after config time this is constant, so it is thread-safe.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowenstatic ipaddr_chain *iphash_table[IPHASH_TABLE_SIZE];
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen/* dump out statistics about the hash function */
5effc8b39fae5cd169d17f342bfc265705840014rbowen/* #define IPHASH_STATISTICS */
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen/* list of the _default_ servers */
5effc8b39fae5cd169d17f342bfc265705840014rbowenstatic ipaddr_chain *default_list;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen/* list of the NameVirtualHost addresses */
5effc8b39fae5cd169d17f342bfc265705840014rbowenstatic server_addr_rec *name_vhost_list;
5effc8b39fae5cd169d17f342bfc265705840014rbowenstatic server_addr_rec **name_vhost_list_tail;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen/*
5effc8b39fae5cd169d17f342bfc265705840014rbowen * How it's used:
5effc8b39fae5cd169d17f342bfc265705840014rbowen *
5effc8b39fae5cd169d17f342bfc265705840014rbowen * The ip address determines which chain in iphash_table is interesting, then
5effc8b39fae5cd169d17f342bfc265705840014rbowen * a comparison is done down that chain to find the first ipaddr_chain whose
5effc8b39fae5cd169d17f342bfc265705840014rbowen * sar matches the address:port pair.
5effc8b39fae5cd169d17f342bfc265705840014rbowen *
5effc8b39fae5cd169d17f342bfc265705840014rbowen * If that ipaddr_chain has names == NULL then you're done, it's an ip-vhost.
5effc8b39fae5cd169d17f342bfc265705840014rbowen *
5effc8b39fae5cd169d17f342bfc265705840014rbowen * Otherwise it's a name-vhost list, and the default is the server in the
5effc8b39fae5cd169d17f342bfc265705840014rbowen * ipaddr_chain record. We tuck away the ipaddr_chain record in the
5effc8b39fae5cd169d17f342bfc265705840014rbowen * conn_rec field vhost_lookup_data. Later on after the headers we get a
5effc8b39fae5cd169d17f342bfc265705840014rbowen * second chance, and we use the name_chain to figure out what name-vhost
5effc8b39fae5cd169d17f342bfc265705840014rbowen * matches the headers.
5effc8b39fae5cd169d17f342bfc265705840014rbowen *
5effc8b39fae5cd169d17f342bfc265705840014rbowen * If there was no ip address match in the iphash_table then do a lookup
5effc8b39fae5cd169d17f342bfc265705840014rbowen * in the default_list.
5effc8b39fae5cd169d17f342bfc265705840014rbowen *
5effc8b39fae5cd169d17f342bfc265705840014rbowen * How it's put together ... well you should be able to figure that out
5effc8b39fae5cd169d17f342bfc265705840014rbowen * from how it's used. Or something like that.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen/* called at the beginning of the config */
5effc8b39fae5cd169d17f342bfc265705840014rbowenvoid ap_init_vhost_config(apr_pool_t *p)
5effc8b39fae5cd169d17f342bfc265705840014rbowen{
5effc8b39fae5cd169d17f342bfc265705840014rbowen memset(iphash_table, 0, sizeof(iphash_table));
5effc8b39fae5cd169d17f342bfc265705840014rbowen default_list = NULL;
5effc8b39fae5cd169d17f342bfc265705840014rbowen name_vhost_list = NULL;
5effc8b39fae5cd169d17f342bfc265705840014rbowen name_vhost_list_tail = &name_vhost_list;
5effc8b39fae5cd169d17f342bfc265705840014rbowen}
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen/*
5effc8b39fae5cd169d17f342bfc265705840014rbowen * Parses a host of the form <address>[:port]
5effc8b39fae5cd169d17f342bfc265705840014rbowen * paddr is used to create a list in the order of input
5effc8b39fae5cd169d17f342bfc265705840014rbowen * **paddr is the ->next pointer of the last entry (or s->addrs)
5effc8b39fae5cd169d17f342bfc265705840014rbowen * *paddr is the variable used to keep track of **paddr between calls
5effc8b39fae5cd169d17f342bfc265705840014rbowen * port is the default port to assume
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowenstatic const char *get_addresses(apr_pool_t *p, const char *w_,
5effc8b39fae5cd169d17f342bfc265705840014rbowen server_addr_rec ***paddr,
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_port_t default_port)
5effc8b39fae5cd169d17f342bfc265705840014rbowen{
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_sockaddr_t *my_addr;
5effc8b39fae5cd169d17f342bfc265705840014rbowen server_addr_rec *sar;
5effc8b39fae5cd169d17f342bfc265705840014rbowen char *w, *host, *scope_id;
5effc8b39fae5cd169d17f342bfc265705840014rbowen int wild_port;
5effc8b39fae5cd169d17f342bfc265705840014rbowen size_t wlen;
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_port_t port;
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_status_t rv;
63befe0983261d711e62457b380e24ecc3b7b79etrawick
63befe0983261d711e62457b380e24ecc3b7b79etrawick if (*w_ == '\0')
63befe0983261d711e62457b380e24ecc3b7b79etrawick return NULL;
63befe0983261d711e62457b380e24ecc3b7b79etrawick
63befe0983261d711e62457b380e24ecc3b7b79etrawick w = apr_pstrdup(p, w_);
63befe0983261d711e62457b380e24ecc3b7b79etrawick /* apr_parse_addr_port() doesn't understand ":*" so handle that first. */
5effc8b39fae5cd169d17f342bfc265705840014rbowen wlen = strlen(w);
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (wlen > 2 && w[wlen - 1] == '*' && w[wlen - 2] == ':') {
5effc8b39fae5cd169d17f342bfc265705840014rbowen w[wlen - 2] = '\0';
5effc8b39fae5cd169d17f342bfc265705840014rbowen wild_port = 1;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen else {
5effc8b39fae5cd169d17f342bfc265705840014rbowen wild_port = 0;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen rv = apr_parse_addr_port(&host, &scope_id, &port, w, p);
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (rv != APR_SUCCESS) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen return "The address or port is invalid";
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (scope_id) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen return "Scope ids are not supported";
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (!port && !wild_port) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen port = default_port;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (strcmp(host, "*") == 0) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen rv = apr_getaddrinfo(&my_addr, NULL, APR_INET, port, 0, p);
5effc8b39fae5cd169d17f342bfc265705840014rbowen my_addr->sa.sin.sin_addr.s_addr = htonl(INADDR_ANY);
5effc8b39fae5cd169d17f342bfc265705840014rbowen } else if (strcasecmp(host, "_default_") == 0
5effc8b39fae5cd169d17f342bfc265705840014rbowen || strcmp(host, "255.255.255.255") == 0) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen rv = apr_getaddrinfo(&my_addr, NULL, APR_INET, port, 0, p);
5effc8b39fae5cd169d17f342bfc265705840014rbowen ap_assert(rv == APR_SUCCESS); /* must be bug or out of storage */
5effc8b39fae5cd169d17f342bfc265705840014rbowen my_addr->sa.sin.sin_addr.s_addr = DEFAULT_VHOST_ADDR;
5effc8b39fae5cd169d17f342bfc265705840014rbowen } else {
5effc8b39fae5cd169d17f342bfc265705840014rbowen rv = apr_getaddrinfo(&my_addr, host, APR_UNSPEC, port, 0, p);
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (rv != APR_SUCCESS) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
5effc8b39fae5cd169d17f342bfc265705840014rbowen "Cannot resolve host name %s --- ignoring!", host);
5effc8b39fae5cd169d17f342bfc265705840014rbowen return NULL;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi /* XXX Gotta go through *all* addresses for the host name!
af84459fbf938e508fd10b01cb8d699c79083813takashi * Fix apr_getaddrinfo() to save them! */
af84459fbf938e508fd10b01cb8d699c79083813takashi
5effc8b39fae5cd169d17f342bfc265705840014rbowen sar = apr_pcalloc(p, sizeof(server_addr_rec));
5effc8b39fae5cd169d17f342bfc265705840014rbowen **paddr = sar;
af84459fbf938e508fd10b01cb8d699c79083813takashi *paddr = &sar->next;
5effc8b39fae5cd169d17f342bfc265705840014rbowen sar->host_addr = my_addr;
5effc8b39fae5cd169d17f342bfc265705840014rbowen sar->host_port = port;
5effc8b39fae5cd169d17f342bfc265705840014rbowen sar->virthost = host;
af84459fbf938e508fd10b01cb8d699c79083813takashi return NULL;
af84459fbf938e508fd10b01cb8d699c79083813takashi}
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi/* parse the <VirtualHost> addresses */
af84459fbf938e508fd10b01cb8d699c79083813takashiconst char *ap_parse_vhost_addrs(apr_pool_t *p, const char *hostname, server_rec *s)
af84459fbf938e508fd10b01cb8d699c79083813takashi{
af84459fbf938e508fd10b01cb8d699c79083813takashi server_addr_rec **addrs;
5effc8b39fae5cd169d17f342bfc265705840014rbowen const char *err;
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi /* start the list of addreses */
5effc8b39fae5cd169d17f342bfc265705840014rbowen addrs = &s->addrs;
5effc8b39fae5cd169d17f342bfc265705840014rbowen while (hostname[0]) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port);
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (err) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen *addrs = NULL;
5effc8b39fae5cd169d17f342bfc265705840014rbowen return err;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* terminate the list */
5effc8b39fae5cd169d17f342bfc265705840014rbowen *addrs = NULL;
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (s->addrs) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (s->addrs->host_port) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* override the default port which is inherited from main_server */
5effc8b39fae5cd169d17f342bfc265705840014rbowen s->port = s->addrs->host_port;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen return NULL;
af84459fbf938e508fd10b01cb8d699c79083813takashi}
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi
5effc8b39fae5cd169d17f342bfc265705840014rbowenconst char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy,
5effc8b39fae5cd169d17f342bfc265705840014rbowen const char *arg)
af84459fbf938e508fd10b01cb8d699c79083813takashi{
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* use whatever port the main server has at this point */
5effc8b39fae5cd169d17f342bfc265705840014rbowen return get_addresses(cmd->pool, arg, &name_vhost_list_tail,
5effc8b39fae5cd169d17f342bfc265705840014rbowen cmd->server->port);
5effc8b39fae5cd169d17f342bfc265705840014rbowen}
5effc8b39fae5cd169d17f342bfc265705840014rbowen
af84459fbf938e508fd10b01cb8d699c79083813takashi
5effc8b39fae5cd169d17f342bfc265705840014rbowen/* hash apr_table_t statistics, keep this in here for the beta period so
af84459fbf938e508fd10b01cb8d699c79083813takashi * we can find out if the hash function is ok
af84459fbf938e508fd10b01cb8d699c79083813takashi */
af84459fbf938e508fd10b01cb8d699c79083813takashi#ifdef IPHASH_STATISTICS
af84459fbf938e508fd10b01cb8d699c79083813takashistatic int iphash_compare(const void *a, const void *b)
af84459fbf938e508fd10b01cb8d699c79083813takashi{
af84459fbf938e508fd10b01cb8d699c79083813takashi return (*(const int *) b - *(const int *) a);
af84459fbf938e508fd10b01cb8d699c79083813takashi}
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowenstatic void dump_iphash_statistics(server_rec *main_s)
5effc8b39fae5cd169d17f342bfc265705840014rbowen{
5effc8b39fae5cd169d17f342bfc265705840014rbowen unsigned count[IPHASH_TABLE_SIZE];
5effc8b39fae5cd169d17f342bfc265705840014rbowen int i;
5effc8b39fae5cd169d17f342bfc265705840014rbowen ipaddr_chain *src;
5effc8b39fae5cd169d17f342bfc265705840014rbowen unsigned total;
5effc8b39fae5cd169d17f342bfc265705840014rbowen char buf[HUGE_STRING_LEN];
5effc8b39fae5cd169d17f342bfc265705840014rbowen char *p;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen total = 0;
5effc8b39fae5cd169d17f342bfc265705840014rbowen for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen count[i] = 0;
5effc8b39fae5cd169d17f342bfc265705840014rbowen for (src = iphash_table[i]; src; src = src->next) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen ++count[i];
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (i < IPHASH_TABLE_SIZE) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* don't count the slop buckets in the total */
5effc8b39fae5cd169d17f342bfc265705840014rbowen ++total;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen qsort(count, IPHASH_TABLE_SIZE, sizeof(count[0]), iphash_compare);
5effc8b39fae5cd169d17f342bfc265705840014rbowen p = buf + apr_snprintf(buf, sizeof(buf),
5effc8b39fae5cd169d17f342bfc265705840014rbowen "iphash: total hashed = %u, avg chain = %u, "
5effc8b39fae5cd169d17f342bfc265705840014rbowen "chain lengths (count x len):",
5effc8b39fae5cd169d17f342bfc265705840014rbowen total, total / IPHASH_TABLE_SIZE);
5effc8b39fae5cd169d17f342bfc265705840014rbowen total = 1;
5effc8b39fae5cd169d17f342bfc265705840014rbowen for (i = 1; i < IPHASH_TABLE_SIZE; ++i) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (count[i - 1] != count[i]) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen p += apr_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
5effc8b39fae5cd169d17f342bfc265705840014rbowen total, count[i - 1]);
5effc8b39fae5cd169d17f342bfc265705840014rbowen total = 1;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen else {
5effc8b39fae5cd169d17f342bfc265705840014rbowen ++total;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen p += apr_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
5effc8b39fae5cd169d17f342bfc265705840014rbowen total, count[IPHASH_TABLE_SIZE - 1]);
5effc8b39fae5cd169d17f342bfc265705840014rbowen ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, main_s, buf);
5effc8b39fae5cd169d17f342bfc265705840014rbowen}
5effc8b39fae5cd169d17f342bfc265705840014rbowen#endif
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen
af84459fbf938e508fd10b01cb8d699c79083813takashi/* This hashing function is designed to get good distribution in the cases
af84459fbf938e508fd10b01cb8d699c79083813takashi * where the server is handling entire "networks" of servers. i.e. a
af84459fbf938e508fd10b01cb8d699c79083813takashi * whack of /24s. This is probably the most common configuration for
af84459fbf938e508fd10b01cb8d699c79083813takashi * ISPs with large virtual servers.
af84459fbf938e508fd10b01cb8d699c79083813takashi *
5effc8b39fae5cd169d17f342bfc265705840014rbowen * NOTE: This function is symmetric (i.e. collapses all 4 octets
5effc8b39fae5cd169d17f342bfc265705840014rbowen * into one), so machine byte order (big/little endianness) does not matter.
5effc8b39fae5cd169d17f342bfc265705840014rbowen *
5effc8b39fae5cd169d17f342bfc265705840014rbowen * Hash function provided by David Hankins.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
af84459fbf938e508fd10b01cb8d699c79083813takashistatic apr_inline unsigned hash_inaddr(unsigned key)
af84459fbf938e508fd10b01cb8d699c79083813takashi{
af84459fbf938e508fd10b01cb8d699c79083813takashi key ^= (key >> 16);
af84459fbf938e508fd10b01cb8d699c79083813takashi return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE;
af84459fbf938e508fd10b01cb8d699c79083813takashi}
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashistatic apr_inline unsigned hash_addr(struct apr_sockaddr_t *sa)
af84459fbf938e508fd10b01cb8d699c79083813takashi{
af84459fbf938e508fd10b01cb8d699c79083813takashi unsigned key;
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi /* The key is the last four bytes of the IP address.
af84459fbf938e508fd10b01cb8d699c79083813takashi * For IPv4, this is the entire address, as always.
af84459fbf938e508fd10b01cb8d699c79083813takashi * For IPv6, this is usually part of the MAC address.
af84459fbf938e508fd10b01cb8d699c79083813takashi */
11495c9f0bd33e51a25b4d532beadfbcf9b944a3nilgun key = *(unsigned *)((char *)sa->ipaddr_ptr + sa->ipaddr_len - 4);
af84459fbf938e508fd10b01cb8d699c79083813takashi return hash_inaddr(key);
11495c9f0bd33e51a25b4d532beadfbcf9b944a3nilgun}
11495c9f0bd33e51a25b4d532beadfbcf9b944a3nilgun
11495c9f0bd33e51a25b4d532beadfbcf9b944a3nilgunstatic ipaddr_chain *new_ipaddr_chain(apr_pool_t *p,
11495c9f0bd33e51a25b4d532beadfbcf9b944a3nilgun server_rec *s, server_addr_rec *sar)
11495c9f0bd33e51a25b4d532beadfbcf9b944a3nilgun{
af84459fbf938e508fd10b01cb8d699c79083813takashi ipaddr_chain *new;
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi new = apr_palloc(p, sizeof(*new));
11495c9f0bd33e51a25b4d532beadfbcf9b944a3nilgun new->names = NULL;
11495c9f0bd33e51a25b4d532beadfbcf9b944a3nilgun new->server = s;
af84459fbf938e508fd10b01cb8d699c79083813takashi new->sar = sar;
af84459fbf938e508fd10b01cb8d699c79083813takashi new->next = NULL;
af84459fbf938e508fd10b01cb8d699c79083813takashi return new;
af84459fbf938e508fd10b01cb8d699c79083813takashi}
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashistatic name_chain *new_name_chain(apr_pool_t *p, server_rec *s, server_addr_rec *sar)
af84459fbf938e508fd10b01cb8d699c79083813takashi{
af84459fbf938e508fd10b01cb8d699c79083813takashi name_chain *new;
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi new = apr_palloc(p, sizeof(*new));
af84459fbf938e508fd10b01cb8d699c79083813takashi new->server = s;
af84459fbf938e508fd10b01cb8d699c79083813takashi new->sar = sar;
af84459fbf938e508fd10b01cb8d699c79083813takashi new->next = NULL;
af84459fbf938e508fd10b01cb8d699c79083813takashi return new;
af84459fbf938e508fd10b01cb8d699c79083813takashi}
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashistatic apr_inline ipaddr_chain *find_ipaddr(apr_sockaddr_t *sa)
af84459fbf938e508fd10b01cb8d699c79083813takashi{
af84459fbf938e508fd10b01cb8d699c79083813takashi unsigned bucket;
af84459fbf938e508fd10b01cb8d699c79083813takashi ipaddr_chain *trav;
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi /* scan the hash apr_table_t for an exact match first */
5effc8b39fae5cd169d17f342bfc265705840014rbowen bucket = hash_addr(sa);
5effc8b39fae5cd169d17f342bfc265705840014rbowen for (trav = iphash_table[bucket]; trav; trav = trav->next) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen server_addr_rec *sar = trav->sar;
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_sockaddr_t *cur = sar->host_addr;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (cur->sa.sin.sin_port == 0 ||
5effc8b39fae5cd169d17f342bfc265705840014rbowen sa->sa.sin.sin_port == 0 ||
af84459fbf938e508fd10b01cb8d699c79083813takashi cur->sa.sin.sin_port == sa->sa.sin.sin_port) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (cur->ipaddr_len == sa->ipaddr_len &&
5effc8b39fae5cd169d17f342bfc265705840014rbowen !memcmp(cur->ipaddr_ptr,
5effc8b39fae5cd169d17f342bfc265705840014rbowen sa->ipaddr_ptr,
5effc8b39fae5cd169d17f342bfc265705840014rbowen sa->ipaddr_len)) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen return trav;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen return NULL;
5effc8b39fae5cd169d17f342bfc265705840014rbowen}
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowenstatic ipaddr_chain *find_default_server(apr_port_t port)
5effc8b39fae5cd169d17f342bfc265705840014rbowen{
5effc8b39fae5cd169d17f342bfc265705840014rbowen server_addr_rec *sar;
5effc8b39fae5cd169d17f342bfc265705840014rbowen ipaddr_chain *trav;
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi for (trav = default_list; trav; trav = trav->next) {
af84459fbf938e508fd10b01cb8d699c79083813takashi sar = trav->sar;
af84459fbf938e508fd10b01cb8d699c79083813takashi if (sar->host_port == 0 || sar->host_port == port) {
af84459fbf938e508fd10b01cb8d699c79083813takashi /* match! */
5effc8b39fae5cd169d17f342bfc265705840014rbowen return trav;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen return NULL;
5effc8b39fae5cd169d17f342bfc265705840014rbowen}
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowenstatic void dump_a_vhost(apr_file_t *f, ipaddr_chain *ic)
5effc8b39fae5cd169d17f342bfc265705840014rbowen{
5effc8b39fae5cd169d17f342bfc265705840014rbowen name_chain *nc;
5effc8b39fae5cd169d17f342bfc265705840014rbowen int len;
5effc8b39fae5cd169d17f342bfc265705840014rbowen char buf[MAX_STRING_LEN];
af84459fbf938e508fd10b01cb8d699c79083813takashi apr_sockaddr_t *ha = ic->sar->host_addr;
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi if (ha->sa.sin.sin_family == APR_INET &&
af84459fbf938e508fd10b01cb8d699c79083813takashi ha->sa.sin.sin_addr.s_addr == DEFAULT_VHOST_ADDR) {
af84459fbf938e508fd10b01cb8d699c79083813takashi len = apr_snprintf(buf, sizeof(buf), "_default_:%u",
af84459fbf938e508fd10b01cb8d699c79083813takashi ic->sar->host_port);
af84459fbf938e508fd10b01cb8d699c79083813takashi }
af84459fbf938e508fd10b01cb8d699c79083813takashi else if (ha->sa.sin.sin_family == APR_INET &&
af84459fbf938e508fd10b01cb8d699c79083813takashi ha->sa.sin.sin_addr.s_addr == INADDR_ANY) {
af84459fbf938e508fd10b01cb8d699c79083813takashi len = apr_snprintf(buf, sizeof(buf), "*:%u",
af84459fbf938e508fd10b01cb8d699c79083813takashi ic->sar->host_port);
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen else {
5effc8b39fae5cd169d17f342bfc265705840014rbowen len = apr_snprintf(buf, sizeof(buf), "%pI", ha);
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (ic->sar->host_port == 0) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen buf[len-1] = '*';
af84459fbf938e508fd10b01cb8d699c79083813takashi }
af84459fbf938e508fd10b01cb8d699c79083813takashi if (ic->names == NULL) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_fprintf(f, "%-22s %s (%s:%u)\n", buf, ic->server->server_hostname,
af84459fbf938e508fd10b01cb8d699c79083813takashi ic->server->defn_name, ic->server->defn_line_number);
af84459fbf938e508fd10b01cb8d699c79083813takashi return;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_fprintf(f, "%-22s is a NameVirtualHost\n"
5effc8b39fae5cd169d17f342bfc265705840014rbowen "%8s default server %s (%s:%u)\n",
5effc8b39fae5cd169d17f342bfc265705840014rbowen buf, "", ic->server->server_hostname,
af84459fbf938e508fd10b01cb8d699c79083813takashi ic->server->defn_name, ic->server->defn_line_number);
5effc8b39fae5cd169d17f342bfc265705840014rbowen for (nc = ic->names; nc; nc = nc->next) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (nc->sar->host_port) {
4aa603e6448b99f9371397d439795c91a93637eand apr_fprintf(f, "%8s port %u ", "", nc->sar->host_port);
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh }
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh else {
4aa603e6448b99f9371397d439795c91a93637eand apr_fprintf(f, "%8s port * ", "");
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh }
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_fprintf(f, "namevhost %s (%s:%u)\n", nc->server->server_hostname,
5effc8b39fae5cd169d17f342bfc265705840014rbowen nc->server->defn_name, nc->server->defn_line_number);
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen}
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowenstatic void dump_vhost_config(apr_file_t *f)
5effc8b39fae5cd169d17f342bfc265705840014rbowen{
af84459fbf938e508fd10b01cb8d699c79083813takashi ipaddr_chain *ic;
af84459fbf938e508fd10b01cb8d699c79083813takashi int i;
af84459fbf938e508fd10b01cb8d699c79083813takashi
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_fprintf(f, "VirtualHost configuration:\n");
af84459fbf938e508fd10b01cb8d699c79083813takashi for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
af84459fbf938e508fd10b01cb8d699c79083813takashi for (ic = iphash_table[i]; ic; ic = ic->next) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen dump_a_vhost(f, ic);
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (default_list) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_fprintf(f, "wildcard NameVirtualHosts and _default_ servers:\n");
5effc8b39fae5cd169d17f342bfc265705840014rbowen for (ic = default_list; ic; ic = ic->next) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen dump_a_vhost(f, ic);
af84459fbf938e508fd10b01cb8d699c79083813takashi }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen}
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen/*
5effc8b39fae5cd169d17f342bfc265705840014rbowen * Two helper functions for ap_fini_vhost_config()
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowenstatic int add_name_vhost_config(apr_pool_t *p, server_rec *main_s, server_rec *s,
5effc8b39fae5cd169d17f342bfc265705840014rbowen server_addr_rec *sar, ipaddr_chain *ic)
5effc8b39fae5cd169d17f342bfc265705840014rbowen{
af84459fbf938e508fd10b01cb8d699c79083813takashi /* the first time we encounter a NameVirtualHost address
5effc8b39fae5cd169d17f342bfc265705840014rbowen * ic->server will be NULL, on subsequent encounters
5effc8b39fae5cd169d17f342bfc265705840014rbowen * ic->names will be non-NULL.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (ic->names || ic->server == NULL) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen name_chain *nc = new_name_chain(p, s, sar);
5effc8b39fae5cd169d17f342bfc265705840014rbowen nc->next = ic->names;
5effc8b39fae5cd169d17f342bfc265705840014rbowen ic->names = nc;
5effc8b39fae5cd169d17f342bfc265705840014rbowen ic->server = s;
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (sar->host_port != ic->sar->host_port) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* one of the two is a * port, the other isn't */
5effc8b39fae5cd169d17f342bfc265705840014rbowen ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, main_s,
5effc8b39fae5cd169d17f342bfc265705840014rbowen "VirtualHost %s:%u -- mixing * "
5effc8b39fae5cd169d17f342bfc265705840014rbowen "ports and non-* ports with "
5effc8b39fae5cd169d17f342bfc265705840014rbowen "a NameVirtualHost address is not supported,"
5effc8b39fae5cd169d17f342bfc265705840014rbowen " proceeding with undefined results",
5effc8b39fae5cd169d17f342bfc265705840014rbowen sar->virthost, sar->host_port);
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen return 1;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
af84459fbf938e508fd10b01cb8d699c79083813takashi else {
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* IP-based vhosts are handled by the caller */
5effc8b39fae5cd169d17f342bfc265705840014rbowen return 0;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen}
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowenstatic void remove_unused_name_vhosts(server_rec *main_s, ipaddr_chain **pic)
5effc8b39fae5cd169d17f342bfc265705840014rbowen{
5effc8b39fae5cd169d17f342bfc265705840014rbowen while (*pic) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen ipaddr_chain *ic = *pic;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (ic->server == NULL) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, main_s,
5effc8b39fae5cd169d17f342bfc265705840014rbowen "NameVirtualHost %s:%u has no VirtualHosts",
5effc8b39fae5cd169d17f342bfc265705840014rbowen ic->sar->virthost, ic->sar->host_port);
5effc8b39fae5cd169d17f342bfc265705840014rbowen *pic = ic->next;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen else if (ic->names == NULL) {
af84459fbf938e508fd10b01cb8d699c79083813takashi /* if server != NULL and names == NULL then we're done
af84459fbf938e508fd10b01cb8d699c79083813takashi * looking at NameVirtualHosts
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
af84459fbf938e508fd10b01cb8d699c79083813takashi break;
af84459fbf938e508fd10b01cb8d699c79083813takashi }
5effc8b39fae5cd169d17f342bfc265705840014rbowen else {
5effc8b39fae5cd169d17f342bfc265705840014rbowen pic = &ic->next;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
af84459fbf938e508fd10b01cb8d699c79083813takashi}
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen/* compile the tables and such we need to do the run-time vhost lookups */
5effc8b39fae5cd169d17f342bfc265705840014rbowenAP_DECLARE(void) ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s)
5effc8b39fae5cd169d17f342bfc265705840014rbowen{
5effc8b39fae5cd169d17f342bfc265705840014rbowen server_addr_rec *sar;
5effc8b39fae5cd169d17f342bfc265705840014rbowen int has_default_vhost_addr;
5effc8b39fae5cd169d17f342bfc265705840014rbowen server_rec *s;
5effc8b39fae5cd169d17f342bfc265705840014rbowen int i;
af84459fbf938e508fd10b01cb8d699c79083813takashi ipaddr_chain **iphash_table_tail[IPHASH_TABLE_SIZE];
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* terminate the name_vhost list */
5effc8b39fae5cd169d17f342bfc265705840014rbowen *name_vhost_list_tail = NULL;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* Main host first */
5effc8b39fae5cd169d17f342bfc265705840014rbowen s = main_s;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (!s->server_hostname) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen s->server_hostname = ap_get_local_host(p);
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* initialize the tails */
5effc8b39fae5cd169d17f342bfc265705840014rbowen for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen iphash_table_tail[i] = &iphash_table[i];
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* The first things to go into the hash apr_table_t are the NameVirtualHosts
5effc8b39fae5cd169d17f342bfc265705840014rbowen * Since name_vhost_list is in the same order that the directives
5effc8b39fae5cd169d17f342bfc265705840014rbowen * occured in the config file, we'll copy it in that order.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowen for (sar = name_vhost_list; sar; sar = sar->next) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen unsigned bucket = hash_addr(sar->host_addr);
af84459fbf938e508fd10b01cb8d699c79083813takashi ipaddr_chain *ic = new_ipaddr_chain(p, NULL, sar);
5effc8b39fae5cd169d17f342bfc265705840014rbowen
af84459fbf938e508fd10b01cb8d699c79083813takashi if (sar->host_addr->sa.sin.sin_addr.s_addr != INADDR_ANY) {
af84459fbf938e508fd10b01cb8d699c79083813takashi *iphash_table_tail[bucket] = ic;
5effc8b39fae5cd169d17f342bfc265705840014rbowen iphash_table_tail[bucket] = &ic->next;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen else {
af84459fbf938e508fd10b01cb8d699c79083813takashi /* A wildcard NameVirtualHost goes on the default_list so
af84459fbf938e508fd10b01cb8d699c79083813takashi * that it can catch incoming requests on any address.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowen ic->next = default_list;
5effc8b39fae5cd169d17f342bfc265705840014rbowen default_list = ic;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* Notice that what we've done is insert an ipaddr_chain with
5effc8b39fae5cd169d17f342bfc265705840014rbowen * both server and names NULL. This fact is used to spot name-
5effc8b39fae5cd169d17f342bfc265705840014rbowen * based vhosts in add_name_vhost_config().
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* The next things to go into the hash apr_table_t are the virtual hosts
5effc8b39fae5cd169d17f342bfc265705840014rbowen * themselves. They're listed off of main_s->next in the reverse
5effc8b39fae5cd169d17f342bfc265705840014rbowen * order they occured in the config file, so we insert them at
5effc8b39fae5cd169d17f342bfc265705840014rbowen * the iphash_table_tail but don't advance the tail.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen for (s = main_s->next; s; s = s->next) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen has_default_vhost_addr = 0;
5effc8b39fae5cd169d17f342bfc265705840014rbowen for (sar = s->addrs; sar; sar = sar->next) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen ipaddr_chain *ic;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (sar->host_addr->sa.sin.sin_addr.s_addr == DEFAULT_VHOST_ADDR
af84459fbf938e508fd10b01cb8d699c79083813takashi || sar->host_addr->sa.sin.sin_addr.s_addr == INADDR_ANY) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen ic = find_default_server(sar->host_port);
af84459fbf938e508fd10b01cb8d699c79083813takashi if (!ic || !add_name_vhost_config(p, main_s, s, sar, ic)) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (ic && ic->sar->host_port != 0) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
5effc8b39fae5cd169d17f342bfc265705840014rbowen 0, main_s, "_default_ VirtualHost overlap on port %u,"
af84459fbf938e508fd10b01cb8d699c79083813takashi " the first has precedence", sar->host_port);
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
af84459fbf938e508fd10b01cb8d699c79083813takashi ic = new_ipaddr_chain(p, s, sar);
5effc8b39fae5cd169d17f342bfc265705840014rbowen ic->next = default_list;
5effc8b39fae5cd169d17f342bfc265705840014rbowen default_list = ic;
af84459fbf938e508fd10b01cb8d699c79083813takashi }
5effc8b39fae5cd169d17f342bfc265705840014rbowen has_default_vhost_addr = 1;
af84459fbf938e508fd10b01cb8d699c79083813takashi }
5effc8b39fae5cd169d17f342bfc265705840014rbowen else {
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* see if it matches something we've already got */
5effc8b39fae5cd169d17f342bfc265705840014rbowen ic = find_ipaddr(sar->host_addr);
af84459fbf938e508fd10b01cb8d699c79083813takashi
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (!ic) {
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf unsigned bucket = hash_addr(sar->host_addr);
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi ic = new_ipaddr_chain(p, s, sar);
5effc8b39fae5cd169d17f342bfc265705840014rbowen ic->next = *iphash_table_tail[bucket];
5effc8b39fae5cd169d17f342bfc265705840014rbowen *iphash_table_tail[bucket] = ic;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen else if (!add_name_vhost_config(p, main_s, s, sar, ic)) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, main_s,
5effc8b39fae5cd169d17f342bfc265705840014rbowen "VirtualHost %s:%u overlaps with "
5effc8b39fae5cd169d17f342bfc265705840014rbowen "VirtualHost %s:%u, the first has precedence, "
5effc8b39fae5cd169d17f342bfc265705840014rbowen "perhaps you need a NameVirtualHost directive",
5effc8b39fae5cd169d17f342bfc265705840014rbowen sar->virthost, sar->host_port,
5effc8b39fae5cd169d17f342bfc265705840014rbowen ic->sar->virthost, ic->sar->host_port);
5effc8b39fae5cd169d17f342bfc265705840014rbowen ic->sar = sar;
5effc8b39fae5cd169d17f342bfc265705840014rbowen ic->server = s;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* Ok now we want to set up a server_hostname if the user was
5effc8b39fae5cd169d17f342bfc265705840014rbowen * silly enough to forget one.
5effc8b39fae5cd169d17f342bfc265705840014rbowen * XXX: This is silly we should just crash and burn.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (!s->server_hostname) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (has_default_vhost_addr) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen s->server_hostname = main_s->server_hostname;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen else if (!s->addrs) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* what else can we do? at this point this vhost has
5effc8b39fae5cd169d17f342bfc265705840014rbowen no configured name, probably because they used
5effc8b39fae5cd169d17f342bfc265705840014rbowen DNS in the VirtualHost statement. It's disabled
5effc8b39fae5cd169d17f342bfc265705840014rbowen anyhow by the host matching code. -djg */
5effc8b39fae5cd169d17f342bfc265705840014rbowen s->server_hostname =
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_pstrdup(p, "bogus_host_without_forward_dns");
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen else {
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_status_t rv;
5effc8b39fae5cd169d17f342bfc265705840014rbowen char *hostname;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen rv = apr_getnameinfo(&hostname, s->addrs->host_addr, 0);
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (rv == APR_SUCCESS) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen s->server_hostname = apr_pstrdup(p, hostname);
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen else {
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* again, what can we do? They didn't specify a
20f499565e77defe9dab24dd85c02f38a1175855nd ServerName, and their DNS isn't working. -djg */
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh char *ipaddr_str;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_get_ipaddr(&ipaddr_str, s->addrs->host_addr);
5effc8b39fae5cd169d17f342bfc265705840014rbowen ap_log_error(APLOG_MARK, APLOG_ERR, rv, main_s,
5effc8b39fae5cd169d17f342bfc265705840014rbowen "Failed to resolve server name "
5effc8b39fae5cd169d17f342bfc265705840014rbowen "for %s (check DNS) -- or specify an explicit "
5effc8b39fae5cd169d17f342bfc265705840014rbowen "ServerName",
5effc8b39fae5cd169d17f342bfc265705840014rbowen ipaddr_str);
5effc8b39fae5cd169d17f342bfc265705840014rbowen s->server_hostname =
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_pstrdup(p, "bogus_host_without_reverse_dns");
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* now go through and delete any NameVirtualHosts that didn't have any
5effc8b39fae5cd169d17f342bfc265705840014rbowen * hosts associated with them. Lamers.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowen for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen remove_unused_name_vhosts(main_s, &iphash_table[i]);
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen remove_unused_name_vhosts(main_s, &default_list);
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen#ifdef IPHASH_STATISTICS
af84459fbf938e508fd10b01cb8d699c79083813takashi dump_iphash_statistics(main_s);
af84459fbf938e508fd10b01cb8d699c79083813takashi#endif
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (ap_exists_config_define("DUMP_VHOSTS")) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_file_t *thefile = NULL;
af84459fbf938e508fd10b01cb8d699c79083813takashi apr_open_stderr(&thefile, p);
af84459fbf938e508fd10b01cb8d699c79083813takashi dump_vhost_config(thefile);
af84459fbf938e508fd10b01cb8d699c79083813takashi }
af84459fbf938e508fd10b01cb8d699c79083813takashi}
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi/*****************************************************************************
af84459fbf938e508fd10b01cb8d699c79083813takashi * run-time vhost matching functions
af84459fbf938e508fd10b01cb8d699c79083813takashi */
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi/* Lowercase and remove any trailing dot and/or :port from the hostname,
af84459fbf938e508fd10b01cb8d699c79083813takashi * and check that it is sane.
af84459fbf938e508fd10b01cb8d699c79083813takashi *
af84459fbf938e508fd10b01cb8d699c79083813takashi * In most configurations the exact syntax of the hostname isn't
af84459fbf938e508fd10b01cb8d699c79083813takashi * important so strict sanity checking isn't necessary. However, in
af84459fbf938e508fd10b01cb8d699c79083813takashi * mass hosting setups (using mod_vhost_alias or mod_rewrite) where
3c13a815670b54d1c17bf02954f7d2b066cde95cnd * the hostname is interpolated into the filename, we need to be sure
af84459fbf938e508fd10b01cb8d699c79083813takashi * that the interpolation doesn't expose parts of the filesystem.
af84459fbf938e508fd10b01cb8d699c79083813takashi * We don't do strict RFC 952 / RFC 1123 syntax checking in order
af84459fbf938e508fd10b01cb8d699c79083813takashi * to support iDNS and people who erroneously use underscores.
5effc8b39fae5cd169d17f342bfc265705840014rbowen * Instead we just check for filesystem metacharacters: directory
af84459fbf938e508fd10b01cb8d699c79083813takashi * separators / and \ and sequences of more than one dot.
af84459fbf938e508fd10b01cb8d699c79083813takashi */
af84459fbf938e508fd10b01cb8d699c79083813takashistatic void fix_hostname(request_rec *r)
af84459fbf938e508fd10b01cb8d699c79083813takashi{
af84459fbf938e508fd10b01cb8d699c79083813takashi char *host, *scope_id;
af84459fbf938e508fd10b01cb8d699c79083813takashi char *dst;
af84459fbf938e508fd10b01cb8d699c79083813takashi apr_port_t port;
af84459fbf938e508fd10b01cb8d699c79083813takashi apr_status_t rv;
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool);
4aa603e6448b99f9371397d439795c91a93637eand if (rv != APR_SUCCESS || scope_id) {
af84459fbf938e508fd10b01cb8d699c79083813takashi goto bad;
af84459fbf938e508fd10b01cb8d699c79083813takashi }
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi /* if the hostname is an IPv6 numeric address string, it was validated
af84459fbf938e508fd10b01cb8d699c79083813takashi * already; otherwise, further validation is needed
af84459fbf938e508fd10b01cb8d699c79083813takashi */
af84459fbf938e508fd10b01cb8d699c79083813takashi if (r->hostname[0] != '[') {
af84459fbf938e508fd10b01cb8d699c79083813takashi dst = host;
af84459fbf938e508fd10b01cb8d699c79083813takashi while (*dst) {
af84459fbf938e508fd10b01cb8d699c79083813takashi if (!apr_isalnum(*dst) && *dst != '-') {
af84459fbf938e508fd10b01cb8d699c79083813takashi if (*dst == '.') {
af84459fbf938e508fd10b01cb8d699c79083813takashi dst++;
af84459fbf938e508fd10b01cb8d699c79083813takashi if (*dst == '.')
af84459fbf938e508fd10b01cb8d699c79083813takashi goto bad;
af84459fbf938e508fd10b01cb8d699c79083813takashi else
af84459fbf938e508fd10b01cb8d699c79083813takashi continue;
3c13a815670b54d1c17bf02954f7d2b066cde95cnd }
af84459fbf938e508fd10b01cb8d699c79083813takashi goto bad;
af84459fbf938e508fd10b01cb8d699c79083813takashi }
af84459fbf938e508fd10b01cb8d699c79083813takashi else {
af84459fbf938e508fd10b01cb8d699c79083813takashi dst++;
af84459fbf938e508fd10b01cb8d699c79083813takashi }
3c13a815670b54d1c17bf02954f7d2b066cde95cnd }
3c13a815670b54d1c17bf02954f7d2b066cde95cnd /* strip trailing gubbins */
af84459fbf938e508fd10b01cb8d699c79083813takashi if (dst > host && dst[-1] == '.') {
5effc8b39fae5cd169d17f342bfc265705840014rbowen dst[-1] = '\0';
af84459fbf938e508fd10b01cb8d699c79083813takashi }
af84459fbf938e508fd10b01cb8d699c79083813takashi }
af84459fbf938e508fd10b01cb8d699c79083813takashi r->hostname = host;
3c13a815670b54d1c17bf02954f7d2b066cde95cnd return;
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashibad:
5effc8b39fae5cd169d17f342bfc265705840014rbowen r->status = HTTP_BAD_REQUEST;
af84459fbf938e508fd10b01cb8d699c79083813takashi ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
af84459fbf938e508fd10b01cb8d699c79083813takashi "Client sent malformed Host header");
0cf3cdbaa1dad11cbf1ce32e48f1b4ec88cf779fnilgun return;
af84459fbf938e508fd10b01cb8d699c79083813takashi}
3c13a815670b54d1c17bf02954f7d2b066cde95cnd
3c13a815670b54d1c17bf02954f7d2b066cde95cnd
3c13a815670b54d1c17bf02954f7d2b066cde95cnd/* return 1 if host matches ServerName or ServerAliases */
af84459fbf938e508fd10b01cb8d699c79083813takashistatic int matches_aliases(server_rec *s, const char *host)
af84459fbf938e508fd10b01cb8d699c79083813takashi{
af84459fbf938e508fd10b01cb8d699c79083813takashi int i;
20f499565e77defe9dab24dd85c02f38a1175855nd apr_array_header_t *names;
888cb40bdeec5abf452bd85d6bf63b26d5913d4chumbedooh
af84459fbf938e508fd10b01cb8d699c79083813takashi /* match ServerName */
af84459fbf938e508fd10b01cb8d699c79083813takashi if (!strcasecmp(host, s->server_hostname)) {
af84459fbf938e508fd10b01cb8d699c79083813takashi return 1;
3c13a815670b54d1c17bf02954f7d2b066cde95cnd }
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashi /* search all the aliases from ServerAlias directive */
af84459fbf938e508fd10b01cb8d699c79083813takashi names = s->names;
0cf3cdbaa1dad11cbf1ce32e48f1b4ec88cf779fnilgun if (names) {
af84459fbf938e508fd10b01cb8d699c79083813takashi char **name = (char **) names->elts;
3c13a815670b54d1c17bf02954f7d2b066cde95cnd for (i = 0; i < names->nelts; ++i) {
af84459fbf938e508fd10b01cb8d699c79083813takashi if(!name[i]) continue;
af84459fbf938e508fd10b01cb8d699c79083813takashi if (!strcasecmp(host, name[i]))
af84459fbf938e508fd10b01cb8d699c79083813takashi return 1;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
af84459fbf938e508fd10b01cb8d699c79083813takashi }
af84459fbf938e508fd10b01cb8d699c79083813takashi names = s->wild_names;
af84459fbf938e508fd10b01cb8d699c79083813takashi if (names) {
af84459fbf938e508fd10b01cb8d699c79083813takashi char **name = (char **) names->elts;
5effc8b39fae5cd169d17f342bfc265705840014rbowen for (i = 0; i < names->nelts; ++i) {
af84459fbf938e508fd10b01cb8d699c79083813takashi if(!name[i]) continue;
af84459fbf938e508fd10b01cb8d699c79083813takashi if (!ap_strcasecmp_match(host, name[i]))
5effc8b39fae5cd169d17f342bfc265705840014rbowen return 1;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
af84459fbf938e508fd10b01cb8d699c79083813takashi }
5effc8b39fae5cd169d17f342bfc265705840014rbowen return 0;
5effc8b39fae5cd169d17f342bfc265705840014rbowen}
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen/* Suppose a request came in on the same socket as this r, and included
5effc8b39fae5cd169d17f342bfc265705840014rbowen * a header "Host: host:port", would it map to r->server? It's more
af84459fbf938e508fd10b01cb8d699c79083813takashi * than just that though. When we do the normal matches for each request
5effc8b39fae5cd169d17f342bfc265705840014rbowen * we don't even bother considering Host: etc on non-namevirtualhosts,
5effc8b39fae5cd169d17f342bfc265705840014rbowen * we just call it a match. But here we require the host:port to match
5effc8b39fae5cd169d17f342bfc265705840014rbowen * the ServerName and/or ServerAliases.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowenAP_DECLARE(int) ap_matches_request_vhost(request_rec *r, const char *host,
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_port_t port)
5effc8b39fae5cd169d17f342bfc265705840014rbowen{
5effc8b39fae5cd169d17f342bfc265705840014rbowen server_rec *s;
5effc8b39fae5cd169d17f342bfc265705840014rbowen server_addr_rec *sar;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
af84459fbf938e508fd10b01cb8d699c79083813takashi s = r->server;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* search all the <VirtualHost> values */
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* XXX: If this is a NameVirtualHost then we may not be doing the Right Thing
5effc8b39fae5cd169d17f342bfc265705840014rbowen * consider:
5effc8b39fae5cd169d17f342bfc265705840014rbowen *
5effc8b39fae5cd169d17f342bfc265705840014rbowen * NameVirtualHost 10.1.1.1
5effc8b39fae5cd169d17f342bfc265705840014rbowen * <VirtualHost 10.1.1.1>
5effc8b39fae5cd169d17f342bfc265705840014rbowen * ServerName v1
af84459fbf938e508fd10b01cb8d699c79083813takashi * </VirtualHost>
5effc8b39fae5cd169d17f342bfc265705840014rbowen * <VirtualHost 10.1.1.1>
5effc8b39fae5cd169d17f342bfc265705840014rbowen * ServerName v2
5effc8b39fae5cd169d17f342bfc265705840014rbowen * </VirtualHost>
af84459fbf938e508fd10b01cb8d699c79083813takashi *
5effc8b39fae5cd169d17f342bfc265705840014rbowen * Suppose r->server is v2, and we're asked to match "10.1.1.1". We'll say
af84459fbf938e508fd10b01cb8d699c79083813takashi * "yup it's v2", when really it isn't... if a request came in for 10.1.1.1
5effc8b39fae5cd169d17f342bfc265705840014rbowen * it would really go to v1.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
af84459fbf938e508fd10b01cb8d699c79083813takashi for (sar = s->addrs; sar; sar = sar->next) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen if ((sar->host_port == 0 || port == sar->host_port)
5effc8b39fae5cd169d17f342bfc265705840014rbowen && !strcasecmp(host, sar->virthost)) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen return 1;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* the Port has to match now, because the rest don't have ports associated
5effc8b39fae5cd169d17f342bfc265705840014rbowen * with them. */
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (port != s->port) {
af84459fbf938e508fd10b01cb8d699c79083813takashi return 0;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen return matches_aliases(s, host);
5effc8b39fae5cd169d17f342bfc265705840014rbowen}
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen
af84459fbf938e508fd10b01cb8d699c79083813takashistatic void check_hostalias(request_rec *r)
5effc8b39fae5cd169d17f342bfc265705840014rbowen{
5effc8b39fae5cd169d17f342bfc265705840014rbowen /*
5effc8b39fae5cd169d17f342bfc265705840014rbowen * Even if the request has a Host: header containing a port we ignore
5effc8b39fae5cd169d17f342bfc265705840014rbowen * that port. We always use the physical port of the socket. There
5effc8b39fae5cd169d17f342bfc265705840014rbowen * are a few reasons for this:
5effc8b39fae5cd169d17f342bfc265705840014rbowen *
5effc8b39fae5cd169d17f342bfc265705840014rbowen * - the default of 80 or 443 for SSL is easier to handle this way
5effc8b39fae5cd169d17f342bfc265705840014rbowen * - there is less of a possibility of a security problem
af84459fbf938e508fd10b01cb8d699c79083813takashi * - it simplifies the data structure
af84459fbf938e508fd10b01cb8d699c79083813takashi * - the client may have no idea that a proxy somewhere along the way
af84459fbf938e508fd10b01cb8d699c79083813takashi * translated the request to another ip:port
5effc8b39fae5cd169d17f342bfc265705840014rbowen * - except for the addresses from the VirtualHost line, none of the other
af84459fbf938e508fd10b01cb8d699c79083813takashi * names we'll match have ports associated with them
af84459fbf938e508fd10b01cb8d699c79083813takashi */
5effc8b39fae5cd169d17f342bfc265705840014rbowen const char *host = r->hostname;
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_port_t port;
5effc8b39fae5cd169d17f342bfc265705840014rbowen server_rec *s;
5effc8b39fae5cd169d17f342bfc265705840014rbowen server_rec *last_s;
5effc8b39fae5cd169d17f342bfc265705840014rbowen name_chain *src;
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_sockaddr_t *localsa;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
af84459fbf938e508fd10b01cb8d699c79083813takashi last_s = NULL;
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_get_sockaddr(&localsa, APR_LOCAL, r->connection->client_socket);
5effc8b39fae5cd169d17f342bfc265705840014rbowen apr_get_port(&port, localsa);
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* Recall that the name_chain is a list of server_addr_recs, some of
5effc8b39fae5cd169d17f342bfc265705840014rbowen * whose ports may not match. Also each server may appear more than
5effc8b39fae5cd169d17f342bfc265705840014rbowen * once in the chain -- specifically, it will appear once for each
af84459fbf938e508fd10b01cb8d699c79083813takashi * address from its VirtualHost line which matched. We only want to
5effc8b39fae5cd169d17f342bfc265705840014rbowen * do the full ServerName/ServerAlias comparisons once for each
5effc8b39fae5cd169d17f342bfc265705840014rbowen * server, fortunately we know that all the VirtualHost addresses for
5effc8b39fae5cd169d17f342bfc265705840014rbowen * a single server are adjacent to each other.
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen for (src = r->connection->vhost_lookup_data; src; src = src->next) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen server_addr_rec *sar;
af84459fbf938e508fd10b01cb8d699c79083813takashi
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* We only consider addresses on the name_chain which have a matching
5effc8b39fae5cd169d17f342bfc265705840014rbowen * port
af84459fbf938e508fd10b01cb8d699c79083813takashi */
5effc8b39fae5cd169d17f342bfc265705840014rbowen sar = src->sar;
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (sar->host_port != 0 && port != sar->host_port) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen continue;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen s = src->server;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* does it match the virthost from the sar? */
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (!strcasecmp(host, sar->virthost)) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen goto found;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (s == last_s) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen /* we've already done ServerName and ServerAlias checks for this
5effc8b39fae5cd169d17f342bfc265705840014rbowen * vhost
5effc8b39fae5cd169d17f342bfc265705840014rbowen */
5effc8b39fae5cd169d17f342bfc265705840014rbowen continue;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen last_s = s;
5effc8b39fae5cd169d17f342bfc265705840014rbowen
5effc8b39fae5cd169d17f342bfc265705840014rbowen if (matches_aliases(s, host)) {
5effc8b39fae5cd169d17f342bfc265705840014rbowen goto found;
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
5effc8b39fae5cd169d17f342bfc265705840014rbowen }
af84459fbf938e508fd10b01cb8d699c79083813takashi return;
af84459fbf938e508fd10b01cb8d699c79083813takashi
af84459fbf938e508fd10b01cb8d699c79083813takashifound:
af84459fbf938e508fd10b01cb8d699c79083813takashi /* s is the first matching server, we're done */
af84459fbf938e508fd10b01cb8d699c79083813takashi r->server = s;
f086b4b402fa9a2fefc7dda85de2a3cc1cd0a654rjung}
727872d18412fc021f03969b8641810d8896820bhumbedooh
0d0ba3a410038e179b695446bb149cce6264e0abnd
727872d18412fc021f03969b8641810d8896820bhumbedoohstatic void check_serverpath(request_rec *r)
cc7e1025de9ac63bd4db6fe7f71c158b2cf09fe4humbedooh{
0d0ba3a410038e179b695446bb149cce6264e0abnd server_rec *s;
cc7e1025de9ac63bd4db6fe7f71c158b2cf09fe4humbedooh server_rec *last_s;
727872d18412fc021f03969b8641810d8896820bhumbedooh name_chain *src;
0d0ba3a410038e179b695446bb149cce6264e0abnd apr_port_t port;
0d0ba3a410038e179b695446bb149cce6264e0abnd apr_sockaddr_t *localsa;
0d0ba3a410038e179b695446bb149cce6264e0abnd
ac082aefa89416cbdc9a1836eaf3bed9698201c8humbedooh apr_get_sockaddr(&localsa, APR_LOCAL, r->connection->client_socket);
0d0ba3a410038e179b695446bb149cce6264e0abnd apr_get_port(&port, localsa);
0d0ba3a410038e179b695446bb149cce6264e0abnd
0d0ba3a410038e179b695446bb149cce6264e0abnd /*
727872d18412fc021f03969b8641810d8896820bhumbedooh * This is in conjunction with the ServerPath code in http_core, so we
0d0ba3a410038e179b695446bb149cce6264e0abnd * get the right host attached to a non- Host-sending request.
0d0ba3a410038e179b695446bb149cce6264e0abnd *
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh * See the comment in check_hostalias about how each vhost can be
205f749042ed530040a4f0080dbcb47ceae8a374rjung * listed multiple times.
af33a4994ae2ff15bc67d19ff1a7feb906745bf8rbowen */
0d0ba3a410038e179b695446bb149cce6264e0abnd
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd last_s = NULL;
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd for (src = r->connection->vhost_lookup_data; src; src = src->next) {
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd /* We only consider addresses on the name_chain which have a matching
af84459fbf938e508fd10b01cb8d699c79083813takashi * 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 = apr_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;
apr_port_t port;
/* scan the hash apr_table_t for an exact match first */
trav = find_ipaddr(conn->local_addr);
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;
}
/* maybe there's a default server or wildcard name-based vhost
* matching this port
*/
apr_get_port(&port, conn->local_addr);
trav = find_default_server(port);
if (trav) {
conn->vhost_lookup_data = trav->names;
conn->base_server = trav->server;
return;
}
/* otherwise we're stuck with just the main server
* and no name-based vhosts
*/
conn->vhost_lookup_data = NULL;
}