diff --git a/include/maxscale/config.h b/include/maxscale/config.h index 33ddad35f..f39190e77 100644 --- a/include/maxscale/config.h +++ b/include/maxscale/config.h @@ -223,10 +223,12 @@ SSL_LISTENER *make_ssl_structure(CONFIG_CONTEXT *obj, bool require_cert, int *er * @param type Module type * @param key Parameter key * @param value Parameter value + * @param context Configuration context or NULL for no context (uses runtime checks) * * @return True if the configuration parameter is valid */ -bool config_param_is_valid(const char *module, const char *type, const char *key, const char *value); +bool config_param_is_valid(const char *module, const char *type, const char *key, + const char *value, const CONFIG_CONTEXT *context); /** * @brief Get a boolean value @@ -256,7 +258,8 @@ int config_get_integer(const CONFIG_PARAMETER *params, const char *key); * @param params List of configuration parameters * @param key Parameter name * - * @return The raw string value */ + * @return The raw string value + */ const char* config_get_string(const CONFIG_PARAMETER *params, const char *key); /** diff --git a/include/maxscale/modinfo.h b/include/maxscale/modinfo.h index 1a5169079..40789eecc 100644 --- a/include/maxscale/modinfo.h +++ b/include/maxscale/modinfo.h @@ -82,16 +82,23 @@ enum mxs_module_param_type MXS_MODULE_PARAM_INT, /**< Integer number */ MXS_MODULE_PARAM_BOOL, /**< Boolean value */ MXS_MODULE_PARAM_STRING, /**< String value */ - MXS_MODULE_PARAM_ENUM /**< Enumeration of string values */ + MXS_MODULE_PARAM_ENUM, /**< Enumeration of string values */ + MXS_MODULE_PARAM_PATH, /**< Path to a file or a directory */ + MXS_MODULE_PARAM_SERVICE, /**< Service name */ }; +/** Parameter options + * + * If no type is specified, the option can be used with all parameter types + */ enum mxs_module_param_options { - MXS_MODULE_OPT_NONE = 0, - MXS_MODULE_OPT_REQUIRED = (1 << 0), /**< A required parameter */ - MXS_MODULE_OPT_PATH_X_OK = (1 << 1), /**< PATH: Execute permission to path required */ - MXS_MODULE_OPT_PATH_R_OK = (1 << 2), /**< PATH: Read permission to path required */ - MXS_MODULE_OPT_PATH_W_OK = (1 << 3) /**< PATH: Write permission to path required */ + MXS_MODULE_OPT_NONE = 0, + MXS_MODULE_OPT_REQUIRED = (1 << 0), /**< A required parameter */ + MXS_MODULE_OPT_PATH_X_OK = (1 << 1), /**< PATH: Execute permission to path required */ + MXS_MODULE_OPT_PATH_R_OK = (1 << 2), /**< PATH: Read permission to path required */ + MXS_MODULE_OPT_PATH_W_OK = (1 << 3), /**< PATH: Write permission to path required */ + MXS_MODULE_OPT_PATH_F_OK = (1 << 4) /**< PATH: Path must exist */ }; /** Module parameter declaration */ diff --git a/server/core/config.c b/server/core/config.c index 20c63daac..aaaf0a40e 100644 --- a/server/core/config.c +++ b/server/core/config.c @@ -2008,7 +2008,7 @@ check_config_objects(CONFIG_CONTEXT *context) if (found == 0) { if (module == NULL || - !config_param_is_valid(module, module_type, params->name, params->value)) + !config_param_is_valid(module, module_type, params->name, params->value, context)) { MXS_ERROR("Unexpected parameter '%s' for object '%s' of type '%s'.", params->name, obj->object, type); @@ -3385,7 +3385,24 @@ bool config_is_ssl_parameter(const char *key) return false; } -bool config_param_is_valid(const char *module, const char *type, const char *key, const char *value) +static bool config_contains_type(const CONFIG_CONTEXT *ctx, const char *name, const char *type) +{ + while (ctx) + { + if (strcmp(ctx->object, name) == 0 && + strcmp(type, config_get_value_string(ctx->parameters, "type")) == 0) + { + return true; + } + + ctx = ctx->next; + } + + return false; +} + +bool config_param_is_valid(const char *module, const char *type, const char *key, + const char *value, const CONFIG_CONTEXT *context) { bool valid = false; const MXS_MODULE *mod = get_module(module, type); @@ -3443,6 +3460,52 @@ bool config_param_is_valid(const char *module, const char *type, const char *key } break; + case MXS_MODULE_PARAM_SERVICE: + if ((context && config_contains_type(context, "service", value)) || + service_find(value)) + { + valid = true; + } + break; + + case MXS_MODULE_PARAM_PATH: + if (mod->parameters[i].options & (MXS_MODULE_OPT_PATH_W_OK | + MXS_MODULE_OPT_PATH_R_OK | + MXS_MODULE_OPT_PATH_X_OK | + MXS_MODULE_OPT_PATH_F_OK)) + { + int mode = F_OK; + if (mod->parameters[i].options & MXS_MODULE_OPT_PATH_W_OK) + { + mode |= W_OK; + } + if (mod->parameters[i].options & MXS_MODULE_OPT_PATH_R_OK) + { + mode |= R_OK; + } + if (mod->parameters[i].options & MXS_MODULE_OPT_PATH_X_OK) + { + mode |= X_OK; + } + + if (access(value, mode) == 0) + { + valid = true; + } + else + { + char err[MXS_STRERROR_BUFLEN]; + MXS_ERROR("Bad path parameter '%s': %d, %s", value, + errno, strerror_r(errno, err, sizeof(err))); + } + } + else + { + /** No checks for the path are required */ + valid = true; + } + break; + default: MXS_ERROR("Unexpected module parameter type: %d", mod->parameters[i].type); ss_dassert(false);