diff options
Diffstat (limited to 'server/vhost.c')
-rw-r--r-- | server/vhost.c | 199 |
1 files changed, 61 insertions, 138 deletions
diff --git a/server/vhost.c b/server/vhost.c index e6d4229a19..02e24405bf 100644 --- a/server/vhost.c +++ b/server/vhost.c @@ -69,6 +69,8 @@ struct ipaddr_chain { server_rec *server; /* the server to use if this matches */ name_chain *names; /* if non-NULL then a list of name-vhosts * sharing this address */ + name_chain *initialnames; /* no runtime use, temporary storage of first + * NVH'es names */ }; /* This defines the size of the hash table used for hashing ip addresses @@ -93,10 +95,6 @@ static ipaddr_chain *iphash_table[IPHASH_TABLE_SIZE]; /* list of the _default_ servers */ static ipaddr_chain *default_list; -/* list of the NameVirtualHost addresses */ -static server_addr_rec *name_vhost_list; -static server_addr_rec **name_vhost_list_tail; - /* whether a config error was seen */ static int config_error = 0; @@ -132,8 +130,6 @@ AP_DECLARE(void) ap_init_vhost_config(apr_pool_t *p) { memset(iphash_table, 0, sizeof(iphash_table)); default_list = NULL; - name_vhost_list = NULL; - name_vhost_list_tail = &name_vhost_list; ap_hook_check_config(vhost_check_config, NULL, NULL, APR_HOOK_MIDDLE); } @@ -190,21 +186,13 @@ static const char *get_addresses(apr_pool_t *p, const char *w_, port = default_port; } - if (strcmp(host, "*") == 0) { + if (strcmp(host, "*") == 0 || strcasecmp(host, "_default_") == 0) { rv = apr_sockaddr_info_get(&my_addr, "0.0.0.0", APR_INET, port, 0, p); if (rv) { return "Could not resolve address '0.0.0.0' -- " "check resolver configuration."; } } - else if (strcasecmp(host, "_default_") == 0 - || strcmp(host, "255.255.255.255") == 0) { - rv = apr_sockaddr_info_get(&my_addr, "255.255.255.255", APR_INET, port, 0, p); - if (rv) { - return "Could not resolve address '255.255.255.255' -- " - "check resolver configuration."; - } - } else { rv = apr_sockaddr_info_get(&my_addr, host, APR_UNSPEC, port, 0, p); if (rv != APR_SUCCESS) { @@ -263,14 +251,16 @@ AP_DECLARE_NONSTD(const char *)ap_set_name_virtual_host(cmd_parms *cmd, void *dummy, const char *arg) { - if (0 == strcasecmp(arg, "_default_") - || 0 == strncasecmp(arg, "_default_:", 10)) { - return "_default_ is not allowed in NameVirtualHost directive"; + static int warnonce = 0; + if (++warnonce == 1) { + ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_STARTUP, APR_SUCCESS, NULL, + "NameVirtualHost has no effect and will be removed in the " + "next release %s:%d", + cmd->directive->filename, + cmd->directive->line_num); } - /* use whatever port the main server has at this point */ - return get_addresses(cmd->pool, arg, &name_vhost_list_tail, - cmd->server->port); + return NULL; } @@ -362,6 +352,7 @@ static ipaddr_chain *new_ipaddr_chain(apr_pool_t *p, new = apr_palloc(p, sizeof(*new)); new->names = NULL; + new->initialnames = NULL; new->server = s; new->sar = sar; new->next = NULL; @@ -425,11 +416,6 @@ static void dump_a_vhost(apr_file_t *f, ipaddr_chain *ic) apr_sockaddr_t *ha = ic->sar->host_addr; if (ha->family == APR_INET && - ha->sa.sin.sin_addr.s_addr == DEFAULT_VHOST_ADDR) { - len = apr_snprintf(buf, sizeof(buf), "_default_:%u", - ic->sar->host_port); - } - else if (ha->family == APR_INET && ha->sa.sin.sin_addr.s_addr == INADDR_ANY) { len = apr_snprintf(buf, sizeof(buf), "*:%u", ic->sar->host_port); @@ -489,70 +475,57 @@ static void dump_vhost_config(apr_file_t *f) int i; apr_file_printf(f, "VirtualHost configuration:\n"); + + /* non-wildcard servers */ for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { for (ic = iphash_table[i]; ic; ic = ic->next) { dump_a_vhost(f, ic); } } - if (default_list) { - apr_file_printf(f, "wildcard NameVirtualHosts and _default_ servers:\n"); - for (ic = default_list; ic; ic = ic->next) { - dump_a_vhost(f, ic); - } + + /* wildcard servers */ + for (ic = default_list; ic; ic = ic->next) { + dump_a_vhost(f, ic); } } + /* - * Two helper functions for ap_fini_vhost_config() + * When a second or later virtual host maps to the same IP chain, + * add the relevant server names to the chain. Special care is taken + * to avoid adding ic->names until we're sure there are multiple VH'es. */ -static int add_name_vhost_config(apr_pool_t *p, server_rec *main_s, +static void 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_ERR, 0, main_s, - "VirtualHost %s:%u -- mixing * " - "ports and non-* ports with " - "a NameVirtualHost address is not supported", - sar->virthost, sar->host_port); - config_error = 1; - } - 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_ERR, 0, main_s, - "Either NameVirtualHost %s:%u has no VirtualHosts," - " or there is more than one identical NameVirtualHost line," - " or your VirtualHost declarations do not match the NameVirtualHost line", - ic->sar->virthost, ic->sar->host_port); - config_error = 1; - *pic = ic->next; - } - else { - pic = &ic->next; - } - } + name_chain *nc = new_name_chain(p, s, sar); + nc->next = ic->names; + + /* iterating backwards, so each one we see becomes the current default server */ + ic->server = s; + + if (ic->names == NULL) { + if (ic->initialnames == NULL) { + /* first pass, set these names aside in case we see another VH. + * Until then, this looks like an IP-based VH to runtime. + */ + ic->initialnames = nc; + } + else { + /* second pass through this chain -- this really is an NVH, and we + * have two sets of names to link in. + */ + nc->next = ic->initialnames; + ic->names = nc; + ic->initialnames = NULL; + } + } + else { + /* 3rd or more -- just keep stacking the names */ + ic->names = nc; + } } /* compile the tables and such we need to do the run-time vhost lookups */ @@ -564,9 +537,6 @@ AP_DECLARE(void) ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s) int i; ipaddr_chain **iphash_table_tail[IPHASH_TABLE_SIZE]; - /* terminate the name_vhost list */ - *name_vhost_list_tail = NULL; - /* Main host first */ s = main_s; @@ -579,33 +549,6 @@ AP_DECLARE(void) ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s) iphash_table_tail[i] = &iphash_table[i]; } - /* The first things to go into the hash table are the NameVirtualHosts - * Since name_vhost_list is in the same order that the directives - * occured in the config file, we'll copy it in that order. - */ - for (sar = name_vhost_list; sar; sar = sar->next) { - char inaddr_any[16] = {0}; /* big enough to handle IPv4 or IPv6 */ - unsigned bucket = hash_addr(sar->host_addr); - ipaddr_chain *ic = new_ipaddr_chain(p, NULL, sar); - - if (memcmp(sar->host_addr->ipaddr_ptr, inaddr_any, - sar->host_addr->ipaddr_len)) { /* not IN[6]ADDR_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. This fact is used to spot name- - * based vhosts in add_name_vhost_config(). - */ - } - /* The next things to go into the hash table are the virtual hosts * themselves. They're listed off of main_s->next in the reverse * order they occured in the config file, so we insert them at @@ -618,17 +561,13 @@ AP_DECLARE(void) ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s) ipaddr_chain *ic; char inaddr_any[16] = {0}; /* big enough to handle IPv4 or IPv6 */ - if ((sar->host_addr->family == AF_INET && - sar->host_addr->sa.sin.sin_addr.s_addr == DEFAULT_VHOST_ADDR) - || !memcmp(sar->host_addr->ipaddr_ptr, inaddr_any, sar->host_addr->ipaddr_len)) { + if (!memcmp(sar->host_addr->ipaddr_ptr, inaddr_any, sar->host_addr->ipaddr_len)) { 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_ERR, - 0, main_s, "_default_ VirtualHost " - "overlap on port %u", sar->host_port); - config_error = 1; - } + if (!ic || sar->host_port != ic->sar->host_port) { + /* No default server, or we found a default server but + ** exactly one of us is a wildcard port, which means we want + ** two ip-based vhosts not an NVH with two names + */ ic = new_ipaddr_chain(p, s, sar); ic->next = default_list; default_list = ic; @@ -639,26 +578,18 @@ AP_DECLARE(void) ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s) /* see if it matches something we've already got */ ic = find_ipaddr(sar->host_addr); - if (!ic) { + if (!ic || sar->host_port != ic->sar->host_port) { + /* No matching server, or we found a matching server but + ** exactly one of us is a wildcard port, which means we want + ** two ip-based vhosts not an NVH with two names + */ unsigned bucket = hash_addr(sar->host_addr); - ic = new_ipaddr_chain(p, s, sar); ic->next = *iphash_table_tail[bucket]; *iphash_table_tail[bucket] = ic; } - else if (!add_name_vhost_config(p, main_s, s, sar, ic)) { - ap_log_error(APLOG_MARK, APLOG_ERR, - 0, main_s, "VirtualHost %s:%u overlaps " - "with VirtualHost %s:%u, the first has " - "precedence, perhaps you need a " - "NameVirtualHost directive", - sar->virthost, sar->host_port, - ic->sar->virthost, ic->sar->host_port); - config_error = 1; - ic->sar = sar; - ic->server = s; - } } + add_name_vhost_config(p, main_s, s, sar, ic); } /* Ok now we want to set up a server_hostname if the user was @@ -703,14 +634,6 @@ AP_DECLARE(void) ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s) } } - /* now go through and delete any NameVirtualHosts that didn't have any - * hosts associated with them. Lamers. - */ - for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { - 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); #endif |