/* Licensed to the Apache Software Foundation (ASF) under one or more *contributorlicenseagreements.SeetheNOTICEfiledistributedwith *thisworkforadditionalinformationregardingcopyrightownership. *TheASFlicensesthisfiletoYouundertheApacheLicense,Version2.0 *(the"License");youmaynotusethisfileexceptincompliancewith *theLicense.YoumayobtainacopyoftheLicenseat * *http://www.apache.org/licenses/LICENSE-2.0 * *Unlessrequiredbyapplicablelaworagreedtoinwriting,software *distributedundertheLicenseisdistributedonan"ASIS"BASIS, *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. *SeetheLicenseforthespecificlanguagegoverningpermissionsand *limitationsundertheLicense.
*/
/* meta-list of name-vhosts. Each server_rec can be in possibly multiple *listsofname-vhosts.
*/ typedefstruct name_chain name_chain; struct name_chain {
name_chain *next;
server_addr_rec *sar; /* the record causing it to be in
* this chain (needed for port comparisons) */
server_rec *server; /* the server to use on a match */
};
/* meta-list of ip addresses. Each server_rec can be in possibly multiple *hashchainssinceitcanhavemultipleips.
*/ typedefstruct ipaddr_chain ipaddr_chain; struct ipaddr_chain {
ipaddr_chain *next;
server_addr_rec *sar; /* the record causing it to be in *thischain(needforbothipaddrandport
* comparisons) */
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 *ofvirtualhosts.Itmustbeapoweroftwo.
*/ #ifndef IPHASH_TABLE_SIZE #define IPHASH_TABLE_SIZE 256 #endif
/* A (n) bucket hash table, each entry has a pointer to a server rec and *apointertotheotherentriesinthatbucket.Eachindividualaddress, *evenforvirtualhostswithmultipleaddresses,hasanentryinthishash *table.Thereareextrabucketsfor_default_,andname-vhostentries. * *Notethatafterconfigtimethisisconstant,soitisthread-safe.
*/ static ipaddr_chain *iphash_table[IPHASH_TABLE_SIZE];
/* dump out statistics about the hash function */ /* #define IPHASH_STATISTICS */
/* list of the _default_ servers */ static ipaddr_chain *default_list;
/* whether a config error was seen */ staticint config_error = 0;
/* called at the beginning of the config */
AP_DECLARE(void) ap_init_vhost_config(apr_pool_t *p)
{
memset(iphash_table, 0, sizeof(iphash_table));
default_list = NULL;
ap_hook_check_config(vhost_check_config, NULL, NULL, APR_HOOK_MIDDLE);
}
wlen = strlen(w_); /* wlen must be > 0 at this point */
w = apr_pstrmemdup(p, w_, wlen); /* apr_parse_addr_port() doesn't understand ":*" so handle that first. */
wild_port = 0; if (w[wlen - 1] == '*') { if (wlen < 2) {
wild_port = 1;
} elseif (w[wlen - 2] == ':') {
w[wlen - 2] = '\0';
wild_port = 1;
}
}
rv = apr_parse_addr_port(&host, &scope_id, &port, w, p); /* If the string is "80", apr_parse_addr_port() will be happy and set *hosttoNULLandportto80,sowatchoutforthat.
*/ if (rv != APR_SUCCESS) { return"The address or port is invalid";
} if (!host) { return"Missing address for VirtualHost";
} #if !APR_VERSION_AT_LEAST(1,7,0) if (scope_id) { return apr_pstrcat(p, "Scope ID in address '", w, "' not supported with APR " APR_VERSION_STRING,
NULL);
} #endif if (!port && !wild_port) {
port = default_port;
}
if (strcmp(host, "*") == 0 || strcasecmp(host, "_default_") == 0) {
rv = apr_sockaddr_info_get(&my_addr, NULL, APR_UNSPEC, port, 0, p); if (rv) { return"Could not determine a wildcard address ('0.0.0.0') -- " "check resolver configuration.";
}
} else {
rv = apr_sockaddr_info_get(&my_addr, host, APR_UNSPEC, port, 0, p); if (rv != APR_SUCCESS) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, APLOGNO(00547) "Could not resolve host name %s -- ignoring!", host); return NULL;
} #if APR_VERSION_AT_LEAST(1,7,0) if (scope_id) {
rv = apr_sockaddr_zone_set(my_addr, scope_id); if (rv) {
ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, APLOGNO(10103) "Could not set scope ID %s for %pI -- ignoring!",
scope_id, my_addr); return NULL;
}
} #endif
}
/* Remember all addresses for the host */
do {
sar = apr_pcalloc(p, sizeof(server_addr_rec));
**paddr = sar;
*paddr = &sar->next;
sar->host_addr = my_addr;
sar->host_port = port;
sar->virthost = host;
my_addr = my_addr->next;
} while (my_addr);
/* start the list of addresses */
addrs = &s->addrs; while (hostname[0]) {
err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port); if (err) {
*addrs = NULL; return err;
}
} /* terminate the list */
*addrs = NULL; if (s->addrs) { if (s->addrs->host_port) { /* override the default port which is inherited from main_server */
s->port = s->addrs->host_port;
}
} return NULL;
}
AP_DECLARE_NONSTD(constchar *)ap_set_name_virtual_host(cmd_parms *cmd, void *dummy, constchar *arg)
{ staticint warnonce = 0; if (++warnonce == 1) {
ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_STARTUP, APR_SUCCESS, NULL, APLOGNO(00548) "NameVirtualHost has no effect and will be removed in the " "next release %s:%d",
cmd->directive->filename,
cmd->directive->line_num);
}
return NULL;
}
/* hash table statistics, keep this in here for the beta period so *wecanfindoutifthehashfunctionisok
*/ #ifdef IPHASH_STATISTICS staticint iphash_compare(constvoid *a, constvoid *b)
{ return (*(constint *) b - *(constint *) a);
}
total = 0; for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
count[i] = 0; for (src = iphash_table[i]; src; src = src->next) {
++count[i]; if (i < IPHASH_TABLE_SIZE) { /* don't count the slop buckets in the total */
++total;
}
}
}
qsort(count, IPHASH_TABLE_SIZE, sizeof(count[0]), iphash_compare);
p = buf + apr_snprintf(buf, sizeof(buf),
APLOGNO(03235) "iphash: total hashed = %u, avg chain = %u, " "chain lengths (count x len):",
total, total / IPHASH_TABLE_SIZE);
total = 1; for (i = 1; i < IPHASH_TABLE_SIZE; ++i) { if (count[i - 1] != count[i]) {
p += apr_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
total, count[i - 1]);
total = 1;
} else {
++total;
}
}
p += apr_snprintf(p, sizeof(buf) - (p - buf), " %ux%u",
total, count[IPHASH_TABLE_SIZE - 1]); /* Intentional no APLOGNO */ /* buf provides APLOGNO */
ap_log_error(APLOG_MARK, APLOG_DEBUG, main_s, buf);
} #endif
/* This hashing function is designed to get good distribution in the cases *wheretheserverishandlingentire"networks"ofservers.i.e.a *whackof/24s.Thisisprobablythemostcommonconfigurationfor *ISPswithlargevirtualservers. * *NOTE:Thisfunctionissymmetric(i.e.collapsesall4octets *intoone),somachinebyteorder(big/littleendianness)doesnotmatter. * *HashfunctionprovidedbyDavidHankins.
*/ static APR_INLINE unsigned hash_inaddr(unsigned key)
{
key ^= (key >> 16); return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE;
}
/* The key is the last four bytes of the IP address. *ForIPv4,thisistheentireaddress,asalways. *ForIPv6,thisisusuallypartoftheMACaddress.
*/
key = *(unsigned *)((char *)sa->ipaddr_ptr + sa->ipaddr_len - 4); return hash_inaddr(key);
}
/* 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. *Untilthen,thislookslikeanIP-basedVHtoruntime.
*/
ic->initialnames = nc;
} else { /* second pass through this chain -- this really is an NVH, and we *havetwosetsofnamestolinkin.
*/
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 */
AP_DECLARE(void) ap_fini_vhost_config(apr_pool_t *p, server_rec *main_s)
{
server_addr_rec *sar; int has_default_vhost_addr;
server_rec *s; int i;
ipaddr_chain **iphash_table_tail[IPHASH_TABLE_SIZE];
/* Main host first */
s = main_s;
if (!s->server_hostname) {
s->server_hostname = ap_get_local_host(p);
}
/* initialize the tails */ for (i = 0; i < IPHASH_TABLE_SIZE; ++i) {
iphash_table_tail[i] = &iphash_table[i];
}
/* The next things to go into the hash table are the virtual hosts *themselves.They'relistedoffofmain_s->nextinthereverse *ordertheyoccurredintheconfigfile,soweinsertthemat *theiphash_table_tailbutdon'tadvancethetail.
*/
for (s = main_s->next; s; s = s->next) {
server_addr_rec *sar_prev = NULL;
has_default_vhost_addr = 0; for (sar = s->addrs; sar; sar = sar->next) {
ipaddr_chain *ic; char inaddr_any[16] = {0}; /* big enough to handle IPv4 or IPv6 */ /* XXX: this treats 0.0.0.0 as a "default" server which matches no-exact-match for IPv6 */ if (!memcmp(sar->host_addr->ipaddr_ptr, inaddr_any, sar->host_addr->ipaddr_len)) {
ic = find_default_server(sar->host_port);
if (ic && sar->host_port == ic->sar->host_port) { /* we're a match for an existing "default server" */ if (!sar_prev || memcmp(sar_prev->host_addr->ipaddr_ptr, inaddr_any, sar_prev->host_addr->ipaddr_len)
|| sar_prev->host_port != sar->host_port) {
add_name_vhost_config(p, main_s, s, sar, ic);
}
} else { /* No default server, or we found a default server but **exactlyoneofusisawildcardport,whichmeanswewant **twoip-basedvhostsnotanNVHwithtwonames
*/
ic = new_ipaddr_chain(p, s, sar);
ic->next = default_list;
default_list = ic;
add_name_vhost_config(p, main_s, s, sar, ic);
}
has_default_vhost_addr = 1;
} else { /* see if it matches something we've already got */
ic = find_ipaddr(sar->host_addr);
if (!ic || sar->host_port != ic->sar->host_port) { /* No matching server, or we found a matching server but **exactlyoneofusisawildcardport,whichmeanswewant **twoip-basedvhostsnotanNVHwithtwonames
*/ 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;
}
add_name_vhost_config(p, main_s, s, sar, ic);
}
sar_prev = sar;
}
/* Ok now we want to set up a server_hostname if the user was *sillyenoughtoforgetone. *XXX:Thisissillyweshouldjustcrashandburn.
*/ if (!s->server_hostname) { if (has_default_vhost_addr) {
s->server_hostname = main_s->server_hostname;
} elseif (!s->addrs) { /* what else can we do? at this point this vhost has noconfiguredname,probablybecausetheyused DNSintheVirtualHoststatement.It'sdisabled
anyhow by the host matching code. -djg */
s->server_hostname =
apr_pstrdup(p, "bogus_host_without_forward_dns");
} else {
apr_status_t rv; char *hostname;
rv = apr_getnameinfo(&hostname, s->addrs->host_addr, 0); if (rv == APR_SUCCESS) {
s->server_hostname = apr_pstrdup(p, hostname);
} else { /* again, what can we do? They didn't specify a
ServerName, and their DNS isn't working. -djg */ char *ipaddr_str;
apr_sockaddr_ip_get(&ipaddr_str, s->addrs->host_addr);
ap_log_error(APLOG_MARK, APLOG_ERR, rv, main_s, APLOGNO(00549) "Failed to resolve server name " "for %s (check DNS) -- or specify an explicit " "ServerName",
ipaddr_str);
s->server_hostname =
apr_pstrdup(p, "bogus_host_without_reverse_dns");
}
}
}
}
/* Lowercase and remove any trailing dot and/or :port from the hostname, *andcheckthatitissane. * *Inmostconfigurationstheexactsyntaxofthehostnameisn't *importantsostrictsanitycheckingisn'tnecessary.However,in *masshostingsetups(usingmod_vhost_aliasormod_rewrite)where *thehostnameisinterpolatedintothefilename,weneedtobesure *thattheinterpolationdoesn'texposepartsofthefilesystem. *Wedon'tdostrictRFC952/RFC1123syntaxcheckinginorder *tosupportiDNSandpeoplewhoerroneouslyuseunderscores. *Insteadwejustcheckforfilesystemmetacharacters:directory *separators/and\andsequencesofmorethanonedot.
*/ staticint fix_hostname(request_rec *r, constchar *host_header, unsigned http_conformance)
{ constchar *src; char *host, *scope_id;
apr_port_t port;
apr_status_t rv; constchar *c; int is_v6literal = 0; int strict = (http_conformance != AP_HTTP_CONFORMANCE_UNSAFE);
src = host_header ? host_header : r->hostname;
/* According to RFC 2616, Host header field CAN be blank */ if (!*src) { return is_v6literal;
}
/* apr_parse_addr_port will interpret a bare integer as a port *whichisincorrectinthiscontext.Sotreatitseparately.
*/ for (c = src; apr_isdigit(*c); ++c); if (!*c) { /* pure integer */ if (strict) { /* RFC 3986 7.4 */
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02416) "[strict] purely numeric host names not allowed: %s",
src); goto bad_nolog;
}
r->hostname = src; return is_v6literal;
}
if (host_header) {
rv = apr_parse_addr_port(&host, &scope_id, &port, src, r->pool); if (rv != APR_SUCCESS || scope_id) goto bad; if (port) { /* Don't throw the Host: header's port number away:
save it in parsed_uri -- ap_get_server_port() needs it! */ /* @@@ XXX there should be a better way to pass the port. *Liker->hostname,thereshouldbear->portno
*/
r->parsed_uri.port = port;
r->parsed_uri.port_str = apr_itoa(r->pool, (int)port);
} if (host_header[0] == '[')
is_v6literal = 1;
} else { /* *Alreadyparsed,surrounding[](ifIPv6literal)and:porthave *alreadybeenremoved.
*/
host = apr_pstrdup(r->pool, r->hostname); if (ap_strchr(host, ':') != NULL)
is_v6literal = 1;
}
/* return 1 if host matches ServerName or ServerAliases */ staticint matches_aliases(server_rec *s, constchar *host)
{ int i;
apr_array_header_t *names;
/* match ServerName */ if (!strcasecmp(host, s->server_hostname)) { return1;
}
/* search all the aliases from ServerAlias directive */
names = s->names; if (names) { char **name = (char **) names->elts; for (i = 0; i < names->nelts; ++i) { if (!name[i]) continue; if (!strcasecmp(host, name[i])) return1;
}
}
names = s->wild_names; if (names) { char **name = (char **) names->elts; for (i = 0; i < names->nelts; ++i) { if (!name[i]) continue; if (!ap_strcasecmp_match(host, name[i])) return1;
}
} return0;
}
/* Suppose a request came in on the same socket as this r, and included *aheader"Host:host:port",woulditmaptor->server?It'smore *thanjustthatthough.Whenwedothenormalmatchesforeachrequest *wedon'tevenbotherconsideringHost:etconnon-namevirtualhosts, *wejustcallitamatch.Butherewerequirethehost:porttomatch *theServerNameand/orServerAliases.
*/
AP_DECLARE(int) ap_matches_request_vhost(request_rec *r, constchar *host,
apr_port_t port)
{
server_rec *s;
server_addr_rec *sar;
s = r->server;
/* search all the <VirtualHost> values */ /* XXX: If this is a NameVirtualHost then we may not be doing the Right Thing *consider: * *NameVirtualHost10.1.1.1 *<VirtualHost10.1.1.1> *ServerNamev1 *</VirtualHost> *<VirtualHost10.1.1.1> *ServerNamev2 *</VirtualHost> * *Supposer->serverisv2,andwe'reaskedtomatch"10.1.1.1".We'llsay *"yupit'sv2",whenreallyitisn't...ifarequestcameinfor10.1.1.1 *itwouldreallygotov1.
*/ for (sar = s->addrs; sar; sar = sar->next) { if ((sar->host_port == 0 || port == sar->host_port)
&& !strcasecmp(host, sar->virthost)) { return1;
}
}
/* the Port has to match now, because the rest don't have ports associated
* with them. */ if (port != s->port) { return0;
}
/* Recall that the name_chain is a list of server_addr_recs, some of *whoseportsmaynotmatch.Alsoeachservermayappearmorethan *onceinthechain--specifically,itwillappearonceforeach *addressfromitsVirtualHostlinewhichmatched.Weonlywantto *dothefullServerName/ServerAliascomparisonsonceforeach *server,fortunatelyweknowthatalltheVirtualHostaddressesfor *asingleserverareadjacenttoeachother.
*/
/* We only consider addresses on the name_chain which have a matching *port
*/
sar = src->sar; if (sar->host_port != 0 && port != sar->host_port) { continue;
}
s = src->server;
/* If we still need to do ServerName and ServerAlias checks for this *server,dothemnow.
*/ if (s != last_s) { /* does it match any ServerName or ServerAlias directive? */ if (matches_aliases(s, host)) { goto found;
}
}
/* Fallback: does it match the virthost from the sar? */ if (!strcasecmp(host, sar->virthost)) { /* only the first match is used */ if (virthost_s == NULL) {
virthost_s = s;
}
}
last_s = s;
}
/* If ServerName and ServerAlias check failed, we end up here. If it *matchesaVirtualHost,virthost_sisset.Usethatasfallback
*/ if (virthost_s) {
s = virthost_s; goto found;
}
if (!r->connection->vhost_lookup_data) { if (matches_aliases(r->server, host)) {
s = r->server; goto found;
}
} return HTTP_BAD_REQUEST;
found: /* s is the first matching server, we're done */
r->server = s; return HTTP_OK;
}
last_s = NULL; for (src = r->connection->vhost_lookup_data; src; src = src->next) { /* We only consider addresses on the name_chain which have a matching *port
*/ if (src->sar->host_port != 0 && port != src->sar->host_port) { continue;
}
s = src->server; if (s == last_s) { continue;
}
last_s = s;
if (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE) { /* *IfwehavebothhostnamefromanabsoluteURIandaHostheader, *wemustignoretheHostheader(RFC26165.2). *Toenforcethis,weresettheHostheadertothevaluefromthe *requestline.
*/ if (have_hostname_from_url && host_header != NULL) { constchar *repl = construct_host_header(r, is_v6literal);
apr_table_setn(r->headers_in, "Host", repl);
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02417) "Replacing host header '%s' with host '%s' given " "in the request uri", host_header, repl);
}
}
/* check if we tucked away a name_chain */ if (r->connection->vhost_lookup_data) { if (r->hostname)
rc = update_server_from_aliases(r); else
check_serverpath(r);
} elseif (require_match && r->hostname) { /* check the base server config */
rc = update_server_from_aliases(r);
}
/* We only consider addresses on the name_chain which have a *matchingport.
*/
sar = src->sar; if (sar->host_port != 0 && port != sar->host_port) { continue;
}
s = src->server;
if (s == last_s) { /* we've already done a callback for this vhost. */ continue;
}
/* Called for a new connection which has a known local_addr. Note that the *newconnectionisassumedtohaveconn->server==mainserver.
*/
AP_DECLARE(void) ap_update_vhost_given_ip(conn_rec *conn)
{
ipaddr_chain *trav;
apr_port_t port;
/* scan the hash table for an exact match first */
trav = find_ipaddr(conn->local_addr);
if (trav) { /* save the name_chain for later in case this is a name-vhost */
conn->vhost_lookup_data = trav->names;
conn->base_server = trav->server; return;
}
/* maybe there's a default server or wildcard name-based vhost *matchingthisport
*/
port = conn->local_addr->port;
/* otherwise we're stuck with just the main server *andnoname-basedvhosts
*/
conn->vhost_lookup_data = NULL;
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.38Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.