|
|
|
@ -258,184 +258,6 @@ int config_plugin_values_init(server * const srv, void *p_d, const config_plugin
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* handle global options */
|
|
|
|
|
|
|
|
|
|
/* parse config array */
|
|
|
|
|
int config_insert_values_internal(server *srv, const array *ca, const config_values_t cv[], config_scope_type_t scope) {
|
|
|
|
|
size_t i;
|
|
|
|
|
const data_unset *du;
|
|
|
|
|
|
|
|
|
|
for (i = 0; cv[i].key; i++) {
|
|
|
|
|
|
|
|
|
|
if (NULL == (du = array_get_element_klen(ca, cv[i].key, strlen(cv[i].key)))) {
|
|
|
|
|
/* no found */
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
case T_CONFIG_ARRAY:
|
|
|
|
|
if (du->type == TYPE_ARRAY) {
|
|
|
|
|
size_t j;
|
|
|
|
|
const data_array *da = (const data_array *)du;
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < da->value.used; j++) {
|
|
|
|
|
data_unset *ds = da->value.data[j];
|
|
|
|
|
if (ds->type == TYPE_STRING || ds->type == TYPE_INTEGER || ds->type == TYPE_ARRAY) {
|
|
|
|
|
array_insert_unique(cv[i].destination, ds->fn->copy(ds));
|
|
|
|
|
} else {
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sssbsd",
|
|
|
|
|
"the value of an array can only be a string, variable:",
|
|
|
|
|
cv[i].key, "[", &ds->key, "], type:", ds->type);
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ss", cv[i].key, "should have been a array of strings like ... = ( \"...\" )");
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case T_CONFIG_STRING:
|
|
|
|
|
if (du->type == TYPE_STRING) {
|
|
|
|
|
const data_string *ds = (const data_string *)du;
|
|
|
|
|
|
|
|
|
|
buffer_copy_buffer(cv[i].destination, &ds->value);
|
|
|
|
|
} else {
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ss", cv[i].key, "should have been a string like ... = \"...\"");
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case T_CONFIG_SHORT:
|
|
|
|
|
switch(du->type) {
|
|
|
|
|
case TYPE_INTEGER: {
|
|
|
|
|
const data_integer *di = (const data_integer *)du;
|
|
|
|
|
|
|
|
|
|
*((unsigned short *)(cv[i].destination)) = di->value;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TYPE_STRING: {
|
|
|
|
|
const data_string *ds = (const data_string *)du;
|
|
|
|
|
|
|
|
|
|
/* If the value came from an environment variable, then it is a
|
|
|
|
|
* data_string, although it may contain a number in ASCII
|
|
|
|
|
* decimal format. We try to interpret the string as a decimal
|
|
|
|
|
* short before giving up, in order to support setting numeric
|
|
|
|
|
* values with environment variables (eg, port number).
|
|
|
|
|
*/
|
|
|
|
|
if (ds->value.ptr && *ds->value.ptr) {
|
|
|
|
|
char *e;
|
|
|
|
|
long l = strtol(ds->value.ptr, &e, 10);
|
|
|
|
|
if (e != ds->value.ptr && !*e && l >=0 && l <= 65535) {
|
|
|
|
|
*((unsigned short *)(cv[i].destination)) = l;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected a short:", cv[i].key, &ds->value);
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssds", "unexpected type for key:", cv[i].key, du->type, "expected a short integer, range 0 ... 65535");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case T_CONFIG_INT:
|
|
|
|
|
switch(du->type) {
|
|
|
|
|
case TYPE_INTEGER: {
|
|
|
|
|
const data_integer *di = (const data_integer *)du;
|
|
|
|
|
|
|
|
|
|
*((unsigned int *)(cv[i].destination)) = di->value;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TYPE_STRING: {
|
|
|
|
|
const data_string *ds = (const data_string *)du;
|
|
|
|
|
|
|
|
|
|
if (ds->value.ptr && *ds->value.ptr) {
|
|
|
|
|
char *e;
|
|
|
|
|
long l = strtol(ds->value.ptr, &e, 10);
|
|
|
|
|
if (e != ds->value.ptr && !*e && l >= 0) {
|
|
|
|
|
*((unsigned int *)(cv[i].destination)) = l;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected an integer:", cv[i].key, &ds->value);
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssds", "unexpected type for key:", cv[i].key, du->type, "expected an integer, range 0 ... 4294967295");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case T_CONFIG_BOOLEAN:
|
|
|
|
|
if (du->type == TYPE_STRING) {
|
|
|
|
|
const data_string *ds = (const data_string *)du;
|
|
|
|
|
|
|
|
|
|
if (buffer_is_equal_string(&ds->value, CONST_STR_LEN("enable"))) {
|
|
|
|
|
*((unsigned short *)(cv[i].destination)) = 1;
|
|
|
|
|
} else if (buffer_is_equal_string(&ds->value, CONST_STR_LEN("disable"))) {
|
|
|
|
|
*((unsigned short *)(cv[i].destination)) = 0;
|
|
|
|
|
} else {
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, &ds->value, "(enable|disable)");
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\"");
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case T_CONFIG_LOCAL:
|
|
|
|
|
case T_CONFIG_UNSET:
|
|
|
|
|
break;
|
|
|
|
|
case T_CONFIG_UNSUPPORTED:
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found unsupported key:", cv[i].key, "-", (char *)(cv[i].destination));
|
|
|
|
|
|
|
|
|
|
srv->srvconf.config_unsupported = 1;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case T_CONFIG_DEPRECATED:
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination));
|
|
|
|
|
|
|
|
|
|
srv->srvconf.config_deprecated = 1;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int config_insert_values_global(server *srv, const array *ca, const config_values_t cv[], config_scope_type_t scope) {
|
|
|
|
|
size_t i;
|
|
|
|
|
const data_unset *du;
|
|
|
|
|
|
|
|
|
|
for (i = 0; cv[i].key; i++) {
|
|
|
|
|
if (NULL == (du = array_get_element_klen(ca, cv[i].key, strlen(cv[i].key)))) {
|
|
|
|
|
/* no found */
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
array_set_key_value(srv->srvconf.config_touched, CONST_BUF_LEN(&du->key), CONST_STR_LEN(""));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return config_insert_values_internal(srv, ca, cv, scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__attribute_cold__
|
|
|
|
|
__attribute_noinline__
|
|
|
|
|
static void config_cond_result_trace(connection *con, const data_config *dc, int cached) {
|
|
|
|
|