version 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; |
} |
} |
|
|