]> granicus.if.org Git - apache/commitdiff
This commit adds support for purely name-based virtual hosting that
authorTony Finch <fanf@apache.org>
Tue, 12 Sep 2000 17:46:40 +0000 (17:46 +0000)
committerTony Finch <fanf@apache.org>
Tue, 12 Sep 2000 17:46:40 +0000 (17:46 +0000)
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 *
        <VirtualHost *>
                ServerName my.friend.has.a.silly.vanitydomain.org
                DocumentRoot /usr/local/apache/docs1
        </VirtualHost>
        <VirtualHost *>
                ServerName but.easier.to.spell.than.my.vanitydomain.org
                DocumentRoot /usr/local/apache/docs2
        </VirtualHost>

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

server/vhost.c

index f083f6414a11bb6f430dd6f80f20226ec27a2de1..054f6accdff8490a10d7ecd7b6acbb1d9d106e53 100644 (file)
@@ -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;
 }