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