1 /* ====================================================================
2 * The Apache Software License, Version 1.1
4 * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
19 * 3. The end-user documentation included with the redistribution,
20 * if any, must include the following acknowledgment:
21 * "This product includes software developed by the
22 * Apache Software Foundation (http://www.apache.org/)."
23 * Alternately, this acknowledgment may appear in the software itself,
24 * if and wherever such third-party acknowledgments normally appear.
26 * 4. The names "Apache" and "Apache Software Foundation" must
27 * not be used to endorse or promote products derived from this
28 * software without prior written permission. For written
29 * permission, please contact apache@apache.org.
31 * 5. Products derived from this software may not be called "Apache",
32 * nor may "Apache" appear in their name, without prior written
33 * permission of the Apache Software Foundation.
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * ====================================================================
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation. For more
51 * information on the Apache Software Foundation, please see
52 * <http://www.apache.org/>.
54 * Portions of this software are based upon public domain software
55 * originally written at the National Center for Supercomputing Applications,
56 * University of Illinois, Urbana-Champaign.
60 * http_vhost.c: functions pertaining to virtual host addresses
61 * (configuration and run-time)
65 #include "apr_strings.h"
68 #define APR_WANT_STRFUNC
72 #include "ap_config.h"
74 #include "http_config.h"
76 #include "http_vhost.h"
77 #include "http_protocol.h"
78 #include "http_core.h"
80 #if APR_HAVE_ARPA_INET_H
81 #include <arpa/inet.h>
85 * After all the definitions there's an explanation of how it's all put
89 /* meta-list of name-vhosts. Each server_rec can be in possibly multiple
90 * lists of name-vhosts.
92 typedef struct name_chain name_chain;
95 server_addr_rec *sar; /* the record causing it to be in
96 * this chain (needed for port comparisons) */
97 server_rec *server; /* the server to use on a match */
100 /* meta-list of ip addresses. Each server_rec can be in possibly multiple
101 * hash chains since it can have multiple ips.
103 typedef struct ipaddr_chain ipaddr_chain;
104 struct ipaddr_chain {
106 server_addr_rec *sar; /* the record causing it to be in
107 * this chain (need for both ip addr and port
109 server_rec *server; /* the server to use if this matches */
110 name_chain *names; /* if non-NULL then a list of name-vhosts
111 * sharing this address */
114 /* This defines the size of the hash apr_table_t used for hashing ip addresses
115 * of virtual hosts. It must be a power of two.
117 #ifndef IPHASH_TABLE_SIZE
118 #define IPHASH_TABLE_SIZE 256
121 /* A (n) bucket hash table, each entry has a pointer to a server rec and
122 * a pointer to the other entries in that bucket. Each individual address,
123 * even for virtualhosts with multiple addresses, has an entry in this hash
124 * table. There are extra buckets for _default_, and name-vhost entries.
126 * Note that after config time this is constant, so it is thread-safe.
128 static ipaddr_chain *iphash_table[IPHASH_TABLE_SIZE];
130 /* dump out statistics about the hash function */
131 /* #define IPHASH_STATISTICS */
133 /* list of the _default_ servers */
134 static ipaddr_chain *default_list;
136 /* list of the NameVirtualHost addresses */
137 static server_addr_rec *name_vhost_list;
138 static server_addr_rec **name_vhost_list_tail;
143 * The ip address determines which chain in iphash_table is interesting, then
144 * a comparison is done down that chain to find the first ipaddr_chain whose
145 * sar matches the address:port pair.
147 * If that ipaddr_chain has names == NULL then you're done, it's an ip-vhost.
149 * Otherwise it's a name-vhost list, and the default is the server in the
150 * ipaddr_chain record. We tuck away the ipaddr_chain record in the
151 * conn_rec field vhost_lookup_data. Later on after the headers we get a
152 * second chance, and we use the name_chain to figure out what name-vhost
153 * matches the headers.
155 * If there was no ip address match in the iphash_table then do a lookup
156 * in the default_list.
158 * How it's put together ... well you should be able to figure that out
159 * from how it's used. Or something like that.
163 /* called at the beginning of the config */
164 void ap_init_vhost_config(apr_pool_t *p)
166 memset(iphash_table, 0, sizeof(iphash_table));
168 name_vhost_list = NULL;
169 name_vhost_list_tail = &name_vhost_list;
174 * Parses a host of the form <address>[:port]
175 * paddr is used to create a list in the order of input
176 * **paddr is the ->next pointer of the last entry (or s->addrs)
177 * *paddr is the variable used to keep track of **paddr between calls
178 * port is the default port to assume
180 static const char *get_addresses(apr_pool_t *p, const char *w_,
181 server_addr_rec ***paddr,
182 apr_port_t default_port)
184 apr_sockaddr_t *my_addr;
185 server_addr_rec *sar;
186 char *w, *host, *scope_id;
195 w = apr_pstrdup(p, w_);
196 /* apr_parse_addr_port() doesn't understand ":*" so handle that first. */
197 wlen = strlen(w); /* wlen must be > 0 at this point */
199 if (w[wlen - 1] == '*') {
203 else if (w[wlen - 2] == ':') {
208 rv = apr_parse_addr_port(&host, &scope_id, &port, w, p);
209 /* If the string is "80", apr_parse_addr_port() will be happy and set
210 * host to NULL and port to 80, so watch out for that.
212 if (rv != APR_SUCCESS) {
213 return "The address or port is invalid";
216 return "Missing address for VirtualHost";
219 return "Scope ids are not supported";
221 if (!port && !wild_port) {
225 if (strcmp(host, "*") == 0) {
226 rv = apr_sockaddr_info_get(&my_addr, NULL, APR_INET, port, 0, p);
227 my_addr->sa.sin.sin_addr.s_addr = htonl(INADDR_ANY);
229 else if (strcasecmp(host, "_default_") == 0
230 || strcmp(host, "255.255.255.255") == 0) {
231 rv = apr_sockaddr_info_get(&my_addr, NULL, APR_INET, port, 0, p);
232 ap_assert(rv == APR_SUCCESS); /* must be bug or out of storage */
233 my_addr->sa.sin.sin_addr.s_addr = DEFAULT_VHOST_ADDR;
236 rv = apr_sockaddr_info_get(&my_addr, host, APR_UNSPEC, port, 0, p);
237 if (rv != APR_SUCCESS) {
238 ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
239 "Cannot resolve host name %s --- ignoring!", host);
244 /* XXX Gotta go through *all* addresses for the host name!
245 * Fix apr_sockaddr_info_get() to save them! */
247 sar = apr_pcalloc(p, sizeof(server_addr_rec));
250 sar->host_addr = my_addr;
251 sar->host_port = port;
252 sar->virthost = host;
257 /* parse the <VirtualHost> addresses */
258 const char *ap_parse_vhost_addrs(apr_pool_t *p,
259 const char *hostname,
262 server_addr_rec **addrs;
265 /* start the list of addreses */
267 while (hostname[0]) {
268 err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port);
274 /* terminate the list */
277 if (s->addrs->host_port) {
278 /* override the default port which is inherited from main_server */
279 s->port = s->addrs->host_port;
286 const char *ap_set_name_virtual_host(cmd_parms *cmd, void *dummy,
289 /* use whatever port the main server has at this point */
290 return get_addresses(cmd->pool, arg, &name_vhost_list_tail,
295 /* hash apr_table_t statistics, keep this in here for the beta period so
296 * we can find out if the hash function is ok
298 #ifdef IPHASH_STATISTICS
299 static int iphash_compare(const void *a, const void *b)
301 return (*(const int *) b - *(const int *) a);
305 static void dump_iphash_statistics(server_rec *main_s)
307 unsigned count[IPHASH_TABLE_SIZE];
311 char buf[HUGE_STRING_LEN];
315 for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
317 for (src = iphash_table[i]; src; src = src->next) {
319 if (i < IPHASH_TABLE_SIZE) {
320 /* don't count the slop buckets in the total */
325 qsort(count, IPHASH_TABLE_SIZE, sizeof(count[0]), iphash_compare);
326 p = buf + apr_snprintf(buf, sizeof(buf),
327 "iphash: total hashed = %u, avg chain = %u, "
328 "chain lengths (count x len):",
329 total, total / IPHASH_TABLE_SIZE);
331 for (i = 1; i < IPHASH_TABLE_SIZE; ++i) {
332 if (count[i - 1] != count[i]) {
333 p += apr_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
334 total, count[i - 1]);
341 p += apr_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
342 total, count[IPHASH_TABLE_SIZE - 1]);
343 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, main_s, buf);
348 /* This hashing function is designed to get good distribution in the cases
349 * where the server is handling entire "networks" of servers. i.e. a
350 * whack of /24s. This is probably the most common configuration for
351 * ISPs with large virtual servers.
353 * NOTE: This function is symmetric (i.e. collapses all 4 octets
354 * into one), so machine byte order (big/little endianness) does not matter.
356 * Hash function provided by David Hankins.
358 static APR_INLINE unsigned hash_inaddr(unsigned key)
361 return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE;
364 static APR_INLINE unsigned hash_addr(struct apr_sockaddr_t *sa)
368 /* The key is the last four bytes of the IP address.
369 * For IPv4, this is the entire address, as always.
370 * For IPv6, this is usually part of the MAC address.
372 key = *(unsigned *)((char *)sa->ipaddr_ptr + sa->ipaddr_len - 4);
373 return hash_inaddr(key);
376 static ipaddr_chain *new_ipaddr_chain(apr_pool_t *p,
377 server_rec *s, server_addr_rec *sar)
381 new = apr_palloc(p, sizeof(*new));
390 static name_chain *new_name_chain(apr_pool_t *p,
391 server_rec *s, server_addr_rec *sar)
395 new = apr_palloc(p, sizeof(*new));
403 static APR_INLINE ipaddr_chain *find_ipaddr(apr_sockaddr_t *sa)
408 /* scan the hash apr_table_t for an exact match first */
409 bucket = hash_addr(sa);
410 for (trav = iphash_table[bucket]; trav; trav = trav->next) {
411 server_addr_rec *sar = trav->sar;
412 apr_sockaddr_t *cur = sar->host_addr;
414 if (cur->sa.sin.sin_port == 0 ||
415 sa->sa.sin.sin_port == 0 ||
416 cur->sa.sin.sin_port == sa->sa.sin.sin_port) {
417 if (cur->ipaddr_len == sa->ipaddr_len &&
418 !memcmp(cur->ipaddr_ptr,
429 static ipaddr_chain *find_default_server(apr_port_t port)
431 server_addr_rec *sar;
434 for (trav = default_list; trav; trav = trav->next) {
436 if (sar->host_port == 0 || sar->host_port == port) {
444 static void dump_a_vhost(apr_file_t *f, ipaddr_chain *ic)
448 char buf[MAX_STRING_LEN];
449 apr_sockaddr_t *ha = ic->sar->host_addr;
451 if (ha->sa.sin.sin_family == APR_INET &&
452 ha->sa.sin.sin_addr.s_addr == DEFAULT_VHOST_ADDR) {
453 len = apr_snprintf(buf, sizeof(buf), "_default_:%u",
456 else if (ha->sa.sin.sin_family == APR_INET &&
457 ha->sa.sin.sin_addr.s_addr == INADDR_ANY) {
458 len = apr_snprintf(buf, sizeof(buf), "*:%u",
462 len = apr_snprintf(buf, sizeof(buf), "%pI", ha);
464 if (ic->sar->host_port == 0) {
467 if (ic->names == NULL) {
468 apr_file_printf(f, "%-22s %s (%s:%u)\n", buf,
469 ic->server->server_hostname,
470 ic->server->defn_name, ic->server->defn_line_number);
473 apr_file_printf(f, "%-22s is a NameVirtualHost\n"
474 "%8s default server %s (%s:%u)\n",
475 buf, "", ic->server->server_hostname,
476 ic->server->defn_name, ic->server->defn_line_number);
477 for (nc = ic->names; nc; nc = nc->next) {
478 if (nc->sar->host_port) {
479 apr_file_printf(f, "%8s port %u ", "", nc->sar->host_port);
482 apr_file_printf(f, "%8s port * ", "");
484 apr_file_printf(f, "namevhost %s (%s:%u)\n",
485 nc->server->server_hostname,
486 nc->server->defn_name, nc->server->defn_line_number);
490 static void dump_vhost_config(apr_file_t *f)
495 apr_file_printf(f, "VirtualHost configuration:\n");
496 for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
497 for (ic = iphash_table[i]; ic; ic = ic->next) {
502 apr_file_printf(f, "wildcard NameVirtualHosts and _default_ servers:\n");
503 for (ic = default_list; ic; ic = ic->next) {
510 * Two helper functions for ap_fini_vhost_config()
512 static int add_name_vhost_config(apr_pool_t *p, server_rec *main_s,
513 server_rec *s, server_addr_rec *sar,
516 /* the first time we encounter a NameVirtualHost address
517 * ic->server will be NULL, on subsequent encounters
518 * ic->names will be non-NULL.
520 if (ic->names || ic->server == NULL) {
521 name_chain *nc = new_name_chain(p, s, sar);
522 nc->next = ic->names;
525 if (sar->host_port != ic->sar->host_port) {
526 /* one of the two is a * port, the other isn't */
527 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, main_s,
528 "VirtualHost %s:%u -- mixing * "
529 "ports and non-* ports with "
530 "a NameVirtualHost address is not supported,"
531 " proceeding with undefined results",
532 sar->virthost, sar->host_port);
537 /* IP-based vhosts are handled by the caller */
542 static void remove_unused_name_vhosts(server_rec *main_s, ipaddr_chain **pic)
545 ipaddr_chain *ic = *pic;
547 if (ic->server == NULL) {
548 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, main_s,
549 "NameVirtualHost %s:%u has no VirtualHosts",
550 ic->sar->virthost, ic->sar->host_port);
553 else if (ic->names == NULL) {
554 /* if server != NULL and names == NULL then we're done
555 * looking at NameVirtualHosts
565 /* compile the tables and such we need to do the run-time vhost lookups */
566 AP_DECLARE(void) ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s)
568 server_addr_rec *sar;
569 int has_default_vhost_addr;
572 ipaddr_chain **iphash_table_tail[IPHASH_TABLE_SIZE];
574 /* terminate the name_vhost list */
575 *name_vhost_list_tail = NULL;
577 /* Main host first */
580 if (!s->server_hostname) {
581 s->server_hostname = ap_get_local_host(p);
584 /* initialize the tails */
585 for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
586 iphash_table_tail[i] = &iphash_table[i];
589 /* The first things to go into the hash apr_table_t are the NameVirtualHosts
590 * Since name_vhost_list is in the same order that the directives
591 * occured in the config file, we'll copy it in that order.
593 for (sar = name_vhost_list; sar; sar = sar->next) {
594 unsigned bucket = hash_addr(sar->host_addr);
595 ipaddr_chain *ic = new_ipaddr_chain(p, NULL, sar);
597 if (sar->host_addr->sa.sin.sin_addr.s_addr != INADDR_ANY) {
598 *iphash_table_tail[bucket] = ic;
599 iphash_table_tail[bucket] = &ic->next;
602 /* A wildcard NameVirtualHost goes on the default_list so
603 * that it can catch incoming requests on any address.
605 ic->next = default_list;
608 /* Notice that what we've done is insert an ipaddr_chain with
609 * both server and names NULL. This fact is used to spot name-
610 * based vhosts in add_name_vhost_config().
614 /* The next things to go into the hash apr_table_t are the virtual hosts
615 * themselves. They're listed off of main_s->next in the reverse
616 * order they occured in the config file, so we insert them at
617 * the iphash_table_tail but don't advance the tail.
620 for (s = main_s->next; s; s = s->next) {
621 has_default_vhost_addr = 0;
622 for (sar = s->addrs; sar; sar = sar->next) {
624 char inaddr_any[16] = {0}; /* big enough to handle IPv4 or IPv6 */
626 if ((sar->host_addr->family == AF_INET &&
627 sar->host_addr->sa.sin.sin_addr.s_addr == DEFAULT_VHOST_ADDR)
628 || !memcmp(sar->host_addr->ipaddr_ptr, inaddr_any, sar->host_addr->ipaddr_len)) {
629 ic = find_default_server(sar->host_port);
630 if (!ic || !add_name_vhost_config(p, main_s, s, sar, ic)) {
631 if (ic && ic->sar->host_port != 0) {
632 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
633 0, main_s, "_default_ VirtualHost "
634 "overlap on port %u, the first has "
635 "precedence", sar->host_port);
637 ic = new_ipaddr_chain(p, s, sar);
638 ic->next = default_list;
641 has_default_vhost_addr = 1;
644 /* see if it matches something we've already got */
645 ic = find_ipaddr(sar->host_addr);
648 unsigned bucket = hash_addr(sar->host_addr);
650 ic = new_ipaddr_chain(p, s, sar);
651 ic->next = *iphash_table_tail[bucket];
652 *iphash_table_tail[bucket] = ic;
654 else if (!add_name_vhost_config(p, main_s, s, sar, ic)) {
655 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
656 0, main_s, "VirtualHost %s:%u overlaps "
657 "with VirtualHost %s:%u, the first has "
658 "precedence, perhaps you need a "
659 "NameVirtualHost directive",
660 sar->virthost, sar->host_port,
661 ic->sar->virthost, ic->sar->host_port);
668 /* Ok now we want to set up a server_hostname if the user was
669 * silly enough to forget one.
670 * XXX: This is silly we should just crash and burn.
672 if (!s->server_hostname) {
673 if (has_default_vhost_addr) {
674 s->server_hostname = main_s->server_hostname;
676 else if (!s->addrs) {
677 /* what else can we do? at this point this vhost has
678 no configured name, probably because they used
679 DNS in the VirtualHost statement. It's disabled
680 anyhow by the host matching code. -djg */
682 apr_pstrdup(p, "bogus_host_without_forward_dns");
688 rv = apr_getnameinfo(&hostname, s->addrs->host_addr, 0);
689 if (rv == APR_SUCCESS) {
690 s->server_hostname = apr_pstrdup(p, hostname);
693 /* again, what can we do? They didn't specify a
694 ServerName, and their DNS isn't working. -djg */
697 apr_sockaddr_ip_get(&ipaddr_str, s->addrs->host_addr);
698 ap_log_error(APLOG_MARK, APLOG_ERR, rv, main_s,
699 "Failed to resolve server name "
700 "for %s (check DNS) -- or specify an explicit "
704 apr_pstrdup(p, "bogus_host_without_reverse_dns");
710 /* now go through and delete any NameVirtualHosts that didn't have any
711 * hosts associated with them. Lamers.
713 for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
714 remove_unused_name_vhosts(main_s, &iphash_table[i]);
716 remove_unused_name_vhosts(main_s, &default_list);
718 #ifdef IPHASH_STATISTICS
719 dump_iphash_statistics(main_s);
721 if (ap_exists_config_define("DUMP_VHOSTS")) {
722 apr_file_t *thefile = NULL;
723 apr_file_open_stderr(&thefile, p);
724 dump_vhost_config(thefile);
729 /*****************************************************************************
730 * run-time vhost matching functions
733 /* Lowercase and remove any trailing dot and/or :port from the hostname,
734 * and check that it is sane.
736 * In most configurations the exact syntax of the hostname isn't
737 * important so strict sanity checking isn't necessary. However, in
738 * mass hosting setups (using mod_vhost_alias or mod_rewrite) where
739 * the hostname is interpolated into the filename, we need to be sure
740 * that the interpolation doesn't expose parts of the filesystem.
741 * We don't do strict RFC 952 / RFC 1123 syntax checking in order
742 * to support iDNS and people who erroneously use underscores.
743 * Instead we just check for filesystem metacharacters: directory
744 * separators / and \ and sequences of more than one dot.
746 static void fix_hostname(request_rec *r)
748 char *host, *scope_id;
753 rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool);
754 if (rv != APR_SUCCESS || scope_id) {
759 /* silly looking host ("Host: 123") but that isn't our job
760 * here to judge; apr_parse_addr_port() would think we had a port
763 host = apr_psprintf(r->pool, "%d", (int)port);
766 /* Don't throw the Host: header's port number away:
767 save it in parsed_uri -- ap_get_server_port() needs it! */
768 /* @@@ XXX there should be a better way to pass the port.
769 * Like r->hostname, there should be a r->portno
771 r->parsed_uri.port = port;
772 r->parsed_uri.port_str = apr_psprintf(r->pool, "%d", (int)port);
775 /* if the hostname is an IPv6 numeric address string, it was validated
776 * already; otherwise, further validation is needed
778 if (r->hostname[0] != '[') {
779 for (dst = host; *dst; dst++) {
785 else if (*dst == '/' || *dst == '\\') {
789 /* strip trailing gubbins */
790 if (dst > host && dst[-1] == '.') {
798 r->status = HTTP_BAD_REQUEST;
799 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
800 "Client sent malformed Host header");
805 /* return 1 if host matches ServerName or ServerAliases */
806 static int matches_aliases(server_rec *s, const char *host)
809 apr_array_header_t *names;
811 /* match ServerName */
812 if (!strcasecmp(host, s->server_hostname)) {
816 /* search all the aliases from ServerAlias directive */
819 char **name = (char **) names->elts;
820 for (i = 0; i < names->nelts; ++i) {
821 if(!name[i]) continue;
822 if (!strcasecmp(host, name[i]))
826 names = s->wild_names;
828 char **name = (char **) names->elts;
829 for (i = 0; i < names->nelts; ++i) {
830 if(!name[i]) continue;
831 if (!ap_strcasecmp_match(host, name[i]))
839 /* Suppose a request came in on the same socket as this r, and included
840 * a header "Host: host:port", would it map to r->server? It's more
841 * than just that though. When we do the normal matches for each request
842 * we don't even bother considering Host: etc on non-namevirtualhosts,
843 * we just call it a match. But here we require the host:port to match
844 * the ServerName and/or ServerAliases.
846 AP_DECLARE(int) ap_matches_request_vhost(request_rec *r, const char *host,
850 server_addr_rec *sar;
854 /* search all the <VirtualHost> values */
855 /* XXX: If this is a NameVirtualHost then we may not be doing the Right Thing
858 * NameVirtualHost 10.1.1.1
859 * <VirtualHost 10.1.1.1>
862 * <VirtualHost 10.1.1.1>
866 * Suppose r->server is v2, and we're asked to match "10.1.1.1". We'll say
867 * "yup it's v2", when really it isn't... if a request came in for 10.1.1.1
868 * it would really go to v1.
870 for (sar = s->addrs; sar; sar = sar->next) {
871 if ((sar->host_port == 0 || port == sar->host_port)
872 && !strcasecmp(host, sar->virthost)) {
877 /* the Port has to match now, because the rest don't have ports associated
879 if (port != s->port) {
883 return matches_aliases(s, host);
887 static void check_hostalias(request_rec *r)
890 * Even if the request has a Host: header containing a port we ignore
891 * that port. We always use the physical port of the socket. There
892 * are a few reasons for this:
894 * - the default of 80 or 443 for SSL is easier to handle this way
895 * - there is less of a possibility of a security problem
896 * - it simplifies the data structure
897 * - the client may have no idea that a proxy somewhere along the way
898 * translated the request to another ip:port
899 * - except for the addresses from the VirtualHost line, none of the other
900 * names we'll match have ports associated with them
902 const char *host = r->hostname;
910 apr_sockaddr_port_get(&port, r->connection->local_addr);
912 /* Recall that the name_chain is a list of server_addr_recs, some of
913 * whose ports may not match. Also each server may appear more than
914 * once in the chain -- specifically, it will appear once for each
915 * address from its VirtualHost line which matched. We only want to
916 * do the full ServerName/ServerAlias comparisons once for each
917 * server, fortunately we know that all the VirtualHost addresses for
918 * a single server are adjacent to each other.
921 for (src = r->connection->vhost_lookup_data; src; src = src->next) {
922 server_addr_rec *sar;
924 /* We only consider addresses on the name_chain which have a matching
928 if (sar->host_port != 0 && port != sar->host_port) {
934 /* does it match the virthost from the sar? */
935 if (!strcasecmp(host, sar->virthost)) {
940 /* we've already done ServerName and ServerAlias checks for this
947 if (matches_aliases(s, host)) {
954 /* s is the first matching server, we're done */
959 static void check_serverpath(request_rec *r)
966 apr_sockaddr_port_get(&port, r->connection->local_addr);
969 * This is in conjunction with the ServerPath code in http_core, so we
970 * get the right host attached to a non- Host-sending request.
972 * See the comment in check_hostalias about how each vhost can be
973 * listed multiple times.
977 for (src = r->connection->vhost_lookup_data; src; src = src->next) {
978 /* We only consider addresses on the name_chain which have a matching
981 if (src->sar->host_port != 0 && port != src->sar->host_port) {
991 if (s->path && !strncmp(r->uri, s->path, s->pathlen) &&
992 (s->path[s->pathlen - 1] == '/' ||
993 r->uri[s->pathlen] == '/' ||
994 r->uri[s->pathlen] == '\0')) {
1002 void ap_update_vhost_from_headers(request_rec *r)
1004 /* must set this for HTTP/1.1 support */
1005 if (r->hostname || (r->hostname = apr_table_get(r->headers_in, "Host"))) {
1007 if (r->status != HTTP_OK)
1010 /* check if we tucked away a name_chain */
1011 if (r->connection->vhost_lookup_data) {
1015 check_serverpath(r);
1020 /* Called for a new connection which has a known local_addr. Note that the
1021 * new connection is assumed to have conn->server == main server.
1023 void ap_update_vhost_given_ip(conn_rec *conn)
1028 /* scan the hash apr_table_t for an exact match first */
1029 trav = find_ipaddr(conn->local_addr);
1032 /* save the name_chain for later in case this is a name-vhost */
1033 conn->vhost_lookup_data = trav->names;
1034 conn->base_server = trav->server;
1038 /* maybe there's a default server or wildcard name-based vhost
1039 * matching this port
1041 apr_sockaddr_port_get(&port, conn->local_addr);
1043 trav = find_default_server(port);
1045 conn->vhost_lookup_data = trav->names;
1046 conn->base_server = trav->server;
1050 /* otherwise we're stuck with just the main server
1051 * and no name-based vhosts
1053 conn->vhost_lookup_data = NULL;