From: Tony Finch Date: Tue, 12 Sep 2000 17:46:40 +0000 (+0000) Subject: This commit adds support for purely name-based virtual hosting that X-Git-Tag: APACHE_2_0_ALPHA_7~173 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=32bcfc4d9d623a32dddc1dcefd814b062d254640;p=apache This commit adds support for purely name-based virtual hosting that does not require any IP addresses in httpd.conf and which disregards the local IP address of any connections. This will be particularly appreciated by people running little servers on machines with dynamically configured IP addresses, and by people wishing to use identical httpd.conf files on all the machines in a load-balanced cluster. The syntax is: NameVirtualHost * ServerName my.friend.has.a.silly.vanitydomain.org DocumentRoot /usr/local/apache/docs1 ServerName but.easier.to.spell.than.my.vanitydomain.org DocumentRoot /usr/local/apache/docs2 The implementation is a straightforward extension of what is there already although the patch is made somewhat larger by the need to avoid duplicate code for normal and wildcarded NameVirtualHosts. PR: 5595, 4455 [ported from 1.3.13] git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86208 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/server/vhost.c b/server/vhost.c index f083f6414a..054f6accdf 100644 --- a/server/vhost.c +++ b/server/vhost.c @@ -425,59 +425,118 @@ static ipaddr_chain *find_default_server(unsigned port) return NULL; } -static void dump_vhost_config(apr_file_t *f) +static void dump_a_vhost(apr_file_t *f, ipaddr_chain *ic) { - int i; - ipaddr_chain *ic; name_chain *nc; + int len; char buf[MAX_STRING_LEN]; + if (ic->sar->host_addr.s_addr == DEFAULT_VHOST_ADDR) { + len = apr_snprintf(buf, sizeof(buf), "_default_:%u", + ic->sar->host_port); + } + else if (ic->sar->host_addr.s_addr == INADDR_ANY) { + len = apr_snprintf(buf, sizeof(buf), "*:%u", + ic->sar->host_port); + } + else { + len = apr_snprintf(buf, sizeof(buf), "%pA:%u", + &ic->sar->host_addr, ic->sar->host_port); + } + if (ic->sar->host_port == 0) { + buf[len-1] = '*'; + } + if (ic->names == NULL) { + apr_fprintf(f, "%-22s %s (%s:%u)\n", buf, ic->server->server_hostname, + ic->server->defn_name, ic->server->defn_line_number); + return; + } + apr_fprintf(f, "%-22s is a NameVirtualHost\n" + "%22s default server %s (%s:%u)\n", + buf, "", ic->server->server_hostname, + ic->server->defn_name, ic->server->defn_line_number); + for (nc = ic->names; nc; nc = nc->next) { + if (nc->sar->host_port) { + apr_fprintf(f, "%22s port %u ", "", nc->sar->host_port); + } + else { + apr_fprintf(f, "%22s port * ", ""); + } + apr_fprintf(f, "namevhost %s (%s:%u)\n", nc->server->server_hostname, + nc->server->defn_name, nc->server->defn_line_number); + } +} + +static void dump_vhost_config(apr_file_t *f) +{ + ipaddr_chain *ic; + int i; + apr_fprintf(f, "VirtualHost configuration:\n"); for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { for (ic = iphash_table[i]; ic; ic = ic->next) { - if (ic->sar->host_port == 0) { - apr_snprintf(buf, sizeof(buf), "%pA:*", &ic->sar->host_addr); - } - else { - apr_snprintf(buf, sizeof(buf), "%pA:%u", &ic->sar->host_addr, - ic->sar->host_port); - } - if (ic->names == NULL) { - apr_fprintf(f, "%-22s %s (%s:%u)\n", buf, - ic->server->server_hostname, ic->server->defn_name, - ic->server->defn_line_number); - continue; - } - apr_fprintf(f, "%-22s is a NameVirtualHost\n" - "%22s default server %s (%s:%u)\n", - buf, "", ic->server->server_hostname, - ic->server->defn_name, ic->server->defn_line_number); - for (nc = ic->names; nc; nc = nc->next) { - if (nc->sar->host_port) { - apr_fprintf(f, "%22s port %u ", "", nc->sar->host_port); - } - else { - apr_fprintf(f, "%22s port * ", ""); - } - apr_fprintf(f, "namevhost %s (%s:%u)\n", - nc->server->server_hostname, - nc->server->defn_name, - nc->server->defn_line_number); - } + dump_a_vhost(f, ic); } } if (default_list) { - apr_fprintf(f, "_default_ servers:\n"); + apr_fprintf(f, "wildcard NameVirtualHosts and _default_ servers:\n"); for (ic = default_list; ic; ic = ic->next) { - if (ic->sar->host_port == 0) { - apr_fprintf(f, "port * "); - } - else { - apr_fprintf(f, "port %u ", ic->sar->host_port); - } - apr_fprintf(f, "server %s (%s:%u)\n", - ic->server->server_hostname, ic->server->defn_name, - ic->server->defn_line_number); + dump_a_vhost(f, ic); + } + } +} + +/* + * Two helper functions for ap_fini_vhost_config() + */ +static int add_name_vhost_config(apr_pool_t *p, server_rec *main_s, server_rec *s, + server_addr_rec *sar, ipaddr_chain *ic) +{ + /* the first time we encounter a NameVirtualHost address + * ic->server will be NULL, on subsequent encounters + * ic->names will be non-NULL. + */ + if (ic->names || ic->server == NULL) { + name_chain *nc = new_name_chain(p, s, sar); + nc->next = ic->names; + ic->names = nc; + ic->server = s; + if (sar->host_port != ic->sar->host_port) { + /* one of the two is a * port, the other isn't */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, main_s, + "VirtualHost %s:%u -- mixing * " + "ports and non-* ports with " + "a NameVirtualHost address is not supported," + " proceeding with undefined results", + sar->virthost, sar->host_port); + } + return 1; + } + else { + /* IP-based vhosts are handled by the caller */ + return 0; + } +} + +static void remove_unused_name_vhosts(server_rec *main_s, ipaddr_chain **pic) +{ + while (*pic) { + ipaddr_chain *ic = *pic; + + if (ic->server == NULL) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, main_s, + "NameVirtualHost %s:%u has no VirtualHosts", + ic->sar->virthost, ic->sar->host_port); + *pic = ic->next; + } + else if (ic->names == NULL) { + /* if server != NULL and names == NULL then we're done + * looking at NameVirtualHosts + */ + break; + } + else { + pic = &ic->next; } } } @@ -512,13 +571,22 @@ void ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s) */ for (sar = name_vhost_list; sar; sar = sar->next) { unsigned bucket = hash_inaddr(sar->host_addr.s_addr); - ipaddr_chain *new = new_ipaddr_chain(p, NULL, sar); - - *iphash_table_tail[bucket] = new; - iphash_table_tail[bucket] = &new->next; + ipaddr_chain *ic = new_ipaddr_chain(p, NULL, sar); + if (sar->host_addr.s_addr != INADDR_ANY) { + *iphash_table_tail[bucket] = ic; + iphash_table_tail[bucket] = &ic->next; + } + else { + /* A wildcard NameVirtualHost goes on the default_list so + * that it can catch incoming requests on any address. + */ + ic->next = default_list; + default_list = ic; + } /* Notice that what we've done is insert an ipaddr_chain with - * both server and names NULL. Remember that. + * both server and names NULL. This fact is used to spot name- + * based vhosts in add_name_vhost_config(). */ } @@ -535,46 +603,31 @@ void ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s) if (sar->host_addr.s_addr == DEFAULT_VHOST_ADDR || sar->host_addr.s_addr == INADDR_ANY) { - /* add it to default bucket for each appropriate sar - * since we need to do a port test - */ - ipaddr_chain *other; - - other = find_default_server(sar->host_port); - if (other && other->sar->host_port != 0) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, main_s, - "_default_ VirtualHost overlap on port %u," + ic = find_default_server(sar->host_port); + if (!ic || !add_name_vhost_config(p, main_s, s, sar, ic)) { + if (ic && ic->sar->host_port != 0) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, + 0, main_s, "_default_ VirtualHost overlap on port %u," " the first has precedence", sar->host_port); + } + ic = new_ipaddr_chain(p, s, sar); + ic->next = default_list; + default_list = ic; } has_default_vhost_addr = 1; - ic = new_ipaddr_chain(p, s, sar); - ic->next = default_list; - default_list = ic; } else { /* see if it matches something we've already got */ ic = find_ipaddr(&sar->host_addr, sar->host_port); - /* the first time we encounter a NameVirtualHost address - * ic->server will be NULL, on subsequent encounters - * ic->names will be non-NULL. - */ - if (ic && (ic->names || ic->server == NULL)) { - name_chain *nc = new_name_chain(p, s, sar); - nc->next = ic->names; - ic->names = nc; - ic->server = s; - if (sar->host_port != ic->sar->host_port) { - /* one of the two is a * port, the other isn't */ - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, main_s, - "VirtualHost %s:%u -- mixing * " - "ports and non-* ports with " - "a NameVirtualHost address is not supported," - " proceeding with undefined results", - sar->virthost, sar->host_port); - } + if (!ic) { + unsigned bucket = hash_inaddr(sar->host_addr.s_addr); + + ic = new_ipaddr_chain(p, s, sar); + ic->next = *iphash_table_tail[bucket]; + *iphash_table_tail[bucket] = ic; } - else if (ic) { + else if (!add_name_vhost_config(p, main_s, s, sar, ic)) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, main_s, "VirtualHost %s:%u overlaps with " "VirtualHost %s:%u, the first has precedence, " @@ -584,13 +637,6 @@ void ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s) ic->sar = sar; ic->server = s; } - else { - unsigned bucket = hash_inaddr(sar->host_addr.s_addr); - - ic = new_ipaddr_chain(p, s, sar); - ic->next = *iphash_table_tail[bucket]; - *iphash_table_tail[bucket] = ic; - } } } @@ -636,28 +682,9 @@ void ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s) * hosts associated with them. Lamers. */ for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { - ipaddr_chain **pic = &iphash_table[i]; - - while (*pic) { - ipaddr_chain *ic = *pic; - - if (ic->server == NULL) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, main_s, - "NameVirtualHost %s:%u has no VirtualHosts", - ic->sar->virthost, ic->sar->host_port); - *pic = ic->next; - } - else if (ic->names == NULL) { - /* if server != NULL and names == NULL then we're done - * looking at NameVirtualHosts - */ - break; - } - else { - pic = &ic->next; - } - } + remove_unused_name_vhosts(main_s, &iphash_table[i]); } + remove_unused_name_vhosts(main_s, &default_list); #ifdef IPHASH_STATISTICS dump_iphash_statistics(main_s); @@ -951,16 +978,18 @@ void ap_update_vhost_given_ip(conn_rec *conn) return; } - /* There's certainly no name-vhosts with this address, they would have - * been matched above. + /* maybe there's a default server or wildcard name-based vhost + * matching this port */ - conn->vhost_lookup_data = NULL; - - /* maybe there's a default server matching this port */ trav = find_default_server(port); if (trav) { + conn->vhost_lookup_data = trav->names; conn->base_server = trav->server; + return; } - /* otherwise we're stuck with just the main server */ + /* otherwise we're stuck with just the main server + * and no name-based vhosts + */ + conn->vhost_lookup_data = NULL; }