From: Yann Ylavic Date: Thu, 15 Feb 2018 17:27:31 +0000 (+0000) Subject: Merge r1667707, r1824332 from trunk: X-Git-Tag: 2.4.30~49 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fd2e91e8570f628e50fde630b962215ce47362a2;p=apache Merge r1667707, r1824332 from trunk: * mod_proxy: Allow setting options to globally defined balancer from ProxyPass used in VirtualHost. Balancers are now merged using the new merge_balancers method which merges the balancers options. mod_proxy: follow up to r1667707: MMN minor bump. Submitted by: jkaluza, ylavic Reviewed by: icing, jim, ylavic git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1824333 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 964e5f5e41..03b2456423 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,10 @@ -*- coding: utf-8 -*- Changes with Apache 2.4.30 + *) mod_proxy: Allow setting options to globally defined balancer from + ProxyPass used in VirtualHost. Balancers are now merged using the new + merge_balancers method which merges the balancers options. [Jan Kaluza] + *) logresolve: Fix incorrect behavior or segfault if -c flag is used Fixes: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=823259 [Stefan Fritsch] diff --git a/include/ap_mmn.h b/include/ap_mmn.h index da093a0f1b..70b9c621bc 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -505,6 +505,8 @@ * and optional ssl_engine_set() to mod_ssl.h. * 20120211.72 (2.4.30-dev) Add NOT_IN_DIR_CONTEXT replacing NOT_IN_DIR_LOC_FILE * semantics + * 20120211.73 (2.4.30-dev) Add failontimeout_set, growth_set and lbmethod_set + * to proxy_balancer struct */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ @@ -512,7 +514,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20120211 #endif -#define MODULE_MAGIC_NUMBER_MINOR 72 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 73 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c index 544611299a..009b375eae 100644 --- a/modules/proxy/mod_proxy.c +++ b/modules/proxy/mod_proxy.c @@ -365,6 +365,7 @@ static const char *set_balancer_param(proxy_server_conf *conf, } else balancer->s->sticky_separator = *val; + balancer->s->sticky_separator_set = 1; } else if (!strcasecmp(key, "nofailover")) { /* If set to 'on' the session will break @@ -377,6 +378,7 @@ static const char *set_balancer_param(proxy_server_conf *conf, balancer->s->sticky_force = 0; else return "failover must be On|Off"; + balancer->s->sticky_force_set = 1; } else if (!strcasecmp(key, "timeout")) { /* Balancer timeout in seconds. @@ -407,6 +409,7 @@ static const char *set_balancer_param(proxy_server_conf *conf, if (provider) { balancer->lbmethod = provider; if (PROXY_STRNCPY(balancer->s->lbpname, val) == APR_SUCCESS) { + balancer->lbmethod_set = 1; return NULL; } else { @@ -426,6 +429,7 @@ static const char *set_balancer_param(proxy_server_conf *conf, balancer->s->scolonsep = 0; else return "scolonpathdelim must be On|Off"; + balancer->s->scolonsep_set = 1; } else if (!strcasecmp(key, "failonstatus")) { char *val_split; @@ -456,6 +460,7 @@ static const char *set_balancer_param(proxy_server_conf *conf, balancer->failontimeout = 0; else return "failontimeout must be On|Off"; + balancer->failontimeout_set = 1; } else if (!strcasecmp(key, "nonce")) { if (!strcasecmp(val, "None")) { @@ -466,12 +471,14 @@ static const char *set_balancer_param(proxy_server_conf *conf, return "Provided nonce is too large"; } } + balancer->s->nonce_set = 1; } else if (!strcasecmp(key, "growth")) { ival = atoi(val); if (ival < 1 || ival > 100) /* arbitrary limit here */ return "growth must be between 1 and 100"; balancer->growth = ival; + balancer->growth_set = 1; } else if (!strcasecmp(key, "forcerecovery")) { if (!strcasecmp(val, "on")) @@ -480,6 +487,7 @@ static const char *set_balancer_param(proxy_server_conf *conf, balancer->s->forcerecovery = 0; else return "forcerecovery must be On|Off"; + balancer->s->forcerecovery_set = 1; } else { return "unknown Balancer parameter"; @@ -1360,6 +1368,99 @@ static void * create_proxy_config(apr_pool_t *p, server_rec *s) return ps; } +static apr_array_header_t *merge_balancers(apr_pool_t *p, + apr_array_header_t *base, + apr_array_header_t *overrides) +{ + proxy_balancer *b1; + proxy_balancer *b2; + proxy_balancer tmp; + int x, y, found; + apr_array_header_t *tocopy = apr_array_make(p, 1, sizeof(proxy_balancer)); + + /* Check if the balancer is defined in both override and base configs: + * a) If it is, Create copy of base balancer and change the configuration + * which can be changed by ProxyPass. + * b) Otherwise, copy the balancer to tocopy array and merge it later. + */ + b1 = (proxy_balancer *) base->elts; + for (y = 0; y < base->nelts; y++) { + b2 = (proxy_balancer *) overrides->elts; + for (x = 0, found = 0; x < overrides->nelts; x++) { + if (b1->hash.def == b2->hash.def && b1->hash.fnv == b2->hash.fnv) { + tmp = *b2; + *b2 = *b1; + b2->s = tmp.s; + + /* For shared memory entries, b2->s belongs to override + * balancer, so if some entry is not set there, we have to + * update it according to the base balancer. */ + if (*b2->s->sticky == 0 && *b1->s->sticky) { + PROXY_STRNCPY(b2->s->sticky_path, b1->s->sticky_path); + PROXY_STRNCPY(b2->s->sticky, b1->s->sticky); + } + if (!b2->s->sticky_separator_set + && b1->s->sticky_separator_set) { + b2->s->sticky_separator_set = b1->s->sticky_separator_set; + b2->s->sticky_separator = b1->s->sticky_separator; + } + if (!b2->s->timeout && b1->s->timeout) { + b2->s->timeout = b1->s->timeout; + } + if (!b2->s->max_attempts_set && b1->s->max_attempts_set) { + b2->s->max_attempts_set = b1->s->max_attempts_set; + b2->s->max_attempts = b1->s->max_attempts; + } + if (!b2->s->nonce_set && b1->s->nonce_set) { + b2->s->nonce_set = b1->s->nonce_set; + PROXY_STRNCPY(b2->s->nonce, b1->s->nonce); + } + if (!b2->s->sticky_force_set && b1->s->sticky_force_set) { + b2->s->sticky_force_set = b1->s->sticky_force_set; + b2->s->sticky_force = b1->s->sticky_force; + } + if (!b2->s->scolonsep_set && b1->s->scolonsep_set) { + b2->s->scolonsep_set = b1->s->scolonsep_set; + b2->s->scolonsep = b1->s->scolonsep; + } + if (!b2->s->forcerecovery_set && b1->s->forcerecovery_set) { + b2->s->forcerecovery_set = b1->s->forcerecovery_set; + b2->s->forcerecovery = b1->s->forcerecovery; + } + + /* For non-shared memory entries, b2 is copy of b1, so we have + * to use tmp copy of b1 to detect changes done in override. */ + if (tmp.lbmethod_set) { + b2->lbmethod_set = tmp.lbmethod_set; + b2->lbmethod = tmp.lbmethod; + } + if (tmp.growth_set) { + b2->growth_set = tmp.growth_set; + b2->growth = tmp.growth; + } + if (tmp.failontimeout_set) { + b2->failontimeout_set = tmp.failontimeout_set; + b2->failontimeout = tmp.failontimeout; + } + if (!apr_is_empty_array(tmp.errstatuses)) { + apr_array_cat(tmp.errstatuses, b2->errstatuses); + b2->errstatuses = tmp.errstatuses; + } + + found = 1; + break; + } + b2++; + } + if (!found) { + *(proxy_balancer *)apr_array_push(tocopy) = *b1; + } + b1++; + } + + return apr_array_append(p, tocopy, overrides); +} + static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv) { proxy_server_conf *ps = apr_pcalloc(p, sizeof(proxy_server_conf)); @@ -1384,7 +1485,7 @@ static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv) ps->dirconn = apr_array_append(p, base->dirconn, overrides->dirconn); if (ps->inherit || ps->ppinherit) { ps->workers = apr_array_append(p, base->workers, overrides->workers); - ps->balancers = apr_array_append(p, base->balancers, overrides->balancers); + ps->balancers = merge_balancers(p, base->balancers, overrides->balancers); } else { ps->workers = overrides->workers; diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index 1708c5c4f2..7542fdc5ec 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -494,6 +494,11 @@ typedef struct { unsigned int inactive:1; unsigned int forcerecovery:1; char sticky_separator; /* separator for sessionid/route */ + unsigned int forcerecovery_set:1; + unsigned int scolonsep_set:1; + unsigned int sticky_force_set:1; + unsigned int nonce_set:1; + unsigned int sticky_separator_set:1; } proxy_balancer_shared; #define ALIGNED_PROXY_BALANCER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_balancer_shared))) @@ -514,6 +519,9 @@ struct proxy_balancer { void *context; /* general purpose storage */ proxy_balancer_shared *s; /* Shared data */ int failontimeout; /* Whether to mark a member in Err if IO timeout occurs */ + unsigned int failontimeout_set:1; + unsigned int growth_set:1; + unsigned int lbmethod_set:1; ap_conf_vector_t *section_config; /* -section wherein defined */ };