|
version 1.1.1.1, 2013/10/14 10:32:47
|
version 1.1.1.2, 2016/11/02 10:35:00
|
|
Line 1
|
Line 1
|
| |
#include "first.h" |
| |
|
| #include "base.h" |
#include "base.h" |
| #include "buffer.h" |
#include "buffer.h" |
| #include "array.h" |
#include "array.h" |
|
Line 8
|
Line 10
|
| |
|
| #include <string.h> |
#include <string.h> |
| #include <stdlib.h> |
#include <stdlib.h> |
| |
#ifndef _WIN32 |
| |
#include <arpa/inet.h> |
| |
#endif |
| |
|
| /** |
/** |
| * like all glue code this file contains functions which |
* like all glue code this file contains functions which |
|
Line 24
|
Line 29
|
| /* handle global options */ |
/* handle global options */ |
| |
|
| /* parse config array */ |
/* parse config array */ |
| int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) { | int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[], config_scope_type_t scope) { |
| size_t i; |
size_t i; |
| data_unset *du; |
data_unset *du; |
| |
|
|
Line 36 int config_insert_values_internal(server *srv, array *
|
Line 41 int config_insert_values_internal(server *srv, array *
|
| continue; |
continue; |
| } |
} |
| |
|
| |
if ((T_CONFIG_SCOPE_SERVER == cv[i].scope) |
| |
&& (T_CONFIG_SCOPE_SERVER != scope)) { |
| |
/* server scope options should only be set in server scope, not in conditionals */ |
| |
log_error_write(srv, __FILE__, __LINE__, "ss", |
| |
"DEPRECATED: don't set server options in conditionals, variable:", |
| |
cv[i].key); |
| |
} |
| |
|
| switch (cv[i].type) { |
switch (cv[i].type) { |
| case T_CONFIG_ARRAY: |
case T_CONFIG_ARRAY: |
| if (du->type == TYPE_ARRAY) { |
if (du->type == TYPE_ARRAY) { |
|
Line 43 int config_insert_values_internal(server *srv, array *
|
Line 56 int config_insert_values_internal(server *srv, array *
|
| data_array *da = (data_array *)du; |
data_array *da = (data_array *)du; |
| |
|
| for (j = 0; j < da->value->used; j++) { |
for (j = 0; j < da->value->used; j++) { |
| if (da->value->data[j]->type == TYPE_STRING) { | data_unset *ds = da->value->data[j]; |
| data_string *ds = data_string_init(); | if (ds->type == TYPE_STRING) { |
| array_insert_unique(cv[i].destination, ds->copy(ds)); |
| buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value); | |
| if (!da->is_index_key) { | |
| /* the id's were generated automaticly, as we copy now we might have to renumber them | |
| * this is used to prepend server.modules by mod_indexfile as it has to be loaded | |
| * before mod_fastcgi and friends */ | |
| buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key); | |
| } | |
| |
| array_insert_unique(cv[i].destination, (data_unset *)ds); | |
| } else { |
} else { |
| log_error_write(srv, __FILE__, __LINE__, "sssd", | log_error_write(srv, __FILE__, __LINE__, "sssbsd", |
| "the key of an array can only be a string or a integer, variable:", | "the value of an array can only be a string, variable:", |
| cv[i].key, "type:", da->value->data[j]->type); | cv[i].key, "[", ds->key, "], type:", ds->type); |
| |
|
| return -1; |
return -1; |
| } |
} |
|
Line 73 int config_insert_values_internal(server *srv, array *
|
Line 77 int config_insert_values_internal(server *srv, array *
|
| if (du->type == TYPE_STRING) { |
if (du->type == TYPE_STRING) { |
| data_string *ds = (data_string *)du; |
data_string *ds = (data_string *)du; |
| |
|
| buffer_copy_string_buffer(cv[i].destination, ds->value); | buffer_copy_buffer(cv[i].destination, ds->value); |
| } else { |
} else { |
| log_error_write(srv, __FILE__, __LINE__, "ssss", cv[i].key, "should have been a string like ... = \"...\""); |
log_error_write(srv, __FILE__, __LINE__, "ssss", cv[i].key, "should have been a string like ... = \"...\""); |
| |
|
|
Line 135 int config_insert_values_internal(server *srv, array *
|
Line 139 int config_insert_values_internal(server *srv, array *
|
| } |
} |
| } |
} |
| |
|
| |
|
| log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected an integer:", cv[i].key, ds->value); |
log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected an integer:", cv[i].key, ds->value); |
| |
|
| return -1; |
return -1; |
|
Line 185 int config_insert_values_internal(server *srv, array *
|
Line 188 int config_insert_values_internal(server *srv, array *
|
| return 0; |
return 0; |
| } |
} |
| |
|
| int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) { | int config_insert_values_global(server *srv, array *ca, const config_values_t cv[], config_scope_type_t scope) { |
| size_t i; |
size_t i; |
| data_unset *du; |
data_unset *du; |
| |
|
|
Line 202 int config_insert_values_global(server *srv, array *ca
|
Line 205 int config_insert_values_global(server *srv, array *ca
|
| touched = data_string_init(); |
touched = data_string_init(); |
| |
|
| buffer_copy_string_len(touched->value, CONST_STR_LEN("")); |
buffer_copy_string_len(touched->value, CONST_STR_LEN("")); |
| buffer_copy_string_buffer(touched->key, du->key); | buffer_copy_buffer(touched->key, du->key); |
| |
|
| array_insert_unique(srv->config_touched, (data_unset *)touched); |
array_insert_unique(srv->config_touched, (data_unset *)touched); |
| } |
} |
| |
|
| return config_insert_values_internal(srv, ca, cv); | return config_insert_values_internal(srv, ca, cv, scope); |
| } |
} |
| |
|
| static unsigned short sock_addr_get_port(sock_addr *addr) { |
static unsigned short sock_addr_get_port(sock_addr *addr) { |
|
Line 218 static unsigned short sock_addr_get_port(sock_addr *ad
|
Line 221 static unsigned short sock_addr_get_port(sock_addr *ad
|
| #endif |
#endif |
| } |
} |
| |
|
| |
static const char* cond_result_to_string(cond_result_t cond_result) { |
| |
switch (cond_result) { |
| |
case COND_RESULT_UNSET: return "unset"; |
| |
case COND_RESULT_SKIP: return "skipped"; |
| |
case COND_RESULT_FALSE: return "false"; |
| |
case COND_RESULT_TRUE: return "true"; |
| |
default: return "invalid cond_result_t"; |
| |
} |
| |
} |
| |
|
| |
static int config_addrstr_eq_remote_ip_mask(server *srv, const char *addrstr, int nm_bits, sock_addr *rmt) { |
| |
/* special-case 0 == nm_bits to mean "all bits of the address" in addrstr */ |
| |
sock_addr val; |
| |
#ifdef HAVE_INET_PTON |
| |
if (1 == inet_pton(AF_INET, addrstr, &val.ipv4.sin_addr)) |
| |
#else |
| |
if (INADDR_NONE != (val.ipv4.sin_addr = inet_addr(addrstr))) |
| |
#endif |
| |
{ |
| |
/* build netmask */ |
| |
uint32_t nm; |
| |
if (nm_bits > 32) { |
| |
log_error_write(srv, __FILE__, __LINE__, "sd", "ERROR: ipv4 netmask too large:", nm_bits); |
| |
return -1; |
| |
} |
| |
nm = htonl(~((1u << (32 - (0 != nm_bits ? nm_bits : 32))) - 1)); |
| |
|
| |
if (rmt->plain.sa_family == AF_INET) { |
| |
return ((val.ipv4.sin_addr.s_addr & nm) == (rmt->ipv4.sin_addr.s_addr & nm)); |
| |
#ifdef HAVE_IPV6 |
| |
} else if (rmt->plain.sa_family == AF_INET6 |
| |
&& IN6_IS_ADDR_V4MAPPED(&rmt->ipv6.sin6_addr)) { |
| |
#ifdef s6_addr32 |
| |
in_addr_t x = rmt->ipv6.sin6_addr.s6_addr32[3]; |
| |
#else |
| |
in_addr_t x; |
| |
memcpy(&x, rmt->ipv6.sin6_addr.s6_addr+12, sizeof(in_addr_t)); |
| |
#endif |
| |
return ((val.ipv4.sin_addr.s_addr & nm) == (x & nm)); |
| |
#endif |
| |
} else { |
| |
return 0; |
| |
} |
| |
#if defined(HAVE_INET_PTON) && defined(HAVE_IPV6) |
| |
} else if (1 == inet_pton(AF_INET6, addrstr, &val.ipv6.sin6_addr)) { |
| |
if (nm_bits > 128) { |
| |
log_error_write(srv, __FILE__, __LINE__, "sd", "ERROR: ipv6 netmask too large:", nm_bits); |
| |
return -1; |
| |
} |
| |
if (rmt->plain.sa_family == AF_INET6) { |
| |
uint8_t *a = (uint8_t *)&val.ipv6.sin6_addr.s6_addr[0]; |
| |
uint8_t *b = (uint8_t *)&rmt->ipv6.sin6_addr.s6_addr[0]; |
| |
int match; |
| |
do { |
| |
match = (nm_bits >= 8) |
| |
? *a++ == *b++ |
| |
: (*a >> (8 - nm_bits)) == (*b >> (8 - nm_bits)); |
| |
} while (match && (nm_bits -= 8) > 0); |
| |
return match; |
| |
} else if (rmt->plain.sa_family == AF_INET |
| |
&& IN6_IS_ADDR_V4MAPPED(&val.ipv6.sin6_addr)) { |
| |
uint32_t nm = |
| |
nm_bits < 128 ? htonl(~(~0u >> (nm_bits > 96 ? nm_bits - 96 : 0))) : ~0u; |
| |
#ifdef s6_addr32 |
| |
in_addr_t x = val.ipv6.sin6_addr.s6_addr32[3]; |
| |
#else |
| |
in_addr_t x; |
| |
memcpy(&x, val.ipv6.sin6_addr.s6_addr+12, sizeof(in_addr_t)); |
| |
#endif |
| |
return ((x & nm) == (rmt->ipv4.sin_addr.s_addr & nm)); |
| |
} else { |
| |
return 0; |
| |
} |
| |
#endif |
| |
} else { |
| |
log_error_write(srv, __FILE__, __LINE__, "ss", "ERROR: ip addr is invalid:", addrstr); |
| |
return -1; |
| |
} |
| |
} |
| |
|
| |
static int config_addrbuf_eq_remote_ip_mask(server *srv, buffer *string, char *nm_slash, sock_addr *rmt) { |
| |
char *err; |
| |
int nm_bits = strtol(nm_slash + 1, &err, 10); |
| |
size_t addrstrlen = (size_t)(nm_slash - string->ptr); |
| |
char addrstr[64]; /*(larger than INET_ADDRSTRLEN and INET6_ADDRSTRLEN)*/ |
| |
|
| |
if (*err) { |
| |
log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", string, err); |
| |
return -1; |
| |
} |
| |
|
| |
if (nm_bits <= 0) { |
| |
if (*(nm_slash+1) == '\0') { |
| |
log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", string); |
| |
} else { |
| |
log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: invalid netmask <= 0:", string, err); |
| |
} |
| |
return -1; |
| |
} |
| |
|
| |
if (addrstrlen >= sizeof(addrstr)) { |
| |
log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: address string too long:", string); |
| |
return -1; |
| |
} |
| |
|
| |
memcpy(addrstr, string->ptr, addrstrlen); |
| |
addrstr[addrstrlen] = '\0'; |
| |
|
| |
return config_addrstr_eq_remote_ip_mask(srv, addrstr, nm_bits, rmt); |
| |
} |
| |
|
| static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc); |
static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc); |
| |
|
| static cond_result_t config_check_cond_nocache(server *srv, connection *con, data_config *dc) { |
static cond_result_t config_check_cond_nocache(server *srv, connection *con, data_config *dc) { |
| buffer *l; |
buffer *l; |
| server_socket *srv_sock = con->srv_socket; |
server_socket *srv_sock = con->srv_socket; |
| |
cond_cache_t *cache = &con->cond_cache[dc->context_ndx]; |
| |
|
| /* check parent first */ |
/* check parent first */ |
| if (dc->parent && dc->parent->context_ndx) { |
if (dc->parent && dc->parent->context_ndx) { |
|
Line 236 static cond_result_t config_check_cond_nocache(server
|
Line 351 static cond_result_t config_check_cond_nocache(server
|
| } |
} |
| |
|
| switch (config_check_cond_cached(srv, con, dc->parent)) { |
switch (config_check_cond_cached(srv, con, dc->parent)) { |
| case COND_RESULT_FALSE: |
|
| return COND_RESULT_FALSE; |
|
| case COND_RESULT_UNSET: |
case COND_RESULT_UNSET: |
| |
/* decide later */ |
| return COND_RESULT_UNSET; |
return COND_RESULT_UNSET; |
| default: | case COND_RESULT_SKIP: |
| | case COND_RESULT_FALSE: |
| | /* failed precondition */ |
| | return COND_RESULT_SKIP; |
| | case COND_RESULT_TRUE: |
| | /* proceed */ |
| break; |
break; |
| } |
} |
| } |
} |
| |
|
| if (dc->prev) { |
if (dc->prev) { |
| /** |
/** |
| * a else branch | * a else branch; can only be executed if the previous branch |
| * | * was evaluated as "false" (not unset/skipped/true) |
| * we can only be executed, if all of our previous brothers | |
| * are false | |
| */ |
*/ |
| if (con->conf.log_condition_handling) { |
if (con->conf.log_condition_handling) { |
| log_error_write(srv, __FILE__, __LINE__, "sb", "go prev", dc->prev->key); |
log_error_write(srv, __FILE__, __LINE__, "sb", "go prev", dc->prev->key); |
| } |
} |
| |
|
| /* make sure prev is checked first */ |
/* make sure prev is checked first */ |
| config_check_cond_cached(srv, con, dc->prev); | switch (config_check_cond_cached(srv, con, dc->prev)) { |
| case COND_RESULT_UNSET: |
| /* one of prev set me to FALSE */ | /* decide later */ |
| switch (con->cond_cache[dc->context_ndx].result) { | return COND_RESULT_UNSET; |
| | case COND_RESULT_SKIP: |
| | case COND_RESULT_TRUE: |
| | /* failed precondition */ |
| | return COND_RESULT_SKIP; |
| case COND_RESULT_FALSE: |
case COND_RESULT_FALSE: |
| return con->cond_cache[dc->context_ndx].result; | /* proceed */ |
| default: | |
| break; |
break; |
| } |
} |
| } |
} |
|
Line 273 static cond_result_t config_check_cond_nocache(server
|
Line 393 static cond_result_t config_check_cond_nocache(server
|
| log_error_write(srv, __FILE__, __LINE__, "dss", |
log_error_write(srv, __FILE__, __LINE__, "dss", |
| dc->comp, |
dc->comp, |
| dc->key->ptr, |
dc->key->ptr, |
| con->conditional_is_valid[dc->comp] ? "yeah" : "nej"); | "not available yet"); |
| } |
} |
| |
|
| return COND_RESULT_UNSET; |
return COND_RESULT_UNSET; |
| } |
} |
| |
|
| |
/* if we had a real result before and weren't cleared just return it */ |
| |
switch (cache->local_result) { |
| |
case COND_RESULT_TRUE: |
| |
case COND_RESULT_FALSE: |
| |
return cache->local_result; |
| |
default: |
| |
break; |
| |
} |
| |
|
| /* pass the rules */ |
/* pass the rules */ |
| |
|
| switch (dc->comp) { |
switch (dc->comp) { |
| case COMP_HTTP_HOST: { |
case COMP_HTTP_HOST: { |
| char *ck_colon = NULL, *val_colon = NULL; |
char *ck_colon = NULL, *val_colon = NULL; |
| |
|
| if (!buffer_is_empty(con->uri.authority)) { | if (!buffer_string_is_empty(con->uri.authority)) { |
| |
|
| /* |
/* |
| * append server-port to the HTTP_POST if necessary |
* append server-port to the HTTP_POST if necessary |
|
Line 301 static cond_result_t config_check_cond_nocache(server
|
Line 430 static cond_result_t config_check_cond_nocache(server
|
| |
|
| if (NULL != ck_colon && NULL == val_colon) { |
if (NULL != ck_colon && NULL == val_colon) { |
| /* condition "host:port" but client send "host" */ |
/* condition "host:port" but client send "host" */ |
| buffer_copy_string_buffer(srv->cond_check_buf, l); | buffer_copy_buffer(srv->cond_check_buf, l); |
| buffer_append_string_len(srv->cond_check_buf, CONST_STR_LEN(":")); |
buffer_append_string_len(srv->cond_check_buf, CONST_STR_LEN(":")); |
| buffer_append_long(srv->cond_check_buf, sock_addr_get_port(&(srv_sock->addr))); | buffer_append_int(srv->cond_check_buf, sock_addr_get_port(&(srv_sock->addr))); |
| l = srv->cond_check_buf; |
l = srv->cond_check_buf; |
| } else if (NULL != val_colon && NULL == ck_colon) { |
} else if (NULL != val_colon && NULL == ck_colon) { |
| /* condition "host" but client send "host:port" */ |
/* condition "host" but client send "host:port" */ |
|
Line 315 static cond_result_t config_check_cond_nocache(server
|
Line 444 static cond_result_t config_check_cond_nocache(server
|
| break; |
break; |
| } |
} |
| #if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT |
#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT |
| } else if (!buffer_is_empty(con->tlsext_server_name)) { | } else if (!buffer_string_is_empty(con->tlsext_server_name)) { |
| l = con->tlsext_server_name; |
l = con->tlsext_server_name; |
| #endif |
#endif |
| } else { |
} else { |
|
Line 336 static cond_result_t config_check_cond_nocache(server
|
Line 465 static cond_result_t config_check_cond_nocache(server
|
| |
|
| if ((dc->cond == CONFIG_COND_EQ || |
if ((dc->cond == CONFIG_COND_EQ || |
| dc->cond == CONFIG_COND_NE) && |
dc->cond == CONFIG_COND_NE) && |
| (con->dst_addr.plain.sa_family == AF_INET) && |
|
| (NULL != (nm_slash = strchr(dc->string->ptr, '/')))) { |
(NULL != (nm_slash = strchr(dc->string->ptr, '/')))) { |
| int nm_bits; | switch (config_addrbuf_eq_remote_ip_mask(srv, dc->string, nm_slash, &con->dst_addr)) { |
| long nm; | case 1: return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE; |
| char *err; | case 0: return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE; |
| struct in_addr val_inp; | case -1: return COND_RESULT_FALSE; /*(error parsing configfile entry)*/ |
| |
| if (*(nm_slash+1) == '\0') { | |
| log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string); | |
| |
| return COND_RESULT_FALSE; | |
| } |
} |
| |
|
| nm_bits = strtol(nm_slash + 1, &err, 10); |
|
| |
|
| if (*err) { |
|
| log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, err); |
|
| |
|
| return COND_RESULT_FALSE; |
|
| } |
|
| |
|
| /* take IP convert to the native */ |
|
| buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr); |
|
| #ifdef __WIN32 |
|
| if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) { |
|
| log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf); |
|
| |
|
| return COND_RESULT_FALSE; |
|
| } |
|
| |
|
| #else |
|
| if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) { |
|
| log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf); |
|
| |
|
| return COND_RESULT_FALSE; |
|
| } |
|
| #endif |
|
| |
|
| /* build netmask */ |
|
| nm = htonl(~((1 << (32 - nm_bits)) - 1)); |
|
| |
|
| if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) { |
|
| return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE; |
|
| } else { |
|
| return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE; |
|
| } |
|
| } else { |
|
| l = con->dst_addr_buf; |
|
| } |
} |
| |
l = con->dst_addr_buf; |
| break; |
break; |
| } |
} |
| case COMP_HTTP_SCHEME: |
case COMP_HTTP_SCHEME: |
|
Line 479 static cond_result_t config_check_cond_nocache(server
|
Line 567 static cond_result_t config_check_cond_nocache(server
|
| #ifdef HAVE_PCRE_H |
#ifdef HAVE_PCRE_H |
| case CONFIG_COND_NOMATCH: |
case CONFIG_COND_NOMATCH: |
| case CONFIG_COND_MATCH: { |
case CONFIG_COND_MATCH: { |
| cond_cache_t *cache = &con->cond_cache[dc->context_ndx]; |
|
| int n; |
int n; |
| |
|
| #ifndef elementsof |
#ifndef elementsof |
| #define elementsof(x) (sizeof(x) / sizeof(x[0])) |
#define elementsof(x) (sizeof(x) / sizeof(x[0])) |
| #endif |
#endif |
| n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0, | n = pcre_exec(dc->regex, dc->regex_study, CONST_BUF_LEN(l), 0, 0, |
| cache->matches, elementsof(cache->matches)); |
cache->matches, elementsof(cache->matches)); |
| |
|
| cache->patterncount = n; |
cache->patterncount = n; |
| if (n > 0) { |
if (n > 0) { |
| cache->comp_value = l; |
cache->comp_value = l; |
| cache->comp_type = dc->comp; |
|
| return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE; |
return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE; |
| } else { |
} else { |
| /* cache is already cleared */ |
/* cache is already cleared */ |
|
Line 512 static cond_result_t config_check_cond_cached(server *
|
Line 598 static cond_result_t config_check_cond_cached(server *
|
| cond_cache_t *caches = con->cond_cache; |
cond_cache_t *caches = con->cond_cache; |
| |
|
| if (COND_RESULT_UNSET == caches[dc->context_ndx].result) { |
if (COND_RESULT_UNSET == caches[dc->context_ndx].result) { |
| if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) { | caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc); |
| if (dc->next) { | switch (caches[dc->context_ndx].result) { |
| data_config *c; | case COND_RESULT_FALSE: |
| if (con->conf.log_condition_handling) { | case COND_RESULT_TRUE: |
| log_error_write(srv, __FILE__, __LINE__, "s", | /* remember result of local condition for a partial reset */ |
| "setting remains of chaining to false"); | caches[dc->context_ndx].local_result = caches[dc->context_ndx].result; |
| } | break; |
| for (c = dc->next; c; c = c->next) { | default: |
| caches[c->context_ndx].result = COND_RESULT_FALSE; | break; |
| } | |
| } | |
| } |
} |
| caches[dc->context_ndx].comp_type = dc->comp; |
|
| |
|
| if (con->conf.log_condition_handling) { |
if (con->conf.log_condition_handling) { |
| log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx, | log_error_write(srv, __FILE__, __LINE__, "dss", |
| "(uncached) result:", | dc->context_ndx, |
| caches[dc->context_ndx].result == COND_RESULT_UNSET ? "unknown" : | "(uncached) result:", |
| (caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false")); | cond_result_to_string(caches[dc->context_ndx].result)); |
| } |
} |
| } else { |
} else { |
| if (con->conf.log_condition_handling) { |
if (con->conf.log_condition_handling) { |
| log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx, | log_error_write(srv, __FILE__, __LINE__, "dss", |
| "(cached) result:", | dc->context_ndx, |
| caches[dc->context_ndx].result == COND_RESULT_UNSET ? "unknown" : | "(cached) result:", |
| (caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false")); | cond_result_to_string(caches[dc->context_ndx].result)); |
| } |
} |
| } |
} |
| return caches[dc->context_ndx].result; |
return caches[dc->context_ndx].result; |
| } |
} |
| |
|
| |
/* if we reset the cache result for a node, we also need to clear all |
| |
* child nodes and else-branches*/ |
| |
static void config_cond_clear_node(server *srv, connection *con, data_config *dc) { |
| |
/* if a node is "unset" all children are unset too */ |
| |
if (con->cond_cache[dc->context_ndx].result != COND_RESULT_UNSET) { |
| |
size_t i; |
| |
|
| |
con->cond_cache[dc->context_ndx].patterncount = 0; |
| |
con->cond_cache[dc->context_ndx].comp_value = NULL; |
| |
con->cond_cache[dc->context_ndx].result = COND_RESULT_UNSET; |
| |
|
| |
for (i = 0; i < dc->children.used; ++i) { |
| |
data_config *dc_child = dc->children.data[i]; |
| |
if (NULL == dc_child->prev) { |
| |
/* only call for first node in if-else chain */ |
| |
config_cond_clear_node(srv, con, dc_child); |
| |
} |
| |
} |
| |
if (NULL != dc->next) config_cond_clear_node(srv, con, dc->next); |
| |
} |
| |
} |
| |
|
| /** |
/** |
| * reset the config-cache for a named item |
* reset the config-cache for a named item |
| * |
* |
|
Line 552 void config_cond_cache_reset_item(server *srv, connect
|
Line 657 void config_cond_cache_reset_item(server *srv, connect
|
| size_t i; |
size_t i; |
| |
|
| for (i = 0; i < srv->config_context->used; i++) { |
for (i = 0; i < srv->config_context->used; i++) { |
| if (item == COMP_LAST_ELEMENT || | data_config *dc = (data_config *)srv->config_context->data[i]; |
| con->cond_cache[i].comp_type == item) { | |
| con->cond_cache[i].result = COND_RESULT_UNSET; | if (item == dc->comp) { |
| con->cond_cache[i].patterncount = 0; | /* clear local_result */ |
| con->cond_cache[i].comp_value = NULL; | con->cond_cache[i].local_result = COND_RESULT_UNSET; |
| | /* clear result in subtree (including the node itself) */ |
| | config_cond_clear_node(srv, con, dc); |
| } |
} |
| } |
} |
| } |
} |
|
Line 567 void config_cond_cache_reset_item(server *srv, connect
|
Line 674 void config_cond_cache_reset_item(server *srv, connect
|
| void config_cond_cache_reset(server *srv, connection *con) { |
void config_cond_cache_reset(server *srv, connection *con) { |
| size_t i; |
size_t i; |
| |
|
| config_cond_cache_reset_all_items(srv, con); | /* resetting all entries; no need to follow children as in config_cond_cache_reset_item */ |
| | for (i = 0; i < srv->config_context->used; i++) { |
| | con->cond_cache[i].result = COND_RESULT_UNSET; |
| | con->cond_cache[i].local_result = COND_RESULT_UNSET; |
| | con->cond_cache[i].patterncount = 0; |
| | con->cond_cache[i].comp_value = NULL; |
| | } |
| |
|
| for (i = 0; i < COMP_LAST_ELEMENT; i++) { |
for (i = 0; i < COMP_LAST_ELEMENT; i++) { |
| con->conditional_is_valid[i] = 0; |
con->conditional_is_valid[i] = 0; |
|
Line 594 int config_append_cond_match_buffer(connection *con, d
|
Line 707 int config_append_cond_match_buffer(connection *con, d
|
| cache->matches[n + 1] - cache->matches[n]); |
cache->matches[n + 1] - cache->matches[n]); |
| return 1; |
return 1; |
| } |
} |
| |
|