Add path and service module parameter types

The path type is validated if the module requested path
validation. Service checks can be done both on startup and at
runtime. This allows dynamic changes to module parameters to be validated
without a configuration context.
This commit is contained in:
Markus Mäkelä
2017-01-05 09:29:21 +02:00
parent e0ad6188ad
commit 257cb5c209
3 changed files with 83 additions and 10 deletions

View File

@ -223,10 +223,12 @@ SSL_LISTENER *make_ssl_structure(CONFIG_CONTEXT *obj, bool require_cert, int *er
* @param type Module type * @param type Module type
* @param key Parameter key * @param key Parameter key
* @param value Parameter value * @param value Parameter value
* @param context Configuration context or NULL for no context (uses runtime checks)
* *
* @return True if the configuration parameter is valid * @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 * @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 params List of configuration parameters
* @param key Parameter name * @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); const char* config_get_string(const CONFIG_PARAMETER *params, const char *key);
/** /**

View File

@ -82,16 +82,23 @@ enum mxs_module_param_type
MXS_MODULE_PARAM_INT, /**< Integer number */ MXS_MODULE_PARAM_INT, /**< Integer number */
MXS_MODULE_PARAM_BOOL, /**< Boolean value */ MXS_MODULE_PARAM_BOOL, /**< Boolean value */
MXS_MODULE_PARAM_STRING, /**< String 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 enum mxs_module_param_options
{ {
MXS_MODULE_OPT_NONE = 0, MXS_MODULE_OPT_NONE = 0,
MXS_MODULE_OPT_REQUIRED = (1 << 0), /**< A required parameter */ 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_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_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_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 */ /** Module parameter declaration */

View File

@ -2008,7 +2008,7 @@ check_config_objects(CONFIG_CONTEXT *context)
if (found == 0) if (found == 0)
{ {
if (module == NULL || 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'.", MXS_ERROR("Unexpected parameter '%s' for object '%s' of type '%s'.",
params->name, obj->object, type); params->name, obj->object, type);
@ -3385,7 +3385,24 @@ bool config_is_ssl_parameter(const char *key)
return false; 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; bool valid = false;
const MXS_MODULE *mod = get_module(module, type); 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; 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: default:
MXS_ERROR("Unexpected module parameter type: %d", mod->parameters[i].type); MXS_ERROR("Unexpected module parameter type: %d", mod->parameters[i].type);
ss_dassert(false); ss_dassert(false);