]> granicus.if.org Git - apache/blob - server/vhost.c
Change references of AF_ to reflect APR_ so they should work
[apache] / server / vhost.c
1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000 The Apache Software Foundation.  All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
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
17  *    distribution.
18  *
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.
25  *
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.
30  *
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.
34  *
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
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
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/>.
53  *
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.
57  */
58
59 /*
60  * http_vhost.c: functions pertaining to virtual host addresses
61  *      (configuration and run-time)
62  */
63
64 #define CORE_PRIVATE
65 #include "ap_config.h"
66 #include "httpd.h"
67 #include "http_config.h"
68 #include "http_log.h"
69 #include "http_vhost.h"
70 #include "http_protocol.h"
71 #include "http_core.h"
72 #include "apr_strings.h"
73
74 #ifdef HAVE_ARPA_INET_H
75 #include <arpa/inet.h>
76 #endif
77 #ifdef HAVE_NETINET_IN_H
78 #include <netinet/in.h>
79 #endif
80 #ifdef HAVE_SYS_SOCKET_H
81 #include <sys/socket.h>
82 #endif
83 #ifdef HAVE_NETDB_H
84 #include <netdb.h>
85 #endif
86 #ifdef HAVE_STRINGS_H
87 #include <strings.h>
88 #endif
89
90 /*
91  * After all the definitions there's an explanation of how it's all put
92  * together.
93  */
94
95 /* meta-list of name-vhosts.  Each server_rec can be in possibly multiple
96  * lists of name-vhosts.
97  */
98 typedef struct name_chain name_chain;
99 struct name_chain {
100     name_chain *next;
101     server_addr_rec *sar;       /* the record causing it to be in
102                                  * this chain (needed for port comparisons) */
103     server_rec *server;         /* the server to use on a match */
104 };
105
106 /* meta-list of ip addresses.  Each server_rec can be in possibly multiple
107  * hash chains since it can have multiple ips.
108  */
109 typedef struct ipaddr_chain ipaddr_chain;
110 struct ipaddr_chain {
111     ipaddr_chain *next;
112     server_addr_rec *sar;       /* the record causing it to be in
113                                  * this chain (need for both ip addr and port
114                                  * comparisons) */
115     server_rec *server;         /* the server to use if this matches */
116     name_chain *names;          /* if non-NULL then a list of name-vhosts
117                                  * sharing this address */
118 };
119
120 /* This defines the size of the hash apr_table_t used for hashing ip addresses
121  * of virtual hosts.  It must be a power of two.
122  */
123 #ifndef IPHASH_TABLE_SIZE
124 #define IPHASH_TABLE_SIZE 256
125 #endif
126
127 /* A (n) bucket hash table, each entry has a pointer to a server rec and
128  * a pointer to the other entries in that bucket.  Each individual address,
129  * even for virtualhosts with multiple addresses, has an entry in this hash
130  * table.  There are extra buckets for _default_, and name-vhost entries.
131  *
132  * Note that after config time this is constant, so it is thread-safe.
133  */
134 static ipaddr_chain *iphash_table[IPHASH_TABLE_SIZE];
135
136 /* dump out statistics about the hash function */
137 /* #define IPHASH_STATISTICS */
138
139 /* list of the _default_ servers */
140 static ipaddr_chain *default_list;
141
142 /* list of the NameVirtualHost addresses */
143 static server_addr_rec *name_vhost_list;
144 static server_addr_rec **name_vhost_list_tail;
145
146 /*
147  * How it's used:
148  *
149  * The ip address determines which chain in iphash_table is interesting, then
150  * a comparison is done down that chain to find the first ipaddr_chain whose
151  * sar matches the address:port pair.
152  *
153  * If that ipaddr_chain has names == NULL then you're done, it's an ip-vhost.
154  *
155  * Otherwise it's a name-vhost list, and the default is the server in the
156  * ipaddr_chain record.  We tuck away the ipaddr_chain record in the
157  * conn_rec field vhost_lookup_data.  Later on after the headers we get a
158  * second chance, and we use the name_chain to figure out what name-vhost
159  * matches the headers.
160  *
161  * If there was no ip address match in the iphash_table then do a lookup
162  * in the default_list.
163  *
164  * How it's put together ... well you should be able to figure that out
165  * from how it's used.  Or something like that.
166  */
167
168
169 /* called at the beginning of the config */
170 void ap_init_vhost_config(apr_pool_t *p)
171 {
172     memset(iphash_table, 0, sizeof(iphash_table));
173     default_list = NULL;
174     name_vhost_list = NULL;
175     name_vhost_list_tail = &name_vhost_list;
176 }
177
178
179 /*
180  * Parses a host of the form <address>[:port]
181  * paddr is used to create a list in the order of input
182  * **paddr is the ->next pointer of the last entry (or s->addrs)
183  * *paddr is the variable used to keep track of **paddr between calls
184  * port is the default port to assume
185  */
186 static const char *get_addresses(apr_pool_t *p, const char *w_,
187                                  server_addr_rec ***paddr, apr_port_t port)
188 {
189     apr_in_addr_t my_addr;
190     server_addr_rec *sar;
191     char *t;
192     int i;
193     char *w;
194
195     if (*w_ == 0)
196         return NULL;
197
198     w=apr_pstrdup(p, w_);
199     t = strchr(w, ':');
200     if (t) {
201         if (strcmp(t + 1, "*") == 0) {
202             port = 0;
203         }
204         else if ((i = atoi(t + 1))) {
205             port = i;
206         }
207         else {
208             return ":port must be numeric";
209         }
210         *t = 0;
211     }
212
213     if (strcasecmp(w, "_default_") == 0
214         || strcmp(w, "255.255.255.255") == 0) {
215         my_addr.s_addr = DEFAULT_VHOST_ADDR;
216     } else {
217         if (apr_get_inaddr(&my_addr, w) != APR_SUCCESS) {
218             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, NULL,
219                 "Cannot resolve host name %s --- ignoring!", w);
220             return NULL;
221         }
222     }
223
224     sar = apr_pcalloc(p, sizeof(server_addr_rec));
225     **paddr = sar;
226     *paddr = &sar->next;
227     sar->host_addr = my_addr;
228     sar->host_port = port;
229     sar->virthost = apr_pstrdup(p, w);
230     return NULL;
231 }
232
233
234 /* parse the <VirtualHost> addresses */
235 const char *ap_parse_vhost_addrs(apr_pool_t *p, const char *hostname, server_rec *s)
236 {
237     server_addr_rec **addrs;
238     const char *err;
239
240     /* start the list of addreses */
241     addrs = &s->addrs;
242     while (hostname[0]) {
243         err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port);
244         if (err) {
245             *addrs = NULL;
246             return err;
247         }
248     }
249     /* terminate the list */
250     *addrs = NULL;
251     if (s->addrs) {
252         if (s->addrs->host_port) {
253             /* override the default port which is inherited from main_server */
254             s->port = s->addrs->host_port;
255         }
256     }
257     return NULL;
258 }
259
260
261 const char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy,
262                                       const char *arg)
263 {
264     /* use whatever port the main server has at this point */
265     return get_addresses(cmd->pool, arg, &name_vhost_list_tail,
266                             cmd->server->port);
267 }
268
269
270 /* hash apr_table_t statistics, keep this in here for the beta period so
271  * we can find out if the hash function is ok
272  */
273 #ifdef IPHASH_STATISTICS
274 static int iphash_compare(const void *a, const void *b)
275 {
276     return (*(const int *) b - *(const int *) a);
277 }
278
279
280 static void dump_iphash_statistics(server_rec *main_s)
281 {
282     unsigned count[IPHASH_TABLE_SIZE];
283     int i;
284     ipaddr_chain *src;
285     unsigned total;
286     char buf[HUGE_STRING_LEN];
287     char *p;
288
289     total = 0;
290     for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
291         count[i] = 0;
292         for (src = iphash_table[i]; src; src = src->next) {
293             ++count[i];
294             if (i < IPHASH_TABLE_SIZE) {
295                 /* don't count the slop buckets in the total */
296                 ++total;
297             }
298         }
299     }
300     qsort(count, IPHASH_TABLE_SIZE, sizeof(count[0]), iphash_compare);
301     p = buf + apr_snprintf(buf, sizeof(buf),
302                     "iphash: total hashed = %u, avg chain = %u, "
303                     "chain lengths (count x len):",
304                     total, total / IPHASH_TABLE_SIZE);
305     total = 1;
306     for (i = 1; i < IPHASH_TABLE_SIZE; ++i) {
307         if (count[i - 1] != count[i]) {
308             p += apr_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
309                              total, count[i - 1]);
310             total = 1;
311         }
312         else {
313             ++total;
314         }
315     }
316     p += apr_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
317                      total, count[IPHASH_TABLE_SIZE - 1]);
318     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, main_s, buf);
319 }
320 #endif
321
322
323 /* This hashing function is designed to get good distribution in the cases
324  * where the server is handling entire "networks" of servers.  i.e. a
325  * whack of /24s.  This is probably the most common configuration for
326  * ISPs with large virtual servers.
327  *
328  * NOTE: This function is symmetric (i.e. collapses all 4 octets
329  * into one), so machine byte order (big/little endianness) does not matter.
330  *
331  * Hash function provided by David Hankins.
332  */
333 static apr_inline unsigned hash_inaddr(unsigned key)
334 {
335     key ^= (key >> 16);
336     return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE;
337 }
338
339
340
341 static ipaddr_chain *new_ipaddr_chain(apr_pool_t *p,
342                                     server_rec *s, server_addr_rec *sar)
343 {
344     ipaddr_chain *new;
345
346     new = apr_palloc(p, sizeof(*new));
347     new->names = NULL;
348     new->server = s;
349     new->sar = sar;
350     new->next = NULL;
351     return new;
352 }
353
354
355 static name_chain *new_name_chain(apr_pool_t *p, server_rec *s, server_addr_rec *sar)
356 {
357     name_chain *new;
358
359     new = apr_palloc(p, sizeof(*new));
360     new->server = s;
361     new->sar = sar;
362     new->next = NULL;
363     return new;
364 }
365
366
367 static apr_inline ipaddr_chain *find_ipaddr(apr_in_addr_t *server_ip,
368     apr_port_t port)
369 {
370     unsigned bucket;
371     ipaddr_chain *trav;
372     unsigned addr;
373
374     /* scan the hash apr_table_t for an exact match first */
375     addr = server_ip->s_addr;
376     bucket = hash_inaddr(addr);
377     for (trav = iphash_table[bucket]; trav; trav = trav->next) {
378         server_addr_rec *sar = trav->sar;
379         if ((sar->host_addr.s_addr == addr)
380             && (sar->host_port == 0 || sar->host_port == port
381                 || port == 0)) {
382             return trav;
383         }
384     }
385     return NULL;
386 }
387
388
389 static ipaddr_chain *find_default_server(apr_port_t port)
390 {
391     server_addr_rec *sar;
392     ipaddr_chain *trav;
393
394     for (trav = default_list; trav; trav = trav->next) {
395         sar = trav->sar;
396         if (sar->host_port == 0 || sar->host_port == port) {
397             /* match! */
398             return trav;
399         }
400     }
401     return NULL;
402 }
403
404 static void dump_a_vhost(apr_file_t *f, ipaddr_chain *ic)
405 {
406     name_chain *nc;
407     int len;
408     char buf[MAX_STRING_LEN];
409
410     if (ic->sar->host_addr.s_addr == DEFAULT_VHOST_ADDR) {
411         len = apr_snprintf(buf, sizeof(buf), "_default_:%u",
412                 ic->sar->host_port);
413     }
414     else if (ic->sar->host_addr.s_addr == INADDR_ANY) {
415         len = apr_snprintf(buf, sizeof(buf), "*:%u",
416                 ic->sar->host_port);
417     }
418     else {
419         len = apr_snprintf(buf, sizeof(buf), "%pA:%u",
420                 &ic->sar->host_addr, ic->sar->host_port);
421     }
422     if (ic->sar->host_port == 0) {
423         buf[len-1] = '*';
424     }
425     if (ic->names == NULL) {
426         apr_fprintf(f, "%-22s %s (%s:%u)\n", buf, ic->server->server_hostname,
427                 ic->server->defn_name, ic->server->defn_line_number);
428         return;
429     }
430     apr_fprintf(f, "%-22s is a NameVirtualHost\n"
431             "%22s default server %s (%s:%u)\n",
432             buf, "", ic->server->server_hostname,
433             ic->server->defn_name, ic->server->defn_line_number);
434     for (nc = ic->names; nc; nc = nc->next) {
435         if (nc->sar->host_port) {
436             apr_fprintf(f, "%22s port %u ", "", nc->sar->host_port);
437         }
438         else {
439             apr_fprintf(f, "%22s port * ", "");
440         }
441         apr_fprintf(f, "namevhost %s (%s:%u)\n", nc->server->server_hostname,
442                 nc->server->defn_name, nc->server->defn_line_number);
443     }
444 }
445
446 static void dump_vhost_config(apr_file_t *f)
447 {
448     ipaddr_chain *ic;
449     int i;
450
451     apr_fprintf(f, "VirtualHost configuration:\n");
452     for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
453         for (ic = iphash_table[i]; ic; ic = ic->next) {
454             dump_a_vhost(f, ic);
455         }
456     }
457     if (default_list) {
458         apr_fprintf(f, "wildcard NameVirtualHosts and _default_ servers:\n");
459         for (ic = default_list; ic; ic = ic->next) {
460             dump_a_vhost(f, ic);
461         }
462     }
463 }
464
465 /*
466  * Two helper functions for ap_fini_vhost_config()
467  */
468 static int add_name_vhost_config(apr_pool_t *p, server_rec *main_s, server_rec *s,
469                                  server_addr_rec *sar, ipaddr_chain *ic)
470 {
471     /* the first time we encounter a NameVirtualHost address
472      * ic->server will be NULL, on subsequent encounters
473      * ic->names will be non-NULL.
474      */
475     if (ic->names || ic->server == NULL) {
476         name_chain *nc = new_name_chain(p, s, sar);
477         nc->next = ic->names;
478         ic->names = nc;
479         ic->server = s;
480         if (sar->host_port != ic->sar->host_port) {
481             /* one of the two is a * port, the other isn't */
482             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, main_s,
483                     "VirtualHost %s:%u -- mixing * "
484                     "ports and non-* ports with "
485                     "a NameVirtualHost address is not supported,"
486                     " proceeding with undefined results",
487                     sar->virthost, sar->host_port);
488         }
489         return 1;
490     }
491     else {
492         /* IP-based vhosts are handled by the caller */
493         return 0;
494     }
495 }
496
497 static void remove_unused_name_vhosts(server_rec *main_s, ipaddr_chain **pic)
498 {
499     while (*pic) {
500         ipaddr_chain *ic = *pic;
501         
502         if (ic->server == NULL) {
503             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, main_s,
504                          "NameVirtualHost %s:%u has no VirtualHosts",
505                          ic->sar->virthost, ic->sar->host_port);
506             *pic = ic->next;
507         }
508         else if (ic->names == NULL) {
509             /* if server != NULL and names == NULL then we're done
510              * looking at NameVirtualHosts
511              */
512             break;
513         }
514         else {
515             pic = &ic->next;
516         }
517     }
518 }
519
520 /* compile the tables and such we need to do the run-time vhost lookups */
521 void ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s)
522 {
523     server_addr_rec *sar;
524     int has_default_vhost_addr;
525     server_rec *s;
526     int i;
527     ipaddr_chain **iphash_table_tail[IPHASH_TABLE_SIZE];
528
529     /* terminate the name_vhost list */
530     *name_vhost_list_tail = NULL;
531
532     /* Main host first */
533     s = main_s;
534
535     if (!s->server_hostname) {
536         s->server_hostname = ap_get_local_host(p);
537     }
538
539     /* initialize the tails */
540     for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
541         iphash_table_tail[i] = &iphash_table[i];
542     }
543
544     /* The first things to go into the hash apr_table_t are the NameVirtualHosts
545      * Since name_vhost_list is in the same order that the directives
546      * occured in the config file, we'll copy it in that order.
547      */
548     for (sar = name_vhost_list; sar; sar = sar->next) {
549         unsigned bucket = hash_inaddr(sar->host_addr.s_addr);
550         ipaddr_chain *ic = new_ipaddr_chain(p, NULL, sar);
551
552         if (sar->host_addr.s_addr != INADDR_ANY) {
553             *iphash_table_tail[bucket] = ic;
554             iphash_table_tail[bucket] = &ic->next;
555         }
556         else {
557             /* A wildcard NameVirtualHost goes on the default_list so
558              * that it can catch incoming requests on any address.
559              */
560             ic->next = default_list;
561             default_list = ic;
562         }
563         /* Notice that what we've done is insert an ipaddr_chain with
564          * both server and names NULL. This fact is used to spot name-
565          * based vhosts in add_name_vhost_config().
566          */
567     }
568
569     /* The next things to go into the hash apr_table_t are the virtual hosts
570      * themselves.  They're listed off of main_s->next in the reverse
571      * order they occured in the config file, so we insert them at
572      * the iphash_table_tail but don't advance the tail.
573      */
574
575     for (s = main_s->next; s; s = s->next) {
576         has_default_vhost_addr = 0;
577         for (sar = s->addrs; sar; sar = sar->next) {
578             ipaddr_chain *ic;
579
580             if (sar->host_addr.s_addr == DEFAULT_VHOST_ADDR
581                 || sar->host_addr.s_addr == INADDR_ANY) {
582                 ic = find_default_server(sar->host_port);
583                 if (!ic || !add_name_vhost_config(p, main_s, s, sar, ic)) {
584                     if (ic && ic->sar->host_port != 0) {
585                         ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
586                             0, main_s, "_default_ VirtualHost overlap on port %u,"
587                             " the first has precedence", sar->host_port);
588                     }
589                     ic = new_ipaddr_chain(p, s, sar);
590                     ic->next = default_list;
591                     default_list = ic;
592                 }
593                 has_default_vhost_addr = 1;
594             }
595             else {
596                 /* see if it matches something we've already got */
597                 ic = find_ipaddr(&sar->host_addr, sar->host_port);
598
599                 if (!ic) {
600                     unsigned bucket = hash_inaddr(sar->host_addr.s_addr);
601
602                     ic = new_ipaddr_chain(p, s, sar);
603                     ic->next = *iphash_table_tail[bucket];
604                     *iphash_table_tail[bucket] = ic;
605                 }
606                 else if (!add_name_vhost_config(p, main_s, s, sar, ic)) {
607                     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, main_s,
608                             "VirtualHost %s:%u overlaps with "
609                             "VirtualHost %s:%u, the first has precedence, "
610                             "perhaps you need a NameVirtualHost directive",
611                             sar->virthost, sar->host_port,
612                             ic->sar->virthost, ic->sar->host_port);
613                     ic->sar = sar;
614                     ic->server = s;
615                 }
616             }
617         }
618
619         /* Ok now we want to set up a server_hostname if the user was
620          * silly enough to forget one.
621          * XXX: This is silly we should just crash and burn.
622          */
623         if (!s->server_hostname) {
624             if (has_default_vhost_addr) {
625                 s->server_hostname = main_s->server_hostname;
626             }
627             else if (!s->addrs) {
628                 /* what else can we do?  at this point this vhost has
629                     no configured name, probably because they used
630                     DNS in the VirtualHost statement.  It's disabled
631                     anyhow by the host matching code.  -djg */
632                 s->server_hostname =
633                     apr_pstrdup(p, "bogus_host_without_forward_dns");
634             }
635             else {
636                 struct hostent *h;
637
638                 if ((h = gethostbyaddr((char *) &(s->addrs->host_addr),
639                                         sizeof(struct in_addr), APR_INET))) {
640                     s->server_hostname = apr_pstrdup(p, (char *) h->h_name);
641                 }
642                 else {
643                     /* again, what can we do?  They didn't specify a
644                        ServerName, and their DNS isn't working. -djg */
645                     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, main_s,
646                             "Failed to resolve server name "
647                             "for %s (check DNS) -- or specify an explicit "
648                             "ServerName",
649                             inet_ntoa(s->addrs->host_addr));
650                     s->server_hostname =
651                         apr_pstrdup(p, "bogus_host_without_reverse_dns");
652                 }
653             }
654         }
655     }
656
657     /* now go through and delete any NameVirtualHosts that didn't have any
658      * hosts associated with them.  Lamers.
659      */
660     for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
661         remove_unused_name_vhosts(main_s, &iphash_table[i]);
662     }
663     remove_unused_name_vhosts(main_s, &default_list);
664
665 #ifdef IPHASH_STATISTICS
666     dump_iphash_statistics(main_s);
667 #endif
668     if (getenv("DUMP_VHOSTS")) {
669         apr_file_t *thefile = NULL;
670         apr_open_stderr(&thefile, p);
671         dump_vhost_config(thefile);
672     }
673 }
674
675
676 /*****************************************************************************
677  * run-time vhost matching functions
678  */
679
680 /* Lowercase and remove any trailing dot and/or :port from the hostname,
681  * and check that it is sane.
682  *
683  * In most configurations the exact syntax of the hostname isn't
684  * important so strict sanity checking isn't necessary. However, in
685  * mass hosting setups (using mod_vhost_alias or mod_rewrite) where
686  * the hostname is interpolated into the filename, we need to be sure
687  * that the interpolation doesn't expose parts of the filesystem.
688  * We don't do strict RFC 952 / RFC 1123 syntax checking in order
689  * to support iDNS and people who erroneously use underscores.
690  * Instead we just check for filesystem metacharacters: directory
691  * separators / and \ and sequences of more than one dot.
692  */
693 static void fix_hostname(request_rec *r)
694 {
695     char *host = apr_palloc(r->pool, strlen(r->hostname) + 1);
696     const char *src;
697     char *dst;
698
699     /* check and copy the host part */
700     src = r->hostname;
701     dst = host;
702     while (*src) {
703         if (!apr_isalnum(*src) && *src != '-') {
704             if (*src == '.') {
705                 *dst++ = *src++;
706                 if (*src == '.')
707                     goto bad;
708                 else
709                     continue;
710             }
711             if (*src == ':')
712                 break;
713             else
714                 goto bad;
715         } else {
716             *dst++ = *src++;
717         }
718     }
719     /* check the port part */
720     if (*src++ == ':') {
721         while (*src) {
722             if (!apr_isdigit(*src++)) {
723                 goto bad;
724             }
725         }
726     }
727     /* strip trailing gubbins */
728     if (dst > host && dst[-1] == '.') {
729         dst[-1] = '\0';
730     } else {
731         dst[0] = '\0';
732     }
733
734     r->hostname = host;
735     return;
736
737 bad:
738     r->status = HTTP_BAD_REQUEST;
739     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
740                   "Client sent malformed Host header");
741     return;
742 }
743
744
745 /* return 1 if host matches ServerName or ServerAliases */
746 static int matches_aliases(server_rec *s, const char *host)
747 {
748     int i;
749     apr_array_header_t *names;
750
751     /* match ServerName */
752     if (!strcasecmp(host, s->server_hostname)) {
753         return 1;
754     }
755
756     /* search all the aliases from ServerAlias directive */
757     names = s->names;
758     if (names) {
759         char **name = (char **) names->elts;
760         for (i = 0; i < names->nelts; ++i) {
761             if(!name[i]) continue;
762             if (!strcasecmp(host, name[i]))
763                 return 1;
764         }
765     }
766     names = s->wild_names;
767     if (names) {
768         char **name = (char **) names->elts;
769         for (i = 0; i < names->nelts; ++i) {
770             if(!name[i]) continue;
771             if (!ap_strcasecmp_match(host, name[i]))
772                 return 1;
773         }
774     }
775     return 0;
776 }
777
778
779 /* Suppose a request came in on the same socket as this r, and included
780  * a header "Host: host:port", would it map to r->server?  It's more
781  * than just that though.  When we do the normal matches for each request
782  * we don't even bother considering Host: etc on non-namevirtualhosts,
783  * we just call it a match.  But here we require the host:port to match
784  * the ServerName and/or ServerAliases.
785  */
786 AP_DECLARE(int) ap_matches_request_vhost(request_rec *r, const char *host,
787     apr_port_t port)
788 {
789     server_rec *s;
790     server_addr_rec *sar;
791
792     s = r->server;
793
794     /* search all the <VirtualHost> values */
795     /* XXX: If this is a NameVirtualHost then we may not be doing the Right Thing
796      * consider: 
797      *
798      *     NameVirtualHost 10.1.1.1
799      *     <VirtualHost 10.1.1.1>
800      *     ServerName v1
801      *     </VirtualHost>
802      *     <VirtualHost 10.1.1.1>
803      *     ServerName v2
804      *     </VirtualHost>
805      *
806      * Suppose r->server is v2, and we're asked to match "10.1.1.1".  We'll say
807      * "yup it's v2", when really it isn't... if a request came in for 10.1.1.1
808      * it would really go to v1.
809      */
810     for (sar = s->addrs; sar; sar = sar->next) {
811         if ((sar->host_port == 0 || port == sar->host_port)
812             && !strcasecmp(host, sar->virthost)) {
813             return 1;
814         }
815     }
816
817     /* the Port has to match now, because the rest don't have ports associated
818      * with them. */
819     if (port != s->port) {
820         return 0;
821     }
822
823     return matches_aliases(s, host);
824 }
825
826
827 static void check_hostalias(request_rec *r)
828 {
829     /*
830      * Even if the request has a Host: header containing a port we ignore
831      * that port.  We always use the physical port of the socket.  There
832      * are a few reasons for this:
833      *
834      * - the default of 80 or 443 for SSL is easier to handle this way
835      * - there is less of a possibility of a security problem
836      * - it simplifies the data structure
837      * - the client may have no idea that a proxy somewhere along the way
838      *   translated the request to another ip:port
839      * - except for the addresses from the VirtualHost line, none of the other
840      *   names we'll match have ports associated with them
841      */
842     const char *host = r->hostname;
843     apr_port_t port;
844     server_rec *s;
845     server_rec *last_s;
846     name_chain *src;
847
848     last_s = NULL;
849     apr_get_port(&port, APR_LOCAL, r->connection->client_socket);
850
851     /* Recall that the name_chain is a list of server_addr_recs, some of
852      * whose ports may not match.  Also each server may appear more than
853      * once in the chain -- specifically, it will appear once for each
854      * address from its VirtualHost line which matched.  We only want to
855      * do the full ServerName/ServerAlias comparisons once for each
856      * server, fortunately we know that all the VirtualHost addresses for
857      * a single server are adjacent to each other.
858      */
859
860     for (src = r->connection->vhost_lookup_data; src; src = src->next) {
861         server_addr_rec *sar;
862
863         /* We only consider addresses on the name_chain which have a matching
864          * port
865          */
866         sar = src->sar;
867         if (sar->host_port != 0 && port != sar->host_port) {
868             continue;
869         }
870
871         s = src->server;
872
873         /* does it match the virthost from the sar? */
874         if (!strcasecmp(host, sar->virthost)) {
875             goto found;
876         }
877
878         if (s == last_s) {
879             /* we've already done ServerName and ServerAlias checks for this
880              * vhost
881              */
882             continue;
883         }
884         last_s = s;
885
886         if (matches_aliases(s, host)) {
887             goto found;
888         }
889     }
890     return;
891
892 found:
893     /* s is the first matching server, we're done */
894     r->server = s;
895 }
896
897
898 static void check_serverpath(request_rec *r)
899 {
900     server_rec *s;
901     server_rec *last_s;
902     name_chain *src;
903     apr_port_t port;
904     apr_get_port(&port, APR_LOCAL, r->connection->client_socket);
905    
906     /*
907      * This is in conjunction with the ServerPath code in http_core, so we
908      * get the right host attached to a non- Host-sending request.
909      *
910      * See the comment in check_hostalias about how each vhost can be
911      * listed multiple times.
912      */
913
914     last_s = NULL;
915     for (src = r->connection->vhost_lookup_data; src; src = src->next) {
916         /* We only consider addresses on the name_chain which have a matching
917          * port
918          */
919         if (src->sar->host_port != 0 && port != src->sar->host_port) {
920             continue;
921         }
922
923         s = src->server;
924         if (s == last_s) {
925             continue;
926         }
927         last_s = s;
928
929         if (s->path && !strncmp(r->uri, s->path, s->pathlen) &&
930             (s->path[s->pathlen - 1] == '/' ||
931              r->uri[s->pathlen] == '/' ||
932              r->uri[s->pathlen] == '\0')) {
933             r->server = s;
934             return;
935         }
936     }
937 }
938
939
940 void ap_update_vhost_from_headers(request_rec *r)
941 {
942     /* must set this for HTTP/1.1 support */
943     if (r->hostname || (r->hostname = apr_table_get(r->headers_in, "Host"))) {
944         fix_hostname(r);
945         if (r->status != HTTP_OK)
946             return;
947     }
948     /* check if we tucked away a name_chain */
949     if (r->connection->vhost_lookup_data) {
950         if (r->hostname)
951             check_hostalias(r);
952         else
953             check_serverpath(r);
954     }
955 }
956
957
958 /* Called for a new connection which has a known local_addr.  Note that the
959  * new connection is assumed to have conn->server == main server.
960  */
961 void ap_update_vhost_given_ip(conn_rec *conn)
962 {
963     ipaddr_chain *trav;
964     apr_port_t port;
965     apr_get_port(&port, APR_LOCAL, conn->client_socket);
966
967     /* scan the hash apr_table_t for an exact match first */
968     trav = find_ipaddr(&conn->local_addr.sin_addr, port);
969     if (trav) {
970         /* save the name_chain for later in case this is a name-vhost */
971         conn->vhost_lookup_data = trav->names;
972         conn->base_server = trav->server;
973         return;
974     }
975
976     /* maybe there's a default server or wildcard name-based vhost
977      * matching this port
978      */
979     trav = find_default_server(port);
980     if (trav) {
981         conn->vhost_lookup_data = trav->names;
982         conn->base_server = trav->server;
983         return;
984     }
985
986     /* otherwise we're stuck with just the main server
987      * and no name-based vhosts
988      */
989     conn->vhost_lookup_data = NULL;
990 }