New feature: AMI Action FilterAdd
This adds a new action, FilterAdd to the manager interface that allows control over event filters for the current session (closes issue ASTERISK-16795) Reported by: kobaz Tested by: kobaz,loloski git-svn-id: http://svn.digium.com/svn/asterisk/trunk@326267 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
parent
0359d5c643
commit
fe15a18ce5
3
CHANGES
3
CHANGES
|
@ -41,6 +41,9 @@ Asterisk Manager Interface
|
|||
Description field that is set by 'description' in the channel configuration
|
||||
file.
|
||||
* Added Uniqueid header to UserEvent.
|
||||
* Added new action FilterAdd to control event filters for the current session.
|
||||
This requires the system permission and uses the same filter syntax as
|
||||
filters that can be defined in manager.conf
|
||||
|
||||
Asterisk HTTP Server
|
||||
--------------------------
|
||||
|
|
156
main/manager.c
156
main/manager.c
|
@ -812,6 +812,52 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|||
<para>Generates an AOC-D or AOC-E message on a channel.</para>
|
||||
</description>
|
||||
</manager>
|
||||
<manager name="Filter" language="en_US">
|
||||
<synopsis>
|
||||
Dynamically add filters for the current manager session.
|
||||
</synopsis>
|
||||
<syntax>
|
||||
<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
|
||||
<parameter name="Operation">
|
||||
<enumlist>
|
||||
<enum name="Add">
|
||||
<para>Add a filter.</para>
|
||||
</enum>
|
||||
</enumlist>
|
||||
</parameter>
|
||||
<parameter name="Filter">
|
||||
<para>Filters can be whitelist or blacklist</para>
|
||||
<para>Example whitelist filter: "Event: Newchannel"</para>
|
||||
<para>Example blacklist filter: "!Channel: DAHDI.*"</para>
|
||||
<para>This filter option is used to whitelist or blacklist events per user to be
|
||||
reported with regular expressions and are allowed if both the regex matches
|
||||
and the user has read access as defined in manager.conf. Filters are assumed to be for whitelisting
|
||||
unless preceeded by an exclamation point, which marks it as being black.
|
||||
Evaluation of the filters is as follows:</para>
|
||||
<para>- If no filters are configured all events are reported as normal.</para>
|
||||
<para>- If there are white filters only: implied black all filter processed first, then white filters.</para>
|
||||
<para>- If there are black filters only: implied white all filter processed first, then black filters.</para>
|
||||
<para>- If there are both white and black filters: implied black all filter processed first, then white
|
||||
filters, and lastly black filters.</para>
|
||||
</parameter>
|
||||
</syntax>
|
||||
<description>
|
||||
<para>The filters added are only used for the current session.
|
||||
Once the connection is closed the filters are removed.</para>
|
||||
<para>This comand requires the system permission because
|
||||
this command can be used to create filters that may bypass
|
||||
filters defined in manager.conf</para>
|
||||
</description>
|
||||
</manager>
|
||||
<manager name="FilterList" language="en_US">
|
||||
<synopsis>
|
||||
Show current event filters for this session
|
||||
</synopsis>
|
||||
<description>
|
||||
<para>The filters displayed are for the current session. Only those filters defined in
|
||||
manager.conf will be present upon starting a new session.</para>
|
||||
</description>
|
||||
</manager>
|
||||
***/
|
||||
|
||||
enum error_type {
|
||||
|
@ -828,6 +874,11 @@ enum error_type {
|
|||
FAILURE_APPEND
|
||||
};
|
||||
|
||||
enum add_filter_result {
|
||||
FILTER_SUCCESS,
|
||||
FILTER_ALLOC_FAILED,
|
||||
FILTER_COMPILE_FAIL,
|
||||
};
|
||||
|
||||
/*!
|
||||
* Linked list of events.
|
||||
|
@ -1019,6 +1070,8 @@ static AST_RWLIST_HEAD_STATIC(manager_hooks, manager_custom_hook);
|
|||
|
||||
static void free_channelvars(void);
|
||||
|
||||
static enum add_filter_result manager_add_filter(const char *filter_pattern, struct ao2_container *whitefilters, struct ao2_container *blackfilters);
|
||||
|
||||
/*! \brief Add a custom hook to be called when an event is fired */
|
||||
void ast_manager_register_hook(struct manager_custom_hook *hook)
|
||||
{
|
||||
|
@ -4122,6 +4175,88 @@ static int blackfilter_cmp_fn(void *obj, void *arg, void *data, int flags)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Manager command to add an event filter to a manager session
|
||||
* \see For more details look at manager_add_filter
|
||||
*/
|
||||
static int action_filter(struct mansession *s, const struct message *m)
|
||||
{
|
||||
const char *filter = astman_get_header(m, "Filter");
|
||||
const char *operation = astman_get_header(m, "Operation");
|
||||
int res;
|
||||
|
||||
if (!strcasecmp(operation, "Add")) {
|
||||
res = manager_add_filter(filter, s->session->whitefilters, s->session->blackfilters);
|
||||
|
||||
if (res != FILTER_SUCCESS) {
|
||||
if (res == FILTER_ALLOC_FAILED) {
|
||||
astman_send_error(s, m, "Internal Error. Failed to allocate regex for filter");
|
||||
return 0;
|
||||
} else if (res == FILTER_COMPILE_FAIL) {
|
||||
astman_send_error(s, m, "Filter did not compile. Check the syntax of the filter given.");
|
||||
return 0;
|
||||
} else {
|
||||
astman_send_error(s, m, "Internal Error. Failed adding filter.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
astman_send_ack(s, m, "Success");
|
||||
return 0;
|
||||
}
|
||||
|
||||
astman_send_error(s, m, "Unknown operation");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Add an event filter to a manager session
|
||||
*
|
||||
* \param s manager session to modify filters on
|
||||
* \param filter_pattern Filter syntax to add, see below for syntax
|
||||
*
|
||||
* \return FILTER_ALLOC_FAILED Memory allocation failure
|
||||
* \return FILTER_COMPILE_FAIL If the filter did not compile
|
||||
* \return FILTER_SUCCESS Success
|
||||
*
|
||||
* Filter will be used to match against each line of a manager event
|
||||
* Filter can be any valid regular expression
|
||||
* Filter can be a valid regular expression prefixed with !, which will add the filter as a black filter
|
||||
*
|
||||
* \example filter_pattern = "Event: Newchannel"
|
||||
* \example filter_pattern = "Event: New.*"
|
||||
* \example filter_pattern = "!Channel: DAHDI.*"
|
||||
*
|
||||
*/
|
||||
static enum add_filter_result manager_add_filter(const char *filter_pattern, struct ao2_container *whitefilters, struct ao2_container *blackfilters) {
|
||||
regex_t *new_filter = ao2_t_alloc(sizeof(*new_filter), event_filter_destructor, "event_filter allocation");
|
||||
int is_blackfilter;
|
||||
|
||||
if (!new_filter) {
|
||||
return FILTER_ALLOC_FAILED;
|
||||
}
|
||||
|
||||
if (filter_pattern[0] == '!') {
|
||||
is_blackfilter = 1;
|
||||
filter_pattern++;
|
||||
} else {
|
||||
is_blackfilter = 0;
|
||||
}
|
||||
|
||||
if (regcomp(new_filter, filter_pattern, 0)) {
|
||||
ao2_t_ref(new_filter, -1, "failed to make regx");
|
||||
return FILTER_COMPILE_FAIL;
|
||||
}
|
||||
|
||||
if (is_blackfilter) {
|
||||
ao2_t_link(blackfilters, new_filter, "link new filter into black user container");
|
||||
} else {
|
||||
ao2_t_link(whitefilters, new_filter, "link new filter into white user container");
|
||||
}
|
||||
|
||||
return FILTER_SUCCESS;
|
||||
}
|
||||
|
||||
static int match_filter(struct mansession *s, char *eventdata)
|
||||
{
|
||||
int result = 0;
|
||||
|
@ -6284,6 +6419,7 @@ static int __init_manager(int reload)
|
|||
ast_manager_register_xml("ModuleLoad", EVENT_FLAG_SYSTEM, manager_moduleload);
|
||||
ast_manager_register_xml("ModuleCheck", EVENT_FLAG_SYSTEM, manager_modulecheck);
|
||||
ast_manager_register_xml("AOCMessage", EVENT_FLAG_AOC, action_aocmessage);
|
||||
ast_manager_register_xml("Filter", EVENT_FLAG_SYSTEM, action_filter);
|
||||
|
||||
ast_cli_register_multiple(cli_manager, ARRAY_LEN(cli_manager));
|
||||
ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
|
||||
|
@ -6563,25 +6699,7 @@ static int __init_manager(int reload)
|
|||
}
|
||||
} else if (!strcasecmp(var->name, "eventfilter")) {
|
||||
const char *value = var->value;
|
||||
regex_t *new_filter = ao2_t_alloc(sizeof(*new_filter), event_filter_destructor, "event_filter allocation");
|
||||
if (new_filter) {
|
||||
int is_blackfilter;
|
||||
if (value[0] == '!') {
|
||||
is_blackfilter = 1;
|
||||
value++;
|
||||
} else {
|
||||
is_blackfilter = 0;
|
||||
}
|
||||
if (regcomp(new_filter, value, 0)) {
|
||||
ao2_t_ref(new_filter, -1, "failed to make regx");
|
||||
} else {
|
||||
if (is_blackfilter) {
|
||||
ao2_t_link(user->blackfilters, new_filter, "link new filter into black user container");
|
||||
} else {
|
||||
ao2_t_link(user->whitefilters, new_filter, "link new filter into white user container");
|
||||
}
|
||||
}
|
||||
}
|
||||
manager_add_filter(value, user->whitefilters, user->blackfilters);
|
||||
} else {
|
||||
ast_debug(1, "%s is an unknown option.\n", var->name);
|
||||
}
|
||||
|
|
Reference in New Issue