Allow restriction of module command arguments
The module commands now support an optional flag for arguments that when enabled checks that the argument module name matches the registered domain name. This can be used to enforce argument type validity for arguments that are given to modules that expect objects of a certain type. For example, this is used by the cache and dbfwfilter to prevent valid filters but of the wrong type being given as arguments.
This commit is contained in:
@ -43,7 +43,7 @@ MXS_BEGIN_DECLS
|
|||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint64_t type; /**< The argument type */
|
uint64_t type; /**< The argument type and options */
|
||||||
const char *description; /**< The argument description */
|
const char *description; /**< The argument description */
|
||||||
} modulecmd_arg_type_t;
|
} modulecmd_arg_type_t;
|
||||||
|
|
||||||
@ -68,13 +68,15 @@ typedef struct
|
|||||||
/**
|
/**
|
||||||
* Options for arguments, bits 9 through 32
|
* Options for arguments, bits 9 through 32
|
||||||
*/
|
*/
|
||||||
#define MODULECMD_ARG_OPTIONAL (1 << 8) /**< The argument is optional */
|
#define MODULECMD_ARG_OPTIONAL (1 << 8) /**< The argument is optional */
|
||||||
|
#define MODULECMD_ARG_NAME_MATCHES_DOMAIN (1 << 9) /**< Argument module name must match domain name */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper macros
|
* Helper macros
|
||||||
*/
|
*/
|
||||||
#define MODULECMD_GET_TYPE(t) ((t)->type & 0xff)
|
#define MODULECMD_GET_TYPE(t) ((t)->type & 0xff)
|
||||||
#define MODULECMD_ARG_IS_REQUIRED(t) (((t)->type & MODULECMD_ARG_OPTIONAL) == 0)
|
#define MODULECMD_ARG_IS_REQUIRED(t) (((t)->type & MODULECMD_ARG_OPTIONAL) == 0)
|
||||||
|
#define MODULECMD_ALLOW_NAME_MISMATCH(t) (((t)->type & MODULECMD_ARG_NAME_MATCHES_DOMAIN) == 0)
|
||||||
#define MODULECMD_ARG_PRESENT(t) (MODULECMD_GET_TYPE(t) != MODULECMD_ARG_NONE)
|
#define MODULECMD_ARG_PRESENT(t) (MODULECMD_GET_TYPE(t) != MODULECMD_ARG_NONE)
|
||||||
|
|
||||||
/** Argument list node */
|
/** Argument list node */
|
||||||
|
@ -205,7 +205,7 @@ static bool domain_has_command(MODULECMD_DOMAIN *dm, const char *id)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool process_argument(modulecmd_arg_type_t *type, const void* value,
|
static bool process_argument(const MODULECMD *cmd, modulecmd_arg_type_t *type, const void* value,
|
||||||
struct arg_node *arg, const char **err)
|
struct arg_node *arg, const char **err)
|
||||||
{
|
{
|
||||||
bool rval = false;
|
bool rval = false;
|
||||||
@ -255,8 +255,16 @@ static bool process_argument(modulecmd_arg_type_t *type, const void* value,
|
|||||||
case MODULECMD_ARG_SERVICE:
|
case MODULECMD_ARG_SERVICE:
|
||||||
if ((arg->value.service = service_find((char*)value)))
|
if ((arg->value.service = service_find((char*)value)))
|
||||||
{
|
{
|
||||||
arg->type.type = MODULECMD_ARG_SERVICE;
|
if (MODULECMD_ALLOW_NAME_MISMATCH(type) ||
|
||||||
rval = true;
|
strcmp(cmd->domain, arg->value.service->routerModule) == 0)
|
||||||
|
{
|
||||||
|
arg->type.type = MODULECMD_ARG_SERVICE;
|
||||||
|
rval = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*err = "router and domain names don't match";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -267,8 +275,16 @@ static bool process_argument(modulecmd_arg_type_t *type, const void* value,
|
|||||||
case MODULECMD_ARG_SERVER:
|
case MODULECMD_ARG_SERVER:
|
||||||
if ((arg->value.server = server_find_by_unique_name((char*)value)))
|
if ((arg->value.server = server_find_by_unique_name((char*)value)))
|
||||||
{
|
{
|
||||||
arg->type.type = MODULECMD_ARG_SERVER;
|
if (MODULECMD_ALLOW_NAME_MISMATCH(type) ||
|
||||||
rval = true;
|
strcmp(cmd->domain, arg->value.server->protocol) == 0)
|
||||||
|
{
|
||||||
|
arg->type.type = MODULECMD_ARG_SERVER;
|
||||||
|
rval = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*err = "server and domain names don't match";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -293,8 +309,16 @@ static bool process_argument(modulecmd_arg_type_t *type, const void* value,
|
|||||||
case MODULECMD_ARG_MONITOR:
|
case MODULECMD_ARG_MONITOR:
|
||||||
if ((arg->value.monitor = monitor_find((char*)value)))
|
if ((arg->value.monitor = monitor_find((char*)value)))
|
||||||
{
|
{
|
||||||
arg->type.type = MODULECMD_ARG_MONITOR;
|
if (MODULECMD_ALLOW_NAME_MISMATCH(type) ||
|
||||||
rval = true;
|
strcmp(cmd->domain, arg->value.monitor->module_name) == 0)
|
||||||
|
{
|
||||||
|
arg->type.type = MODULECMD_ARG_MONITOR;
|
||||||
|
rval = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*err = "monitor and domain names don't match";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -305,8 +329,16 @@ static bool process_argument(modulecmd_arg_type_t *type, const void* value,
|
|||||||
case MODULECMD_ARG_FILTER:
|
case MODULECMD_ARG_FILTER:
|
||||||
if ((arg->value.filter = filter_def_find((char*)value)))
|
if ((arg->value.filter = filter_def_find((char*)value)))
|
||||||
{
|
{
|
||||||
arg->type.type = MODULECMD_ARG_FILTER;
|
if (MODULECMD_ALLOW_NAME_MISMATCH(type) ||
|
||||||
rval = true;
|
strcmp(cmd->domain, arg->value.filter->module) == 0)
|
||||||
|
{
|
||||||
|
arg->type.type = MODULECMD_ARG_FILTER;
|
||||||
|
rval = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*err = "filter and domain names don't match";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -459,7 +491,7 @@ MODULECMD_ARG* modulecmd_arg_parse(const MODULECMD *cmd, int argc, const void **
|
|||||||
{
|
{
|
||||||
const char *err = "";
|
const char *err = "";
|
||||||
|
|
||||||
if (!process_argument(&cmd->arg_types[i], argv[i], &arg->argv[i], &err))
|
if (!process_argument(cmd, &cmd->arg_types[i], argv[i], &arg->argv[i], &err))
|
||||||
{
|
{
|
||||||
error = true;
|
error = true;
|
||||||
modulecmd_set_error("Argument %d, %s: %s", i + 1, err, argv[i] ? argv[i] : "No argument given");
|
modulecmd_set_error("Argument %d, %s: %s", i + 1, err, argv[i] ? argv[i] : "No argument given");
|
||||||
|
16
server/modules/filter/cache/cachefilter.cc
vendored
16
server/modules/filter/cache/cachefilter.cc
vendored
@ -93,17 +93,11 @@ bool cache_command_show(const MODULECMD_ARG* pArgs)
|
|||||||
|
|
||||||
const MXS_FILTER_DEF* pFilterDef = pArgs->argv[1].value.filter;
|
const MXS_FILTER_DEF* pFilterDef = pArgs->argv[1].value.filter;
|
||||||
ss_dassert(pFilterDef);
|
ss_dassert(pFilterDef);
|
||||||
|
ss_dassert(strcmp(pFilterDef->module, MXS_MODULE_NAME) == 0);
|
||||||
|
|
||||||
if (strcmp(pFilterDef->module, "cache") == 0)
|
CacheFilter* pFilter = reinterpret_cast<CacheFilter*>(pFilterDef->filter);
|
||||||
{
|
|
||||||
CacheFilter* pFilter = reinterpret_cast<CacheFilter*>(pFilterDef->filter);
|
|
||||||
|
|
||||||
pFilter->cache().show(pDcb);
|
pFilter->cache().show(pDcb);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dcb_printf(pDcb, "Filter %s exists, but it is not a cache.", pFilterDef->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -127,10 +121,10 @@ extern "C" MXS_MODULE* MXS_CREATE_MODULE()
|
|||||||
static modulecmd_arg_type_t show_argv[] =
|
static modulecmd_arg_type_t show_argv[] =
|
||||||
{
|
{
|
||||||
{ MODULECMD_ARG_OUTPUT, "The output dcb" },
|
{ MODULECMD_ARG_OUTPUT, "The output dcb" },
|
||||||
{ MODULECMD_ARG_FILTER, "Cache name" }
|
{ MODULECMD_ARG_FILTER | MODULECMD_ARG_NAME_MATCHES_DOMAIN, "Cache name" }
|
||||||
};
|
};
|
||||||
|
|
||||||
modulecmd_register_command("cache", "show", cache_command_show,
|
modulecmd_register_command(MXS_MODULE_NAME, "show", cache_command_show,
|
||||||
MXS_ARRAY_NELEMS(show_argv), show_argv);
|
MXS_ARRAY_NELEMS(show_argv), show_argv);
|
||||||
|
|
||||||
MXS_NOTICE("Initialized cache module %s.\n", VERSION_STRING);
|
MXS_NOTICE("Initialized cache module %s.\n", VERSION_STRING);
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
*@endcode
|
*@endcode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define MXS_MODULE_NAME "dbfwfilter"
|
||||||
#include <maxscale/cdefs.h>
|
#include <maxscale/cdefs.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -791,19 +792,19 @@ MXS_MODULE* MXS_CREATE_MODULE()
|
|||||||
{
|
{
|
||||||
modulecmd_arg_type_t args_rules_reload[] =
|
modulecmd_arg_type_t args_rules_reload[] =
|
||||||
{
|
{
|
||||||
{MODULECMD_ARG_FILTER, "Filter to reload"},
|
{MODULECMD_ARG_FILTER | MODULECMD_ARG_NAME_MATCHES_DOMAIN, "Filter to reload"},
|
||||||
{MODULECMD_ARG_STRING | MODULECMD_ARG_OPTIONAL, "Path to rule file"}
|
{MODULECMD_ARG_STRING | MODULECMD_ARG_OPTIONAL, "Path to rule file"}
|
||||||
};
|
};
|
||||||
|
|
||||||
modulecmd_register_command("dbfwfilter", "rules/reload", dbfw_reload_rules, 2, args_rules_reload);
|
modulecmd_register_command(MXS_MODULE_NAME, "rules/reload", dbfw_reload_rules, 2, args_rules_reload);
|
||||||
|
|
||||||
modulecmd_arg_type_t args_rules_show[] =
|
modulecmd_arg_type_t args_rules_show[] =
|
||||||
{
|
{
|
||||||
{MODULECMD_ARG_OUTPUT, "DCB where result is written"},
|
{MODULECMD_ARG_OUTPUT, "DCB where result is written"},
|
||||||
{MODULECMD_ARG_FILTER, "Filter to inspect"}
|
{MODULECMD_ARG_FILTER | MODULECMD_ARG_NAME_MATCHES_DOMAIN, "Filter to inspect"}
|
||||||
};
|
};
|
||||||
|
|
||||||
modulecmd_register_command("dbfwfilter", "rules", dbfw_show_rules, 2, args_rules_show);
|
modulecmd_register_command(MXS_MODULE_NAME, "rules", dbfw_show_rules, 2, args_rules_show);
|
||||||
|
|
||||||
static MXS_FILTER_OBJECT MyObject =
|
static MXS_FILTER_OBJECT MyObject =
|
||||||
{
|
{
|
||||||
|
@ -43,17 +43,11 @@ bool masking_command_reload(const MODULECMD_ARG* pArgs)
|
|||||||
|
|
||||||
const MXS_FILTER_DEF* pFilterDef = pArgs->argv[1].value.filter;
|
const MXS_FILTER_DEF* pFilterDef = pArgs->argv[1].value.filter;
|
||||||
ss_dassert(pFilterDef);
|
ss_dassert(pFilterDef);
|
||||||
|
ss_dassert(strcmp(pFilterDef->module, MXS_MODULE_NAME) == 0);
|
||||||
|
|
||||||
if (strcmp(pFilterDef->module, "masking") == 0)
|
MaskingFilter* pFilter = reinterpret_cast<MaskingFilter*>(pFilterDef->filter);
|
||||||
{
|
|
||||||
MaskingFilter* pFilter = reinterpret_cast<MaskingFilter*>(pFilterDef->filter);
|
|
||||||
|
|
||||||
MXS_EXCEPTION_GUARD(pFilter->reload(pDcb));
|
MXS_EXCEPTION_GUARD(pFilter->reload(pDcb));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dcb_printf(pDcb, "Filter %s exists, but it is not a masking filter.", pFilterDef->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -69,10 +63,10 @@ extern "C" MXS_MODULE* MXS_CREATE_MODULE()
|
|||||||
static modulecmd_arg_type_t reload_argv[] =
|
static modulecmd_arg_type_t reload_argv[] =
|
||||||
{
|
{
|
||||||
{ MODULECMD_ARG_OUTPUT, "The output dcb" },
|
{ MODULECMD_ARG_OUTPUT, "The output dcb" },
|
||||||
{ MODULECMD_ARG_FILTER, "Masking name" }
|
{ MODULECMD_ARG_FILTER | MODULECMD_ARG_NAME_MATCHES_DOMAIN, "Masking name" }
|
||||||
};
|
};
|
||||||
|
|
||||||
modulecmd_register_command("masking", "reload", masking_command_reload,
|
modulecmd_register_command(MXS_MODULE_NAME, "reload", masking_command_reload,
|
||||||
MXS_ARRAY_NELEMS(reload_argv), reload_argv);
|
MXS_ARRAY_NELEMS(reload_argv), reload_argv);
|
||||||
|
|
||||||
MXS_NOTICE("Masking module %s initialized.", VERSION_STRING);
|
MXS_NOTICE("Masking module %s initialized.", VERSION_STRING);
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define MXS_MODULE_NAME "avrorouter"
|
||||||
|
#include <maxscale/cdefs.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -134,10 +137,10 @@ MXS_MODULE* MXS_CREATE_MODULE()
|
|||||||
|
|
||||||
static modulecmd_arg_type_t args[] =
|
static modulecmd_arg_type_t args[] =
|
||||||
{
|
{
|
||||||
{ MODULECMD_ARG_SERVICE, "The avrorouter service" },
|
{ MODULECMD_ARG_SERVICE | MODULECMD_ARG_NAME_MATCHES_DOMAIN, "The avrorouter service" },
|
||||||
{ MODULECMD_ARG_STRING, "Action, whether to 'start' or 'stop' the conversion process" }
|
{ MODULECMD_ARG_STRING, "Action, whether to 'start' or 'stop' the conversion process" }
|
||||||
};
|
};
|
||||||
modulecmd_register_command("avrorouter", "convert", avro_handle_convert, 2, args);
|
modulecmd_register_command(MXS_MODULE_NAME, "convert", avro_handle_convert, 2, args);
|
||||||
|
|
||||||
static ROUTER_OBJECT MyObject =
|
static ROUTER_OBJECT MyObject =
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user