Data Structures | |
struct | actions |
list of actions registered More... | |
struct | all_events |
struct | ast_manager_user |
user descriptor, as read from the config file. More... | |
struct | channelvars |
struct | eventqent |
struct | fast_originate_helper |
helper function for originate More... | |
struct | manager_channel_variable |
struct | manager_hooks |
list of hooks registered More... | |
struct | mansession |
struct | mansession_session |
struct | permalias |
struct | users |
list of users found in the config file More... | |
Defines | |
#define | ASTMAN_APPEND_BUF_INITSIZE 256 |
initial allocated size for the astman_append_buf | |
#define | DEFAULT_REALM "asterisk" |
#define | GET_HEADER_FIRST_MATCH 0 |
#define | GET_HEADER_LAST_MATCH 1 |
#define | GET_HEADER_SKIP_EMPTY 2 |
#define | MANAGER_EVENT_BUF_INITSIZE 256 |
#define | MAX_BLACKLIST_CMD_LEN 2 |
Descriptor for a manager session, either on the AMI socket or over HTTP. | |
#define | MSG_MOREDATA ((char *)astman_send_response) |
send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field. | |
Enumerations | |
enum | error_type { UNKNOWN_ACTION = 1, UNKNOWN_CATEGORY, UNSPECIFIED_CATEGORY, UNSPECIFIED_ARGUMENT, FAILURE_ALLOCATION, FAILURE_NEWCAT, FAILURE_DELCAT, FAILURE_EMPTYCAT, FAILURE_UPDATE, FAILURE_DELETE, FAILURE_APPEND } |
Functions | |
int | __ast_manager_event_multichan (int category, const char *event, int chancount, struct ast_channel **chans, const char *file, int line, const char *func, const char *fmt,...) |
static const char * | __astman_get_header (const struct message *m, char *var, int mode) |
static void | __init_astman_append_buf (void) |
thread local buffer for astman_append | |
static void | __init_manager_event_buf (void) |
static void | __init_manager_event_funcbuf (void) |
static void | __init_userevent_buf (void) |
static int | action_aocmessage (struct mansession *s, const struct message *m) |
static int | action_atxfer (struct mansession *s, const struct message *m) |
static int | action_challenge (struct mansession *s, const struct message *m) |
static int | action_command (struct mansession *s, const struct message *m) |
Manager command "command" - execute CLI command. | |
static int | action_coresettings (struct mansession *s, const struct message *m) |
Show PBX core settings information. | |
static int | action_coreshowchannels (struct mansession *s, const struct message *m) |
Manager command "CoreShowChannels" - List currently defined channels and some information about them. | |
static int | action_corestatus (struct mansession *s, const struct message *m) |
Show PBX core status information. | |
static int | action_createconfig (struct mansession *s, const struct message *m) |
static int | action_events (struct mansession *s, const struct message *m) |
static int | action_extensionstate (struct mansession *s, const struct message *m) |
static int | action_getconfig (struct mansession *s, const struct message *m) |
static int | action_getconfigjson (struct mansession *s, const struct message *m) |
static int | action_getvar (struct mansession *s, const struct message *m) |
static int | action_hangup (struct mansession *s, const struct message *m) |
static int | action_listcategories (struct mansession *s, const struct message *m) |
static int | action_listcommands (struct mansession *s, const struct message *m) |
static int | action_login (struct mansession *s, const struct message *m) |
static int | action_logoff (struct mansession *s, const struct message *m) |
static int | action_mailboxcount (struct mansession *s, const struct message *m) |
static int | action_mailboxstatus (struct mansession *s, const struct message *m) |
static int | action_originate (struct mansession *s, const struct message *m) |
static int | action_ping (struct mansession *s, const struct message *m) |
static int | action_redirect (struct mansession *s, const struct message *m) |
action_redirect: The redirect manager command | |
static int | action_reload (struct mansession *s, const struct message *m) |
Send a reload event. | |
static int | action_sendtext (struct mansession *s, const struct message *m) |
static int | action_setvar (struct mansession *s, const struct message *m) |
static int | action_status (struct mansession *s, const struct message *m) |
Manager "status" command to show channels. | |
static int | action_timeout (struct mansession *s, const struct message *m) |
static int | action_updateconfig (struct mansession *s, const struct message *m) |
static int | action_userevent (struct mansession *s, const struct message *m) |
static int | action_waitevent (struct mansession *s, const struct message *m) |
static struct eventqent * | advance_event (struct eventqent *e) |
static int | aocmessage_get_unit_entry (const struct message *m, struct ast_aoc_unit_entry *entry, unsigned int entry_num) |
static void | append_channel_vars (struct ast_str **pbuf, struct ast_channel *chan) |
static int | append_event (const char *str, int category) |
int | ast_hook_send_action (struct manager_custom_hook *hook, const char *msg) |
Registered hooks can call this function to invoke actions and they will receive responses through registered callback. | |
static int | ast_instring (const char *bigstr, const char *smallstr, const char delim) |
int | ast_manager_register2 (const char *action, int auth, int(*func)(struct mansession *s, const struct message *m), const char *synopsis, const char *description) |
Register a manager command with the manager interface. | |
void | ast_manager_register_hook (struct manager_custom_hook *hook) |
Add a custom hook to be called when an event is fired. | |
static int | ast_manager_register_struct (struct manager_action *act) |
int | ast_manager_unregister (char *action) |
Unregister a registered manager command. | |
void | ast_manager_unregister_hook (struct manager_custom_hook *hook) |
Delete a custom hook to be called when an event is fired. | |
void | astman_append (struct mansession *s, const char *fmt,...) |
const char * | astman_get_header (const struct message *m, char *var) |
Get header from mananger transaction. | |
ast_variable * | astman_get_variables (const struct message *m) |
Get a linked list of the Variable: headers. | |
void | astman_send_ack (struct mansession *s, const struct message *m, char *msg) |
Send ack in manager transaction. | |
void | astman_send_error (struct mansession *s, const struct message *m, char *error) |
Send error in manager transaction. | |
void | astman_send_listack (struct mansession *s, const struct message *m, char *msg, char *listflag) |
Send ack in manager list transaction. | |
void | astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg) |
Send response in manager transaction. | |
static void | astman_send_response_full (struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag) |
static void | astman_start_ack (struct mansession *s, const struct message *m) |
static int | authenticate (struct mansession *s, const struct message *m) |
static const char * | authority_to_str (int authority, struct ast_str **res) |
Convert authority code to a list of options. | |
static int | blackfilter_cmp_fn (void *obj, void *arg, void *data, int flags) |
static struct mansession_session * | build_mansession (struct sockaddr_in sin) |
Allocate manager session structure and add it to the list of sessions. | |
static int | check_blacklist (const char *cmd) |
int | check_manager_enabled () |
Check if AMI is enabled. | |
static int | check_manager_session_inuse (const char *name) |
int | check_webmanager_enabled () |
Check if AMI/HTTP is enabled. | |
static int | do_message (struct mansession *s) |
static void | event_filter_destructor (void *obj) |
static void * | fast_originate (void *data) |
static void | free_channelvars (void) |
static int | get_input (struct mansession *s, char *output) |
static struct ast_manager_user * | get_manager_by_name_locked (const char *name) |
static int | get_perm (const char *instr) |
static struct eventqent * | grab_last (void) |
static char * | handle_manager_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI command manager reload. | |
static char * | handle_mandebug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_showmanager (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_showmanagers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_showmancmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_showmancmds (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI command manager list commands. | |
static char * | handle_showmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI command manager list connected. | |
static char * | handle_showmaneventq (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI command manager list eventq. | |
static enum error_type | handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn) |
static void | json_escape (char *out, const char *in) |
static int | manager_displayconnects (struct mansession_session *session) |
Get displayconnects config option. | |
static int | manager_modulecheck (struct mansession *s, const struct message *m) |
static int | manager_moduleload (struct mansession *s, const struct message *m) |
static int | manager_state_cb (char *context, char *exten, int state, void *data) |
static int | mansession_cmp_fn (void *obj, void *arg, int flags) |
static struct sockaddr_in * | mansession_encode_sin_local (const struct mansession *s, struct sockaddr_in *sin_local) |
static enum ast_security_event_transport_type | mansession_get_transport (const struct mansession *s) |
static void | mansession_lock (struct mansession *s) |
Lock the 'mansession' structure. | |
static void | mansession_unlock (struct mansession *s) |
Unlock the 'mansession' structure. | |
static int | match_filter (struct mansession *s, char *eventdata) |
static int | process_events (struct mansession *s) |
static int | process_message (struct mansession *s, const struct message *m) |
static void | purge_events (void) |
static void | purge_sessions (int n_max) |
remove at most n_max stale session from the list. | |
static void | report_auth_success (const struct mansession *s) |
static void | report_failed_acl (const struct mansession *s, const char *username) |
static void | report_failed_challenge_response (const struct mansession *s, const char *response, const char *expected_response) |
static void | report_inval_password (const struct mansession *s, const char *username) |
static void | report_invalid_user (const struct mansession *s, const char *username) |
static void | report_req_bad_format (const struct mansession *s, const char *action) |
static void | report_req_not_allowed (const struct mansession *s, const char *action) |
static void | report_session_limit (const struct mansession *s) |
static int | send_string (struct mansession *s, char *string) |
static void | session_destroy (struct mansession_session *s) |
static void | session_destructor (void *obj) |
static void * | session_do (void *data) |
The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ). | |
static int | set_eventmask (struct mansession *s, const char *eventmask) |
Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm. | |
static int | strings_to_mask (const char *string) |
static struct mansession_session * | unref_mansession (struct mansession_session *s) |
Unreference manager session object. If no more references, then go ahead and delete it. | |
static int | whitefilter_cmp_fn (void *obj, void *arg, void *data, int flags) |
Variables | |
static int | allowmultiplelogin = 1 |
static struct ast_threadstorage | astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , } |
static int | authlimit |
static int | authtimeout |
static int | block_sockets |
static int | broken_events_action |
struct { | |
const char * words [AST_MAX_CMD_LEN] | |
} | command_blacklist [] |
static const int | DEFAULT_AUTHLIMIT = 50 |
static const int | DEFAULT_AUTHTIMEOUT = 30 |
static const int | DEFAULT_BLOCKSOCKETS = 0 |
static const int | DEFAULT_BROKENEVENTSACTION = 0 |
static const int | DEFAULT_DISPLAYCONNECTS = 1 |
static const int | DEFAULT_ENABLED = 0 |
static const int | DEFAULT_HTTPTIMEOUT = 60 |
static const int | DEFAULT_TIMESTAMPEVENTS = 0 |
static const int | DEFAULT_WEBENABLED = 0 |
static int | displayconnects |
static char | global_realm [MAXHOSTNAMELEN] |
static int | httptimeout |
static char * | manager_channelvars |
static int | manager_debug |
static int | manager_enabled = 0 |
static struct ast_threadstorage | manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , } |
static struct ast_threadstorage | manager_event_funcbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_funcbuf , .custom_init = NULL , } |
static struct permalias | perms [] |
static struct ao2_container * | sessions = NULL |
static int | timestampevents |
static int | unauth_sessions = 0 |
static struct ast_threadstorage | userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , } |
static int | webmanager_enabled = 0 |
#define ASTMAN_APPEND_BUF_INITSIZE 256 |
initial allocated size for the astman_append_buf
Definition at line 1879 of file manager.c.
Referenced by astman_append().
#define DEFAULT_REALM "asterisk" |
#define GET_HEADER_FIRST_MATCH 0 |
#define GET_HEADER_LAST_MATCH 1 |
#define GET_HEADER_SKIP_EMPTY 2 |
Definition at line 1708 of file manager.c.
Referenced by __astman_get_header(), and process_message().
#define MANAGER_EVENT_BUF_INITSIZE 256 |
#define MAX_BLACKLIST_CMD_LEN 2 |
Descriptor for a manager session, either on the AMI socket or over HTTP.
Definition at line 895 of file manager.c.
Referenced by check_blacklist().
#define MSG_MOREDATA ((char *)astman_send_response) |
send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field.
Use the explicit constant MSG_MOREDATA to remove the empty line. XXX MSG_MOREDATA should go to a header file.
Definition at line 1920 of file manager.c.
Referenced by astman_send_response_full(), and astman_start_ack().
enum error_type |
Doxygen group
UNKNOWN_ACTION | |
UNKNOWN_CATEGORY | |
UNSPECIFIED_CATEGORY | |
UNSPECIFIED_ARGUMENT | |
FAILURE_ALLOCATION | |
FAILURE_NEWCAT | |
FAILURE_DELCAT | |
FAILURE_EMPTYCAT | |
FAILURE_UPDATE | |
FAILURE_DELETE | |
FAILURE_APPEND |
Definition at line 811 of file manager.c.
00811 { 00812 UNKNOWN_ACTION = 1, 00813 UNKNOWN_CATEGORY, 00814 UNSPECIFIED_CATEGORY, 00815 UNSPECIFIED_ARGUMENT, 00816 FAILURE_ALLOCATION, 00817 FAILURE_NEWCAT, 00818 FAILURE_DELCAT, 00819 FAILURE_EMPTYCAT, 00820 FAILURE_UPDATE, 00821 FAILURE_DELETE, 00822 FAILURE_APPEND 00823 };
int __ast_manager_event_multichan | ( | int | category, | |
const char * | event, | |||
int | chancount, | |||
struct ast_channel ** | chans, | |||
const char * | file, | |||
int | line, | |||
const char * | func, | |||
const char * | contents, | |||
... | ||||
) |
External routines may send asterisk manager events this way
category | Event category, matches manager authorization | |
event | Event name | |
chancount | Number of channels in chans parameter | |
chans | A pointer to an array of channels involved in the event | |
contents | Format string describing event |
Definition at line 4833 of file manager.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, append_channel_vars(), append_event(), ast_atomic_fetchadd_int(), AST_PTHREADT_NULL, AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_str_append(), ast_str_append_va(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_tvnow(), authority_to_str(), manager_custom_hook::helper, manager_debug, manager_event_buf, MANAGER_EVENT_BUF_INITSIZE, seq, timestampevents, and unref_mansession().
04835 { 04836 struct mansession_session *session; 04837 struct manager_custom_hook *hook; 04838 struct ast_str *auth = ast_str_alloca(80); 04839 const char *cat_str; 04840 va_list ap; 04841 struct timeval now; 04842 struct ast_str *buf; 04843 int i; 04844 04845 if (!(sessions && ao2_container_count(sessions)) && AST_RWLIST_EMPTY(&manager_hooks)) { 04846 return 0; 04847 } 04848 04849 if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) { 04850 return -1; 04851 } 04852 04853 cat_str = authority_to_str(category, &auth); 04854 ast_str_set(&buf, 0, 04855 "Event: %s\r\nPrivilege: %s\r\n", 04856 event, cat_str); 04857 04858 if (timestampevents) { 04859 now = ast_tvnow(); 04860 ast_str_append(&buf, 0, 04861 "Timestamp: %ld.%06lu\r\n", 04862 (long)now.tv_sec, (unsigned long) now.tv_usec); 04863 } 04864 if (manager_debug) { 04865 static int seq; 04866 ast_str_append(&buf, 0, 04867 "SequenceNumber: %d\r\n", 04868 ast_atomic_fetchadd_int(&seq, 1)); 04869 ast_str_append(&buf, 0, 04870 "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func); 04871 } 04872 04873 va_start(ap, fmt); 04874 ast_str_append_va(&buf, 0, fmt, ap); 04875 va_end(ap); 04876 for (i = 0; i < chancount; i++) { 04877 append_channel_vars(&buf, chans[i]); 04878 } 04879 04880 ast_str_append(&buf, 0, "\r\n"); 04881 04882 append_event(ast_str_buffer(buf), category); 04883 04884 /* Wake up any sleeping sessions */ 04885 if (sessions) { 04886 struct ao2_iterator i; 04887 i = ao2_iterator_init(sessions, 0); 04888 while ((session = ao2_iterator_next(&i))) { 04889 ao2_lock(session); 04890 if (session->waiting_thread != AST_PTHREADT_NULL) { 04891 pthread_kill(session->waiting_thread, SIGURG); 04892 } else { 04893 /* We have an event to process, but the mansession is 04894 * not waiting for it. We still need to indicate that there 04895 * is an event waiting so that get_input processes the pending 04896 * event instead of polling. 04897 */ 04898 session->pending_event = 1; 04899 } 04900 ao2_unlock(session); 04901 unref_mansession(session); 04902 } 04903 ao2_iterator_destroy(&i); 04904 } 04905 04906 if (!AST_RWLIST_EMPTY(&manager_hooks)) { 04907 AST_RWLIST_RDLOCK(&manager_hooks); 04908 AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) { 04909 hook->helper(category, event, ast_str_buffer(buf)); 04910 } 04911 AST_RWLIST_UNLOCK(&manager_hooks); 04912 } 04913 04914 return 0; 04915 }
static const char* __astman_get_header | ( | const struct message * | m, | |
char * | var, | |||
int | mode | |||
) | [static] |
Definition at line 1709 of file manager.c.
References ast_skip_blanks(), ast_strlen_zero(), GET_HEADER_LAST_MATCH, GET_HEADER_SKIP_EMPTY, message::hdrcount, message::headers, and value.
Referenced by astman_get_header(), and process_message().
01710 { 01711 int x, l = strlen(var); 01712 const char *result = ""; 01713 01714 for (x = 0; x < m->hdrcount; x++) { 01715 const char *h = m->headers[x]; 01716 if (!strncasecmp(var, h, l) && h[l] == ':') { 01717 const char *value = h + l + 1; 01718 value = ast_skip_blanks(value); /* ignore leading spaces in the value */ 01719 /* found a potential candidate */ 01720 if (mode & GET_HEADER_SKIP_EMPTY && ast_strlen_zero(value)) 01721 continue; /* not interesting */ 01722 if (mode & GET_HEADER_LAST_MATCH) 01723 result = value; /* record the last match so far */ 01724 else 01725 return value; 01726 } 01727 } 01728 01729 return ""; 01730 }
static void __init_astman_append_buf | ( | void | ) | [static] |
thread local buffer for astman_append
Definition at line 1875 of file manager.c.
static void __init_manager_event_buf | ( | void | ) | [static] |
static void __init_manager_event_funcbuf | ( | void | ) | [static] |
static void __init_userevent_buf | ( | void | ) | [static] |
static int action_aocmessage | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3610 of file manager.c.
References ast_aoc_unit_entry::amount, aocmessage_get_unit_entry(), ast_aoc_add_unit_entry(), AST_AOC_BILLING_CALL_DEFLECTION, AST_AOC_BILLING_CALL_FWD_BUSY, AST_AOC_BILLING_CALL_FWD_NO_REPLY, AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL, AST_AOC_BILLING_CALL_TRANSFER, AST_AOC_BILLING_CREDIT_CARD, AST_AOC_BILLING_NA, AST_AOC_BILLING_NORMAL, AST_AOC_BILLING_REVERSE_CHARGE, AST_AOC_CHARGE_CURRENCY, AST_AOC_CHARGE_FREE, AST_AOC_CHARGE_NA, AST_AOC_CHARGE_UNIT, ast_aoc_create(), AST_AOC_D, ast_aoc_destroy_decoded(), ast_aoc_destroy_encoded(), AST_AOC_E, ast_aoc_encode(), AST_AOC_MULT_HUNDRED, AST_AOC_MULT_ONE, AST_AOC_MULT_ONEHUNDREDTH, AST_AOC_MULT_ONETENTH, AST_AOC_MULT_ONETHOUSANDTH, AST_AOC_MULT_TEN, AST_AOC_MULT_THOUSAND, ast_aoc_set_association_id(), ast_aoc_set_association_number(), ast_aoc_set_billing_id(), ast_aoc_set_currency_info(), ast_aoc_set_total_type(), AST_AOC_SUBTOTAL, AST_AOC_TOTAL, ast_channel_get_by_name(), ast_channel_get_by_name_prefix(), ast_channel_unref, AST_CONTROL_AOC, ast_indicate_data(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_aoc_unit_entry::type, ast_aoc_unit_entry::valid_amount, and ast_aoc_unit_entry::valid_type.
Referenced by __init_manager().
03611 { 03612 const char *channel = astman_get_header(m, "Channel"); 03613 const char *pchannel = astman_get_header(m, "ChannelPrefix"); 03614 const char *msgtype = astman_get_header(m, "MsgType"); 03615 const char *chargetype = astman_get_header(m, "ChargeType"); 03616 const char *currencyname = astman_get_header(m, "CurrencyName"); 03617 const char *currencyamount = astman_get_header(m, "CurrencyAmount"); 03618 const char *mult = astman_get_header(m, "CurrencyMultiplier"); 03619 const char *totaltype = astman_get_header(m, "TotalType"); 03620 const char *aocbillingid = astman_get_header(m, "AOCBillingId"); 03621 const char *association_id= astman_get_header(m, "ChargingAssociationId"); 03622 const char *association_num = astman_get_header(m, "ChargingAssociationNumber"); 03623 const char *association_plan = astman_get_header(m, "ChargingAssociationPlan"); 03624 03625 enum ast_aoc_type _msgtype; 03626 enum ast_aoc_charge_type _chargetype; 03627 enum ast_aoc_currency_multiplier _mult = AST_AOC_MULT_ONE; 03628 enum ast_aoc_total_type _totaltype = AST_AOC_TOTAL; 03629 enum ast_aoc_billing_id _billingid = AST_AOC_BILLING_NA; 03630 unsigned int _currencyamount = 0; 03631 int _association_id = 0; 03632 unsigned int _association_plan = 0; 03633 struct ast_channel *chan = NULL; 03634 03635 struct ast_aoc_decoded *decoded = NULL; 03636 struct ast_aoc_encoded *encoded = NULL; 03637 size_t encoded_size = 0; 03638 03639 if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) { 03640 astman_send_error(s, m, "Channel and PartialChannel are not specified. Specify at least one of these."); 03641 goto aocmessage_cleanup; 03642 } 03643 03644 if (!(chan = ast_channel_get_by_name(channel)) && !ast_strlen_zero(pchannel)) { 03645 chan = ast_channel_get_by_name_prefix(pchannel, strlen(pchannel)); 03646 } 03647 03648 if (!chan) { 03649 astman_send_error(s, m, "No such channel"); 03650 goto aocmessage_cleanup; 03651 } 03652 03653 if (ast_strlen_zero(msgtype) || (strcasecmp(msgtype, "d") && strcasecmp(msgtype, "e"))) { 03654 astman_send_error(s, m, "Invalid MsgType"); 03655 goto aocmessage_cleanup; 03656 } 03657 03658 if (ast_strlen_zero(chargetype)) { 03659 astman_send_error(s, m, "ChargeType not specified"); 03660 goto aocmessage_cleanup; 03661 } 03662 03663 _msgtype = strcasecmp(msgtype, "d") ? AST_AOC_E : AST_AOC_D; 03664 03665 if (!strcasecmp(chargetype, "NA")) { 03666 _chargetype = AST_AOC_CHARGE_NA; 03667 } else if (!strcasecmp(chargetype, "Free")) { 03668 _chargetype = AST_AOC_CHARGE_FREE; 03669 } else if (!strcasecmp(chargetype, "Currency")) { 03670 _chargetype = AST_AOC_CHARGE_CURRENCY; 03671 } else if (!strcasecmp(chargetype, "Unit")) { 03672 _chargetype = AST_AOC_CHARGE_UNIT; 03673 } else { 03674 astman_send_error(s, m, "Invalid ChargeType"); 03675 goto aocmessage_cleanup; 03676 } 03677 03678 if (_chargetype == AST_AOC_CHARGE_CURRENCY) { 03679 03680 if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u", &_currencyamount) != 1)) { 03681 astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency"); 03682 goto aocmessage_cleanup; 03683 } 03684 03685 if (ast_strlen_zero(mult)) { 03686 astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency."); 03687 goto aocmessage_cleanup; 03688 } else if (!strcasecmp(mult, "onethousandth")) { 03689 _mult = AST_AOC_MULT_ONETHOUSANDTH; 03690 } else if (!strcasecmp(mult, "onehundredth")) { 03691 _mult = AST_AOC_MULT_ONEHUNDREDTH; 03692 } else if (!strcasecmp(mult, "onetenth")) { 03693 _mult = AST_AOC_MULT_ONETENTH; 03694 } else if (!strcasecmp(mult, "one")) { 03695 _mult = AST_AOC_MULT_ONE; 03696 } else if (!strcasecmp(mult, "ten")) { 03697 _mult = AST_AOC_MULT_TEN; 03698 } else if (!strcasecmp(mult, "hundred")) { 03699 _mult = AST_AOC_MULT_HUNDRED; 03700 } else if (!strcasecmp(mult, "thousand")) { 03701 _mult = AST_AOC_MULT_THOUSAND; 03702 } else { 03703 astman_send_error(s, m, "Invalid ChargeMultiplier"); 03704 goto aocmessage_cleanup; 03705 } 03706 } 03707 03708 /* create decoded object and start setting values */ 03709 if (!(decoded = ast_aoc_create(_msgtype, _chargetype, 0))) { 03710 astman_send_error(s, m, "Message Creation Failed"); 03711 goto aocmessage_cleanup; 03712 } 03713 03714 if (_msgtype == AST_AOC_D) { 03715 if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype, "subtotal")) { 03716 _totaltype = AST_AOC_SUBTOTAL; 03717 } 03718 03719 if (ast_strlen_zero(aocbillingid)) { 03720 /* ignore this is optional */ 03721 } else if (!strcasecmp(aocbillingid, "Normal")) { 03722 _billingid = AST_AOC_BILLING_NORMAL; 03723 } else if (!strcasecmp(aocbillingid, "ReverseCharge")) { 03724 _billingid = AST_AOC_BILLING_REVERSE_CHARGE; 03725 } else if (!strcasecmp(aocbillingid, "CreditCard")) { 03726 _billingid = AST_AOC_BILLING_CREDIT_CARD; 03727 } else { 03728 astman_send_error(s, m, "Invalid AOC-D AOCBillingId"); 03729 goto aocmessage_cleanup; 03730 } 03731 } else { 03732 if (ast_strlen_zero(aocbillingid)) { 03733 /* ignore this is optional */ 03734 } else if (!strcasecmp(aocbillingid, "Normal")) { 03735 _billingid = AST_AOC_BILLING_NORMAL; 03736 } else if (!strcasecmp(aocbillingid, "ReverseCharge")) { 03737 _billingid = AST_AOC_BILLING_REVERSE_CHARGE; 03738 } else if (!strcasecmp(aocbillingid, "CreditCard")) { 03739 _billingid = AST_AOC_BILLING_CREDIT_CARD; 03740 } else if (!strcasecmp(aocbillingid, "CallFwdUnconditional")) { 03741 _billingid = AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL; 03742 } else if (!strcasecmp(aocbillingid, "CallFwdBusy")) { 03743 _billingid = AST_AOC_BILLING_CALL_FWD_BUSY; 03744 } else if (!strcasecmp(aocbillingid, "CallFwdNoReply")) { 03745 _billingid = AST_AOC_BILLING_CALL_FWD_NO_REPLY; 03746 } else if (!strcasecmp(aocbillingid, "CallDeflection")) { 03747 _billingid = AST_AOC_BILLING_CALL_DEFLECTION; 03748 } else if (!strcasecmp(aocbillingid, "CallTransfer")) { 03749 _billingid = AST_AOC_BILLING_CALL_TRANSFER; 03750 } else { 03751 astman_send_error(s, m, "Invalid AOC-E AOCBillingId"); 03752 goto aocmessage_cleanup; 03753 } 03754 03755 if (!ast_strlen_zero(association_id) && (sscanf(association_id, "%30d", &_association_id) != 1)) { 03756 astman_send_error(s, m, "Invalid ChargingAssociationId"); 03757 goto aocmessage_cleanup; 03758 } 03759 if (!ast_strlen_zero(association_plan) && (sscanf(association_plan, "%30u", &_association_plan) != 1)) { 03760 astman_send_error(s, m, "Invalid ChargingAssociationPlan"); 03761 goto aocmessage_cleanup; 03762 } 03763 03764 if (_association_id) { 03765 ast_aoc_set_association_id(decoded, _association_id); 03766 } else if (!ast_strlen_zero(association_num)) { 03767 ast_aoc_set_association_number(decoded, association_num, _association_plan); 03768 } 03769 } 03770 03771 if (_chargetype == AST_AOC_CHARGE_CURRENCY) { 03772 ast_aoc_set_currency_info(decoded, _currencyamount, _mult, ast_strlen_zero(currencyname) ? NULL : currencyname); 03773 } else if (_chargetype == AST_AOC_CHARGE_UNIT) { 03774 struct ast_aoc_unit_entry entry; 03775 int i; 03776 03777 /* multiple unit entries are possible, lets get them all */ 03778 for (i = 0; i < 32; i++) { 03779 if (aocmessage_get_unit_entry(m, &entry, i)) { 03780 break; /* that's the end then */ 03781 } 03782 03783 ast_aoc_add_unit_entry(decoded, entry.valid_amount, entry.amount, entry.valid_type, entry.type); 03784 } 03785 03786 /* at least one unit entry is required */ 03787 if (!i) { 03788 astman_send_error(s, m, "Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit"); 03789 goto aocmessage_cleanup; 03790 } 03791 03792 } 03793 03794 ast_aoc_set_billing_id(decoded, _billingid); 03795 ast_aoc_set_total_type(decoded, _totaltype); 03796 03797 03798 if ((encoded = ast_aoc_encode(decoded, &encoded_size, NULL)) && !ast_indicate_data(chan, AST_CONTROL_AOC, encoded, encoded_size)) { 03799 astman_send_ack(s, m, "AOC Message successfully queued on channel"); 03800 } else { 03801 astman_send_error(s, m, "Error encoding AOC message, could not queue onto channel"); 03802 } 03803 03804 aocmessage_cleanup: 03805 03806 ast_aoc_destroy_decoded(decoded); 03807 ast_aoc_destroy_encoded(encoded); 03808 03809 if (chan) { 03810 chan = ast_channel_unref(chan); 03811 } 03812 return 0; 03813 }
static int action_atxfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3377 of file manager.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_find_call_feature(), AST_FRAME_DTMF, ast_queue_frame(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), context, ast_call_feature::exten, exten, f, ast_frame_subclass::integer, name, pbx_builtin_setvar_helper(), and ast_frame::subclass.
Referenced by __init_manager().
03378 { 03379 const char *name = astman_get_header(m, "Channel"); 03380 const char *exten = astman_get_header(m, "Exten"); 03381 const char *context = astman_get_header(m, "Context"); 03382 struct ast_channel *chan = NULL; 03383 struct ast_call_feature *atxfer_feature = NULL; 03384 char *feature_code = NULL; 03385 03386 if (ast_strlen_zero(name)) { 03387 astman_send_error(s, m, "No channel specified"); 03388 return 0; 03389 } 03390 if (ast_strlen_zero(exten)) { 03391 astman_send_error(s, m, "No extension specified"); 03392 return 0; 03393 } 03394 03395 if (!(atxfer_feature = ast_find_call_feature("atxfer"))) { 03396 astman_send_error(s, m, "No attended transfer feature found"); 03397 return 0; 03398 } 03399 03400 if (!(chan = ast_channel_get_by_name(name))) { 03401 astman_send_error(s, m, "Channel specified does not exist"); 03402 return 0; 03403 } 03404 03405 if (!ast_strlen_zero(context)) { 03406 pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context); 03407 } 03408 03409 for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) { 03410 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code }; 03411 ast_queue_frame(chan, &f); 03412 } 03413 03414 for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) { 03415 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code }; 03416 ast_queue_frame(chan, &f); 03417 } 03418 03419 chan = ast_channel_unref(chan); 03420 03421 astman_send_ack(s, m, "Atxfer successfully queued"); 03422 03423 return 0; 03424 }
static int action_challenge | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2948 of file manager.c.
References ast_random(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), mansession_session::challenge, mansession_lock(), mansession_unlock(), and mansession::session.
Referenced by __init_manager().
02949 { 02950 const char *authtype = astman_get_header(m, "AuthType"); 02951 02952 if (!strcasecmp(authtype, "MD5")) { 02953 if (ast_strlen_zero(s->session->challenge)) { 02954 snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random()); 02955 } 02956 mansession_lock(s); 02957 astman_start_ack(s, m); 02958 astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge); 02959 mansession_unlock(s); 02960 } else { 02961 astman_send_error(s, m, "Must specify AuthType"); 02962 } 02963 return 0; 02964 }
static int action_command | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager command "command" - execute CLI command.
Definition at line 3462 of file manager.c.
References ast_calloc, ast_cli_command, ast_free, ast_log(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), check_blacklist(), errno, LOG_WARNING, S_OR, and term_strip().
Referenced by __init_manager().
03463 { 03464 const char *cmd = astman_get_header(m, "Command"); 03465 const char *id = astman_get_header(m, "ActionID"); 03466 char *buf, *final_buf; 03467 char template[] = "/tmp/ast-ami-XXXXXX"; /* template for temporary file */ 03468 int fd; 03469 off_t l; 03470 03471 if (ast_strlen_zero(cmd)) { 03472 astman_send_error(s, m, "No command provided"); 03473 return 0; 03474 } 03475 03476 if (check_blacklist(cmd)) { 03477 astman_send_error(s, m, "Command blacklisted"); 03478 return 0; 03479 } 03480 03481 fd = mkstemp(template); 03482 03483 astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n"); 03484 if (!ast_strlen_zero(id)) { 03485 astman_append(s, "ActionID: %s\r\n", id); 03486 } 03487 /* FIXME: Wedge a ActionID response in here, waiting for later changes */ 03488 ast_cli_command(fd, cmd); /* XXX need to change this to use a FILE * */ 03489 l = lseek(fd, 0, SEEK_END); /* how many chars available */ 03490 03491 /* This has a potential to overflow the stack. Hence, use the heap. */ 03492 buf = ast_calloc(1, l + 1); 03493 final_buf = ast_calloc(1, l + 1); 03494 if (buf) { 03495 lseek(fd, 0, SEEK_SET); 03496 if (read(fd, buf, l) < 0) { 03497 ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); 03498 } 03499 buf[l] = '\0'; 03500 if (final_buf) { 03501 term_strip(final_buf, buf, l); 03502 final_buf[l] = '\0'; 03503 } 03504 astman_append(s, "%s", S_OR(final_buf, buf)); 03505 ast_free(buf); 03506 } 03507 close(fd); 03508 unlink(template); 03509 astman_append(s, "--END COMMAND--\r\n\r\n"); 03510 if (final_buf) { 03511 ast_free(final_buf); 03512 } 03513 return 0; 03514 }
static int action_coresettings | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Show PBX core settings information.
Definition at line 4152 of file manager.c.
References AMI_VERSION, AST_CLI_YESNO, ast_config_AST_RUN_GROUP, ast_config_AST_RUN_USER, ast_config_AST_SYSTEM_NAME, ast_get_version(), ast_realtime_enabled(), ast_strlen_zero(), astman_append(), astman_get_header(), check_cdr_enabled(), check_webmanager_enabled(), option_maxcalls, option_maxfiles, and option_maxload.
Referenced by __init_manager().
04153 { 04154 const char *actionid = astman_get_header(m, "ActionID"); 04155 char idText[150]; 04156 04157 if (!ast_strlen_zero(actionid)) { 04158 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04159 } else { 04160 idText[0] = '\0'; 04161 } 04162 04163 astman_append(s, "Response: Success\r\n" 04164 "%s" 04165 "AMIversion: %s\r\n" 04166 "AsteriskVersion: %s\r\n" 04167 "SystemName: %s\r\n" 04168 "CoreMaxCalls: %d\r\n" 04169 "CoreMaxLoadAvg: %f\r\n" 04170 "CoreRunUser: %s\r\n" 04171 "CoreRunGroup: %s\r\n" 04172 "CoreMaxFilehandles: %d\r\n" 04173 "CoreRealTimeEnabled: %s\r\n" 04174 "CoreCDRenabled: %s\r\n" 04175 "CoreHTTPenabled: %s\r\n" 04176 "\r\n", 04177 idText, 04178 AMI_VERSION, 04179 ast_get_version(), 04180 ast_config_AST_SYSTEM_NAME, 04181 option_maxcalls, 04182 option_maxload, 04183 ast_config_AST_RUN_USER, 04184 ast_config_AST_RUN_GROUP, 04185 option_maxfiles, 04186 AST_CLI_YESNO(ast_realtime_enabled()), 04187 AST_CLI_YESNO(check_cdr_enabled()), 04188 AST_CLI_YESNO(check_webmanager_enabled()) 04189 ); 04190 return 0; 04191 }
static int action_coreshowchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager command "CoreShowChannels" - List currently defined channels and some information about them.
Definition at line 4249 of file manager.c.
References ast_channel::_state, ast_channel::accountcode, ast_channel::appl, ast_bridged_channel(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_state2str(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), astman_append(), astman_get_header(), astman_send_error(), astman_send_listack(), ast_channel::caller, ast_channel::cdr, ast_channel::context, ast_channel::data, ast_channel::exten, ast_party_caller::id, ast_channel::name, ast_party_id::number, ast_channel::priority, S_COR, S_OR, ast_cdr::start, ast_party_number::str, ast_channel::uniqueid, and ast_party_number::valid.
Referenced by __init_manager().
04250 { 04251 const char *actionid = astman_get_header(m, "ActionID"); 04252 char idText[256]; 04253 struct ast_channel *c = NULL; 04254 int numchans = 0; 04255 int duration, durh, durm, durs; 04256 struct ast_channel_iterator *iter; 04257 04258 if (!ast_strlen_zero(actionid)) { 04259 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04260 } else { 04261 idText[0] = '\0'; 04262 } 04263 04264 if (!(iter = ast_channel_iterator_all_new())) { 04265 astman_send_error(s, m, "Memory Allocation Failure"); 04266 return 1; 04267 } 04268 04269 astman_send_listack(s, m, "Channels will follow", "start"); 04270 04271 for (; (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) { 04272 struct ast_channel *bc; 04273 char durbuf[10] = ""; 04274 04275 ast_channel_lock(c); 04276 04277 bc = ast_bridged_channel(c); 04278 if (c->cdr && !ast_tvzero(c->cdr->start)) { 04279 duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000); 04280 durh = duration / 3600; 04281 durm = (duration % 3600) / 60; 04282 durs = duration % 60; 04283 snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs); 04284 } 04285 04286 astman_append(s, 04287 "Event: CoreShowChannel\r\n" 04288 "%s" 04289 "Channel: %s\r\n" 04290 "UniqueID: %s\r\n" 04291 "Context: %s\r\n" 04292 "Extension: %s\r\n" 04293 "Priority: %d\r\n" 04294 "ChannelState: %d\r\n" 04295 "ChannelStateDesc: %s\r\n" 04296 "Application: %s\r\n" 04297 "ApplicationData: %s\r\n" 04298 "CallerIDnum: %s\r\n" 04299 "Duration: %s\r\n" 04300 "AccountCode: %s\r\n" 04301 "BridgedChannel: %s\r\n" 04302 "BridgedUniqueID: %s\r\n" 04303 "\r\n", idText, c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state, 04304 ast_state2str(c->_state), c->appl ? c->appl : "", c->data ? S_OR(c->data, "") : "", 04305 S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""), 04306 durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : ""); 04307 04308 ast_channel_unlock(c); 04309 04310 numchans++; 04311 } 04312 04313 astman_append(s, 04314 "Event: CoreShowChannelsComplete\r\n" 04315 "EventList: Complete\r\n" 04316 "ListItems: %d\r\n" 04317 "%s" 04318 "\r\n", numchans, idText); 04319 04320 ast_channel_iterator_destroy(iter); 04321 04322 return 0; 04323 }
static int action_corestatus | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Show PBX core status information.
Definition at line 4194 of file manager.c.
References ast_active_channels(), ast_lastreloadtime, ast_localtime(), ast_startuptime, ast_strftime(), ast_strlen_zero(), astman_append(), and astman_get_header().
Referenced by __init_manager().
04195 { 04196 const char *actionid = astman_get_header(m, "ActionID"); 04197 char idText[150]; 04198 char startuptime[150], startupdate[150]; 04199 char reloadtime[150], reloaddate[150]; 04200 struct ast_tm tm; 04201 04202 if (!ast_strlen_zero(actionid)) { 04203 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04204 } else { 04205 idText[0] = '\0'; 04206 } 04207 04208 ast_localtime(&ast_startuptime, &tm, NULL); 04209 ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm); 04210 ast_strftime(startupdate, sizeof(startupdate), "%Y-%m-%d", &tm); 04211 ast_localtime(&ast_lastreloadtime, &tm, NULL); 04212 ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm); 04213 ast_strftime(reloaddate, sizeof(reloaddate), "%Y-%m-%d", &tm); 04214 04215 astman_append(s, "Response: Success\r\n" 04216 "%s" 04217 "CoreStartupDate: %s\r\n" 04218 "CoreStartupTime: %s\r\n" 04219 "CoreReloadDate: %s\r\n" 04220 "CoreReloadTime: %s\r\n" 04221 "CoreCurrentCalls: %d\r\n" 04222 "\r\n", 04223 idText, 04224 startupdate, 04225 startuptime, 04226 reloaddate, 04227 reloadtime, 04228 ast_active_channels() 04229 ); 04230 return 0; 04231 }
static int action_createconfig | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2738 of file manager.c.
References ast_config_AST_CONFIG_DIR, AST_FILE_MODE, ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_set(), astman_get_header(), astman_send_ack(), astman_send_error(), and errno.
Referenced by __init_manager().
02739 { 02740 int fd; 02741 const char *fn = astman_get_header(m, "Filename"); 02742 struct ast_str *filepath = ast_str_alloca(PATH_MAX); 02743 ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR); 02744 ast_str_append(&filepath, 0, "%s", fn); 02745 02746 if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) { 02747 close(fd); 02748 astman_send_ack(s, m, "New configuration file created successfully"); 02749 } else { 02750 astman_send_error(s, m, strerror(errno)); 02751 } 02752 02753 return 0; 02754 }
static int action_events | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2880 of file manager.c.
References ARRAY_LEN, astman_append(), astman_get_header(), astman_send_error(), broken_events_action, perms, and set_eventmask().
Referenced by __init_manager().
02881 { 02882 const char *mask = astman_get_header(m, "EventMask"); 02883 int res, x; 02884 02885 res = set_eventmask(s, mask); 02886 if (broken_events_action) { 02887 /* if this option is set we should not return a response on 02888 * error, or when all events are set */ 02889 02890 if (res > 0) { 02891 for (x = 0; x < ARRAY_LEN(perms); x++) { 02892 if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) { 02893 return 0; 02894 } 02895 } 02896 astman_append(s, "Response: Success\r\n" 02897 "Events: On\r\n\r\n"); 02898 } else if (res == 0) 02899 astman_append(s, "Response: Success\r\n" 02900 "Events: Off\r\n\r\n"); 02901 return 0; 02902 } 02903 02904 if (res > 0) 02905 astman_append(s, "Response: Success\r\n" 02906 "Events: On\r\n\r\n"); 02907 else if (res == 0) 02908 astman_append(s, "Response: Success\r\n" 02909 "Events: Off\r\n\r\n"); 02910 else 02911 astman_send_error(s, m, "Invalid event mask"); 02912 02913 return 0; 02914 }
static int action_extensionstate | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3991 of file manager.c.
References ast_extension_state(), ast_get_hint(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), context, exten, and status.
Referenced by __init_manager().
03992 { 03993 const char *exten = astman_get_header(m, "Exten"); 03994 const char *context = astman_get_header(m, "Context"); 03995 char hint[256] = ""; 03996 int status; 03997 if (ast_strlen_zero(exten)) { 03998 astman_send_error(s, m, "Extension not specified"); 03999 return 0; 04000 } 04001 if (ast_strlen_zero(context)) { 04002 context = "default"; 04003 } 04004 status = ast_extension_state(NULL, context, exten); 04005 ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten); 04006 astman_start_ack(s, m); 04007 astman_append(s, "Message: Extension Status\r\n" 04008 "Exten: %s\r\n" 04009 "Context: %s\r\n" 04010 "Hint: %s\r\n" 04011 "Status: %d\r\n\r\n", 04012 exten, context, hint, status); 04013 return 0; 04014 }
static int action_getconfig | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2353 of file manager.c.
References ast_category_browse(), ast_config_destroy(), ast_config_load2(), ast_strlen_zero(), ast_variable_browse(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by __init_manager().
02354 { 02355 struct ast_config *cfg; 02356 const char *fn = astman_get_header(m, "Filename"); 02357 const char *category = astman_get_header(m, "Category"); 02358 int catcount = 0; 02359 int lineno = 0; 02360 char *cur_category = NULL; 02361 struct ast_variable *v; 02362 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02363 02364 if (ast_strlen_zero(fn)) { 02365 astman_send_error(s, m, "Filename not specified"); 02366 return 0; 02367 } 02368 cfg = ast_config_load2(fn, "manager", config_flags); 02369 if (cfg == CONFIG_STATUS_FILEMISSING) { 02370 astman_send_error(s, m, "Config file not found"); 02371 return 0; 02372 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02373 astman_send_error(s, m, "Config file has invalid format"); 02374 return 0; 02375 } 02376 02377 astman_start_ack(s, m); 02378 while ((cur_category = ast_category_browse(cfg, cur_category))) { 02379 if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) { 02380 lineno = 0; 02381 astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category); 02382 for (v = ast_variable_browse(cfg, cur_category); v; v = v->next) { 02383 astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value); 02384 } 02385 catcount++; 02386 } 02387 } 02388 if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */ 02389 astman_append(s, "No categories found\r\n"); 02390 } 02391 ast_config_destroy(cfg); 02392 astman_append(s, "\r\n"); 02393 02394 return 0; 02395 }
static int action_getconfigjson | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2445 of file manager.c.
References ast_category_browse(), ast_config_load2(), ast_strlen_zero(), ast_variable_browse(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, config_flags, CONFIG_STATUS_FILEINVALID, json_escape(), ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by __init_manager().
02446 { 02447 struct ast_config *cfg; 02448 const char *fn = astman_get_header(m, "Filename"); 02449 char *category = NULL; 02450 struct ast_variable *v; 02451 int comma1 = 0; 02452 char *buf = NULL; 02453 unsigned int buf_len = 0; 02454 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02455 02456 if (ast_strlen_zero(fn)) { 02457 astman_send_error(s, m, "Filename not specified"); 02458 return 0; 02459 } 02460 02461 if (!(cfg = ast_config_load2(fn, "manager", config_flags))) { 02462 astman_send_error(s, m, "Config file not found"); 02463 return 0; 02464 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02465 astman_send_error(s, m, "Config file has invalid format"); 02466 return 0; 02467 } 02468 02469 buf_len = 512; 02470 buf = alloca(buf_len); 02471 02472 astman_start_ack(s, m); 02473 astman_append(s, "JSON: {"); 02474 while ((category = ast_category_browse(cfg, category))) { 02475 int comma2 = 0; 02476 if (buf_len < 2 * strlen(category) + 1) { 02477 buf_len *= 2; 02478 buf = alloca(buf_len); 02479 } 02480 json_escape(buf, category); 02481 astman_append(s, "%s\"%s\":[", comma1 ? "," : "", buf); 02482 if (!comma1) { 02483 comma1 = 1; 02484 } 02485 for (v = ast_variable_browse(cfg, category); v; v = v->next) { 02486 if (comma2) { 02487 astman_append(s, ","); 02488 } 02489 if (buf_len < 2 * strlen(v->name) + 1) { 02490 buf_len *= 2; 02491 buf = alloca(buf_len); 02492 } 02493 json_escape(buf, v->name); 02494 astman_append(s, "\"%s", buf); 02495 if (buf_len < 2 * strlen(v->value) + 1) { 02496 buf_len *= 2; 02497 buf = alloca(buf_len); 02498 } 02499 json_escape(buf, v->value); 02500 astman_append(s, "%s\"", buf); 02501 if (!comma2) { 02502 comma2 = 1; 02503 } 02504 } 02505 astman_append(s, "]"); 02506 } 02507 astman_append(s, "}\r\n\r\n"); 02508 02509 ast_config_destroy(cfg); 02510 02511 return 0; 02512 }
static int action_getvar | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3042 of file manager.c.
References ast_channel_get_by_name(), ast_channel_release(), ast_channel_unref, ast_dummy_channel_alloc(), ast_func_read(), ast_log(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), LOG_ERROR, name, pbx_retrieve_variable(), and S_OR.
Referenced by __init_manager().
03043 { 03044 struct ast_channel *c = NULL; 03045 const char *name = astman_get_header(m, "Channel"); 03046 const char *varname = astman_get_header(m, "Variable"); 03047 char *varval; 03048 char workspace[1024] = ""; 03049 03050 if (ast_strlen_zero(varname)) { 03051 astman_send_error(s, m, "No variable specified"); 03052 return 0; 03053 } 03054 03055 if (!ast_strlen_zero(name)) { 03056 if (!(c = ast_channel_get_by_name(name))) { 03057 astman_send_error(s, m, "No such channel"); 03058 return 0; 03059 } 03060 } 03061 03062 if (varname[strlen(varname) - 1] == ')') { 03063 if (!c) { 03064 c = ast_dummy_channel_alloc(); 03065 if (c) { 03066 ast_func_read(c, (char *) varname, workspace, sizeof(workspace)); 03067 c = ast_channel_release(c); 03068 } else 03069 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03070 } else { 03071 ast_func_read(c, (char *) varname, workspace, sizeof(workspace)); 03072 } 03073 varval = workspace; 03074 } else { 03075 pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL); 03076 } 03077 03078 if (c) { 03079 c = ast_channel_unref(c); 03080 } 03081 03082 astman_start_ack(s, m); 03083 astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, S_OR(varval, "")); 03084 03085 return 0; 03086 }
static int action_hangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2966 of file manager.c.
References ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_debug, ast_log(), AST_SOFTHANGUP_EXPLICIT, ast_softhangup_nolock(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), cause, ast_channel::hangupcause, LOG_NOTICE, ast_channel::name, and name.
Referenced by __init_manager().
02967 { 02968 struct ast_channel *c = NULL; 02969 int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */ 02970 const char *name = astman_get_header(m, "Channel"); 02971 const char *cause = astman_get_header(m, "Cause"); 02972 02973 if (ast_strlen_zero(name)) { 02974 astman_send_error(s, m, "No channel specified"); 02975 return 0; 02976 } 02977 02978 if (!ast_strlen_zero(cause)) { 02979 char *endptr; 02980 causecode = strtol(cause, &endptr, 10); 02981 if (causecode < 0 || causecode > 127 || *endptr != '\0') { 02982 ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause); 02983 /* keep going, better to hangup without cause than to not hang up at all */ 02984 causecode = 0; /* do not set channel's hangupcause */ 02985 } 02986 } 02987 02988 if (!(c = ast_channel_get_by_name(name))) { 02989 astman_send_error(s, m, "No such channel"); 02990 return 0; 02991 } 02992 02993 ast_channel_lock(c); 02994 if (causecode > 0) { 02995 ast_debug(1, "Setting hangupcause of channel %s to %d (is %d now)\n", 02996 c->name, causecode, c->hangupcause); 02997 c->hangupcause = causecode; 02998 } 02999 ast_softhangup_nolock(c, AST_SOFTHANGUP_EXPLICIT); 03000 ast_channel_unlock(c); 03001 03002 c = ast_channel_unref(c); 03003 03004 astman_send_ack(s, m, "Channel Hungup"); 03005 03006 return 0; 03007 }
static int action_listcategories | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2397 of file manager.c.
References ast_category_browse(), ast_config_destroy(), ast_config_load2(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, config_flags, and CONFIG_STATUS_FILEINVALID.
Referenced by __init_manager().
02398 { 02399 struct ast_config *cfg; 02400 const char *fn = astman_get_header(m, "Filename"); 02401 char *category = NULL; 02402 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02403 int catcount = 0; 02404 02405 if (ast_strlen_zero(fn)) { 02406 astman_send_error(s, m, "Filename not specified"); 02407 return 0; 02408 } 02409 if (!(cfg = ast_config_load2(fn, "manager", config_flags))) { 02410 astman_send_error(s, m, "Config file not found"); 02411 return 0; 02412 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02413 astman_send_error(s, m, "Config file has invalid format"); 02414 return 0; 02415 } 02416 astman_start_ack(s, m); 02417 while ((category = ast_category_browse(cfg, category))) { 02418 astman_append(s, "Category-%06d: %s\r\n", catcount, category); 02419 catcount++; 02420 } 02421 if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */ 02422 astman_append(s, "Error: no categories found\r\n"); 02423 } 02424 ast_config_destroy(cfg); 02425 astman_append(s, "\r\n"); 02426 02427 return 0; 02428 }
static int action_listcommands | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2863 of file manager.c.
References manager_action::action, AST_RWLIST_TRAVERSE, ast_str_alloca, astman_append(), astman_start_ack(), manager_action::authority, authority_to_str(), mansession::session, and mansession_session::writeperm.
Referenced by __init_manager().
02864 { 02865 struct manager_action *cur; 02866 struct ast_str *temp = ast_str_alloca(BUFSIZ); /* XXX very large ? */ 02867 02868 astman_start_ack(s, m); 02869 AST_RWLIST_TRAVERSE(&actions, cur, list) { 02870 if (s->session->writeperm & cur->authority || cur->authority == 0) { 02871 astman_append(s, "%s: %s (Priv: %s)\r\n", 02872 cur->action, cur->synopsis, authority_to_str(cur->authority, &temp)); 02873 } 02874 } 02875 astman_append(s, "\r\n"); 02876 02877 return 0; 02878 }
static int action_login | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2922 of file manager.c.
References ast_atomic_fetchadd_int(), ast_inet_ntoa(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, ast_test_flag, ast_verb, astman_send_ack(), astman_send_error(), authenticate(), mansession_session::authenticated, EVENT_FLAG_SYSTEM, manager_displayconnects(), manager_event, mansession_session::managerid, mansession::session, mansession_session::sin, unauth_sessions, and mansession_session::username.
Referenced by __init_manager().
02923 { 02924 02925 /* still authenticated - don't process again */ 02926 if (s->session->authenticated) { 02927 astman_send_ack(s, m, "Already authenticated"); 02928 return 0; 02929 } 02930 02931 if (authenticate(s, m)) { 02932 sleep(1); 02933 astman_send_error(s, m, "Authentication failed"); 02934 return -1; 02935 } 02936 s->session->authenticated = 1; 02937 ast_atomic_fetchadd_int(&unauth_sessions, -1); 02938 if (manager_displayconnects(s->session)) { 02939 ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr)); 02940 } 02941 astman_send_ack(s, m, "Authentication accepted"); 02942 if (ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 02943 manager_event(EVENT_FLAG_SYSTEM, "FullyBooted", "Status: Fully Booted\r\n"); 02944 } 02945 return 0; 02946 }
static int action_logoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2916 of file manager.c.
References astman_send_response().
Referenced by __init_manager().
02917 { 02918 astman_send_response(s, m, "Goodbye", "Thanks for all the fish."); 02919 return -1; 02920 }
static int action_mailboxcount | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3970 of file manager.c.
References ast_app_inboxcount2(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), and mailbox.
Referenced by __init_manager().
03971 { 03972 const char *mailbox = astman_get_header(m, "Mailbox"); 03973 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;; 03974 03975 if (ast_strlen_zero(mailbox)) { 03976 astman_send_error(s, m, "Mailbox not specified"); 03977 return 0; 03978 } 03979 ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs); 03980 astman_start_ack(s, m); 03981 astman_append(s, "Message: Mailbox Message Count\r\n" 03982 "Mailbox: %s\r\n" 03983 "UrgMessages: %d\r\n" 03984 "NewMessages: %d\r\n" 03985 "OldMessages: %d\r\n" 03986 "\r\n", 03987 mailbox, urgentmsgs, newmsgs, oldmsgs); 03988 return 0; 03989 }
static int action_mailboxstatus | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3953 of file manager.c.
References ast_app_has_voicemail(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), and mailbox.
Referenced by __init_manager().
03954 { 03955 const char *mailbox = astman_get_header(m, "Mailbox"); 03956 int ret; 03957 03958 if (ast_strlen_zero(mailbox)) { 03959 astman_send_error(s, m, "Mailbox not specified"); 03960 return 0; 03961 } 03962 ret = ast_app_has_voicemail(mailbox, NULL); 03963 astman_start_ack(s, m); 03964 astman_append(s, "Message: Mailbox Status\r\n" 03965 "Mailbox: %s\r\n" 03966 "Waiting: %d\r\n\r\n", mailbox, ret); 03967 return 0; 03968 }
static int action_originate | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3815 of file manager.c.
References app, ast_callerid_parse(), ast_calloc, ast_copy_string(), ast_findlabel_extension(), AST_FORMAT_SLINEAR, ast_free, ast_parse_allow_disallow(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_pthread_create_detached, ast_shrink_phone_number(), ast_strlen_zero(), ast_true(), ast_variables_destroy(), astman_get_header(), astman_get_variables(), astman_send_ack(), astman_send_error(), context, ast_frame::data, EVENT_FLAG_SYSTEM, exten, fast_originate(), format, name, mansession::session, strcasestr(), and mansession_session::writeperm.
Referenced by __init_manager().
03816 { 03817 const char *name = astman_get_header(m, "Channel"); 03818 const char *exten = astman_get_header(m, "Exten"); 03819 const char *context = astman_get_header(m, "Context"); 03820 const char *priority = astman_get_header(m, "Priority"); 03821 const char *timeout = astman_get_header(m, "Timeout"); 03822 const char *callerid = astman_get_header(m, "CallerID"); 03823 const char *account = astman_get_header(m, "Account"); 03824 const char *app = astman_get_header(m, "Application"); 03825 const char *appdata = astman_get_header(m, "Data"); 03826 const char *async = astman_get_header(m, "Async"); 03827 const char *id = astman_get_header(m, "ActionID"); 03828 const char *codecs = astman_get_header(m, "Codecs"); 03829 struct ast_variable *vars; 03830 char *tech, *data; 03831 char *l = NULL, *n = NULL; 03832 int pi = 0; 03833 int res; 03834 int to = 30000; 03835 int reason = 0; 03836 char tmp[256]; 03837 char tmp2[256]; 03838 format_t format = AST_FORMAT_SLINEAR; 03839 03840 pthread_t th; 03841 if (ast_strlen_zero(name)) { 03842 astman_send_error(s, m, "Channel not specified"); 03843 return 0; 03844 } 03845 if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) { 03846 if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) { 03847 astman_send_error(s, m, "Invalid priority"); 03848 return 0; 03849 } 03850 } 03851 if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) { 03852 astman_send_error(s, m, "Invalid timeout"); 03853 return 0; 03854 } 03855 ast_copy_string(tmp, name, sizeof(tmp)); 03856 tech = tmp; 03857 data = strchr(tmp, '/'); 03858 if (!data) { 03859 astman_send_error(s, m, "Invalid channel"); 03860 return 0; 03861 } 03862 *data++ = '\0'; 03863 ast_copy_string(tmp2, callerid, sizeof(tmp2)); 03864 ast_callerid_parse(tmp2, &n, &l); 03865 if (n) { 03866 if (ast_strlen_zero(n)) { 03867 n = NULL; 03868 } 03869 } 03870 if (l) { 03871 ast_shrink_phone_number(l); 03872 if (ast_strlen_zero(l)) { 03873 l = NULL; 03874 } 03875 } 03876 if (!ast_strlen_zero(codecs)) { 03877 format = 0; 03878 ast_parse_allow_disallow(NULL, &format, codecs, 1); 03879 } 03880 if (!ast_strlen_zero(app)) { 03881 /* To run the System application (or anything else that goes to 03882 * shell), you must have the additional System privilege */ 03883 if (!(s->session->writeperm & EVENT_FLAG_SYSTEM) 03884 && ( 03885 strcasestr(app, "system") || /* System(rm -rf /) 03886 TrySystem(rm -rf /) */ 03887 strcasestr(app, "exec") || /* Exec(System(rm -rf /)) 03888 TryExec(System(rm -rf /)) */ 03889 strcasestr(app, "agi") || /* AGI(/bin/rm,-rf /) 03890 EAGI(/bin/rm,-rf /) */ 03891 strstr(appdata, "SHELL") || /* NoOp(${SHELL(rm -rf /)}) */ 03892 strstr(appdata, "EVAL") /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ 03893 )) { 03894 astman_send_error(s, m, "Originate with certain 'Application' arguments requires the additional System privilege, which you do not have."); 03895 return 0; 03896 } 03897 } 03898 /* Allocate requested channel variables */ 03899 vars = astman_get_variables(m); 03900 03901 if (ast_true(async)) { 03902 struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast)); 03903 if (!fast) { 03904 res = -1; 03905 } else { 03906 if (!ast_strlen_zero(id)) 03907 snprintf(fast->idtext, sizeof(fast->idtext), "ActionID: %s", id); 03908 ast_copy_string(fast->tech, tech, sizeof(fast->tech)); 03909 ast_copy_string(fast->data, data, sizeof(fast->data)); 03910 ast_copy_string(fast->app, app, sizeof(fast->app)); 03911 ast_copy_string(fast->appdata, appdata, sizeof(fast->appdata)); 03912 if (l) { 03913 ast_copy_string(fast->cid_num, l, sizeof(fast->cid_num)); 03914 } 03915 if (n) { 03916 ast_copy_string(fast->cid_name, n, sizeof(fast->cid_name)); 03917 } 03918 fast->vars = vars; 03919 ast_copy_string(fast->context, context, sizeof(fast->context)); 03920 ast_copy_string(fast->exten, exten, sizeof(fast->exten)); 03921 ast_copy_string(fast->account, account, sizeof(fast->account)); 03922 fast->format = format; 03923 fast->timeout = to; 03924 fast->priority = pi; 03925 if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) { 03926 ast_free(fast); 03927 res = -1; 03928 } else { 03929 res = 0; 03930 } 03931 } 03932 } else if (!ast_strlen_zero(app)) { 03933 res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL); 03934 } else { 03935 if (exten && context && pi) { 03936 res = ast_pbx_outgoing_exten(tech, format, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL); 03937 } else { 03938 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'"); 03939 if (vars) { 03940 ast_variables_destroy(vars); 03941 } 03942 return 0; 03943 } 03944 } 03945 if (!res) { 03946 astman_send_ack(s, m, "Originate successfully queued"); 03947 } else { 03948 astman_send_error(s, m, "Originate failed"); 03949 } 03950 return 0; 03951 }
static int action_ping | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2335 of file manager.c.
References ast_strlen_zero(), ast_tvnow(), astman_append(), and astman_get_header().
Referenced by __init_manager().
02336 { 02337 const char *actionid = astman_get_header(m, "ActionID"); 02338 struct timeval now = ast_tvnow(); 02339 02340 astman_append(s, "Response: Success\r\n"); 02341 if (!ast_strlen_zero(actionid)){ 02342 astman_append(s, "ActionID: %s\r\n", actionid); 02343 } 02344 astman_append( 02345 s, 02346 "Ping: Pong\r\n" 02347 "Timestamp: %ld.%06lu\r\n" 02348 "\r\n", 02349 (long) now.tv_sec, (unsigned long) now.tv_usec); 02350 return 0; 02351 }
static int action_redirect | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
action_redirect: The redirect manager command
Definition at line 3274 of file manager.c.
References ast_async_goto(), ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_check_hangup_locked(), ast_findlabel_extension(), AST_FLAG_BRIDGE_HANGUP_DONT, ast_set_flag, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), context, exten, name, ast_channel::pbx, and ast_channel::priority.
Referenced by __init_manager().
03275 { 03276 const char *name = astman_get_header(m, "Channel"); 03277 const char *name2 = astman_get_header(m, "ExtraChannel"); 03278 const char *exten = astman_get_header(m, "Exten"); 03279 const char *exten2 = astman_get_header(m, "ExtraExten"); 03280 const char *context = astman_get_header(m, "Context"); 03281 const char *context2 = astman_get_header(m, "ExtraContext"); 03282 const char *priority = astman_get_header(m, "Priority"); 03283 const char *priority2 = astman_get_header(m, "ExtraPriority"); 03284 struct ast_channel *chan, *chan2 = NULL; 03285 int pi, pi2 = 0; 03286 int res; 03287 03288 if (ast_strlen_zero(name)) { 03289 astman_send_error(s, m, "Channel not specified"); 03290 return 0; 03291 } 03292 03293 if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) { 03294 if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) { 03295 astman_send_error(s, m, "Invalid priority"); 03296 return 0; 03297 } 03298 } 03299 03300 if (!ast_strlen_zero(priority2) && (sscanf(priority2, "%30d", &pi2) != 1)) { 03301 if ((pi2 = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL)) < 1) { 03302 astman_send_error(s, m, "Invalid ExtraPriority"); 03303 return 0; 03304 } 03305 } 03306 03307 if (!(chan = ast_channel_get_by_name(name))) { 03308 char buf[256]; 03309 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name); 03310 astman_send_error(s, m, buf); 03311 return 0; 03312 } 03313 03314 if (ast_check_hangup_locked(chan)) { 03315 astman_send_error(s, m, "Redirect failed, channel not up."); 03316 chan = ast_channel_unref(chan); 03317 return 0; 03318 } 03319 03320 if (!ast_strlen_zero(name2)) { 03321 chan2 = ast_channel_get_by_name(name2); 03322 } 03323 03324 if (chan2 && ast_check_hangup_locked(chan2)) { 03325 astman_send_error(s, m, "Redirect failed, extra channel not up."); 03326 chan = ast_channel_unref(chan); 03327 chan2 = ast_channel_unref(chan2); 03328 return 0; 03329 } 03330 03331 if (chan->pbx) { 03332 ast_channel_lock(chan); 03333 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */ 03334 ast_channel_unlock(chan); 03335 } 03336 03337 res = ast_async_goto(chan, context, exten, pi); 03338 if (!res) { 03339 if (!ast_strlen_zero(name2)) { 03340 if (chan2) { 03341 if (chan2->pbx) { 03342 ast_channel_lock(chan2); 03343 ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */ 03344 ast_channel_unlock(chan2); 03345 } 03346 if (context2) { 03347 res = ast_async_goto(chan2, context2, exten2, pi2); 03348 } else { 03349 res = ast_async_goto(chan2, context, exten, pi); 03350 } 03351 } else { 03352 res = -1; 03353 } 03354 if (!res) { 03355 astman_send_ack(s, m, "Dual Redirect successful"); 03356 } else { 03357 astman_send_error(s, m, "Secondary redirect failed"); 03358 } 03359 } else { 03360 astman_send_ack(s, m, "Redirect successful"); 03361 } 03362 } else { 03363 astman_send_error(s, m, "Redirect failed"); 03364 } 03365 03366 if (chan) { 03367 chan = ast_channel_unref(chan); 03368 } 03369 03370 if (chan2) { 03371 chan2 = ast_channel_unref(chan2); 03372 } 03373 03374 return 0; 03375 }
static int action_reload | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Send a reload event.
Definition at line 4234 of file manager.c.
References ast_module_reload(), astman_get_header(), astman_send_ack(), astman_send_error(), and S_OR.
Referenced by __init_manager().
04235 { 04236 const char *module = astman_get_header(m, "Module"); 04237 int res = ast_module_reload(S_OR(module, NULL)); 04238 04239 if (res == 2) { 04240 astman_send_ack(s, m, "Module Reloaded"); 04241 } else { 04242 astman_send_error(s, m, s == 0 ? "No such module" : "Module does not support reload"); 04243 } 04244 return 0; 04245 }
static int action_sendtext | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3239 of file manager.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_sendtext(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and name.
Referenced by __init_manager().
03240 { 03241 struct ast_channel *c = NULL; 03242 const char *name = astman_get_header(m, "Channel"); 03243 const char *textmsg = astman_get_header(m, "Message"); 03244 int res = 0; 03245 03246 if (ast_strlen_zero(name)) { 03247 astman_send_error(s, m, "No channel specified"); 03248 return 0; 03249 } 03250 03251 if (ast_strlen_zero(textmsg)) { 03252 astman_send_error(s, m, "No Message specified"); 03253 return 0; 03254 } 03255 03256 if (!(c = ast_channel_get_by_name(name))) { 03257 astman_send_error(s, m, "No such channel"); 03258 return 0; 03259 } 03260 03261 res = ast_sendtext(c, textmsg); 03262 c = ast_channel_unref(c); 03263 03264 if (res >= 0) { 03265 astman_send_ack(s, m, "Success"); 03266 } else { 03267 astman_send_error(s, m, "Failure"); 03268 } 03269 03270 return res; 03271 }
static int action_setvar | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3009 of file manager.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), name, pbx_builtin_setvar_helper(), and S_OR.
Referenced by __init_manager().
03010 { 03011 struct ast_channel *c = NULL; 03012 const char *name = astman_get_header(m, "Channel"); 03013 const char *varname = astman_get_header(m, "Variable"); 03014 const char *varval = astman_get_header(m, "Value"); 03015 int res = 0; 03016 03017 if (ast_strlen_zero(varname)) { 03018 astman_send_error(s, m, "No variable specified"); 03019 return 0; 03020 } 03021 03022 if (!ast_strlen_zero(name)) { 03023 if (!(c = ast_channel_get_by_name(name))) { 03024 astman_send_error(s, m, "No such channel"); 03025 return 0; 03026 } 03027 } 03028 03029 res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, "")); 03030 03031 if (c) { 03032 c = ast_channel_unref(c); 03033 } 03034 if (res == 0) { 03035 astman_send_ack(s, m, "Variable Set"); 03036 } else { 03037 astman_send_error(s, m, "Variable not set"); 03038 } 03039 return 0; 03040 }
static int action_status | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager "status" command to show channels.
Definition at line 3090 of file manager.c.
References AST_APP_ARG, ast_channel_get_by_name(), ast_channel_iterator_all_new(), ast_channel_iterator_next(), ast_channel_lock, AST_DECLARE_APP_ARGS, ast_free, ast_func_read(), AST_STANDARD_APP_ARGS, ast_str_append(), ast_str_create(), ast_str_reset(), ast_strdupa, ast_strlen_zero(), ast_tvnow(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_channel::bridge, channels, ast_channel::name, name, pbx_retrieve_variable(), S_OR, and str.
Referenced by __init_manager().
03091 { 03092 const char *name = astman_get_header(m, "Channel"); 03093 const char *cvariables = astman_get_header(m, "Variables"); 03094 char *variables = ast_strdupa(S_OR(cvariables, "")); 03095 struct ast_channel *c; 03096 char bridge[256]; 03097 struct timeval now = ast_tvnow(); 03098 long elapsed_seconds = 0; 03099 int channels = 0; 03100 int all = ast_strlen_zero(name); /* set if we want all channels */ 03101 const char *id = astman_get_header(m, "ActionID"); 03102 char idText[256]; 03103 AST_DECLARE_APP_ARGS(vars, 03104 AST_APP_ARG(name)[100]; 03105 ); 03106 struct ast_str *str = ast_str_create(1000); 03107 struct ast_channel_iterator *iter = NULL; 03108 03109 if (!ast_strlen_zero(id)) { 03110 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 03111 } else { 03112 idText[0] = '\0'; 03113 } 03114 03115 if (all) { 03116 if (!(iter = ast_channel_iterator_all_new())) { 03117 ast_free(str); 03118 astman_send_error(s, m, "Memory Allocation Failure"); 03119 return 1; 03120 } 03121 c = ast_channel_iterator_next(iter); 03122 } else { 03123 if (!(c = ast_channel_get_by_name(name))) { 03124 astman_send_error(s, m, "No such channel"); 03125 ast_free(str); 03126 return 0; 03127 } 03128 } 03129 03130 astman_send_ack(s, m, "Channel status will follow"); 03131 03132 if (!ast_strlen_zero(cvariables)) { 03133 AST_STANDARD_APP_ARGS(vars, variables); 03134 } 03135 03136 /* if we look by name, we break after the first iteration */ 03137 for (; c; c = ast_channel_iterator_next(iter)) { 03138 ast_channel_lock(c); 03139 03140 if (!ast_strlen_zero(cvariables)) { 03141 int i; 03142 ast_str_reset(str); 03143 for (i = 0; i < vars.argc; i++) { 03144 char valbuf[512], *ret = NULL; 03145 03146 if (vars.name[i][strlen(vars.name[i]) - 1] == ')') { 03147 if (ast_func_read(c, vars.name[i], valbuf, sizeof(valbuf)) < 0) { 03148 valbuf[0] = '\0'; 03149 } 03150 ret = valbuf; 03151 } else { 03152 pbx_retrieve_variable(c, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL); 03153 } 03154 03155 ast_str_append(&str, 0, "Variable: %s=%s\r\n", vars.name[i], ret); 03156 } 03157 } 03158 03159 channels++; 03160 if (c->_bridge) { 03161 snprintf(bridge, sizeof(bridge), "BridgedChannel: %s\r\nBridgedUniqueid: %s\r\n", c->_bridge->name, c->_bridge->uniqueid); 03162 } else { 03163 bridge[0] = '\0'; 03164 } 03165 if (c->pbx) { 03166 if (c->cdr) { 03167 elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec; 03168 } 03169 astman_append(s, 03170 "Event: Status\r\n" 03171 "Privilege: Call\r\n" 03172 "Channel: %s\r\n" 03173 "CallerIDNum: %s\r\n" 03174 "CallerIDName: %s\r\n" 03175 "Accountcode: %s\r\n" 03176 "ChannelState: %d\r\n" 03177 "ChannelStateDesc: %s\r\n" 03178 "Context: %s\r\n" 03179 "Extension: %s\r\n" 03180 "Priority: %d\r\n" 03181 "Seconds: %ld\r\n" 03182 "%s" 03183 "Uniqueid: %s\r\n" 03184 "%s" 03185 "%s" 03186 "\r\n", 03187 c->name, 03188 S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""), 03189 S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""), 03190 c->accountcode, 03191 c->_state, 03192 ast_state2str(c->_state), c->context, 03193 c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, ast_str_buffer(str), idText); 03194 } else { 03195 astman_append(s, 03196 "Event: Status\r\n" 03197 "Privilege: Call\r\n" 03198 "Channel: %s\r\n" 03199 "CallerIDNum: %s\r\n" 03200 "CallerIDName: %s\r\n" 03201 "Account: %s\r\n" 03202 "State: %s\r\n" 03203 "%s" 03204 "Uniqueid: %s\r\n" 03205 "%s" 03206 "%s" 03207 "\r\n", 03208 c->name, 03209 S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"), 03210 S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"), 03211 c->accountcode, 03212 ast_state2str(c->_state), bridge, c->uniqueid, 03213 ast_str_buffer(str), idText); 03214 } 03215 03216 ast_channel_unlock(c); 03217 c = ast_channel_unref(c); 03218 03219 if (!all) { 03220 break; 03221 } 03222 } 03223 03224 if (iter) { 03225 ast_channel_iterator_destroy(iter); 03226 } 03227 03228 astman_append(s, 03229 "Event: StatusComplete\r\n" 03230 "%s" 03231 "Items: %d\r\n" 03232 "\r\n", idText, channels); 03233 03234 ast_free(str); 03235 03236 return 0; 03237 }
static int action_timeout | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4016 of file manager.c.
References ast_channel_get_by_name(), ast_channel_lock, ast_channel_setwhentohangup_tv(), ast_channel_unlock, ast_channel_unref, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and name.
Referenced by __init_manager().
04017 { 04018 struct ast_channel *c; 04019 const char *name = astman_get_header(m, "Channel"); 04020 double timeout = atof(astman_get_header(m, "Timeout")); 04021 struct timeval when = { timeout, 0 }; 04022 04023 if (ast_strlen_zero(name)) { 04024 astman_send_error(s, m, "No channel specified"); 04025 return 0; 04026 } 04027 04028 if (!timeout || timeout < 0) { 04029 astman_send_error(s, m, "No timeout specified"); 04030 return 0; 04031 } 04032 04033 if (!(c = ast_channel_get_by_name(name))) { 04034 astman_send_error(s, m, "No such channel"); 04035 return 0; 04036 } 04037 04038 when.tv_usec = (timeout - when.tv_sec) * 1000000.0; 04039 04040 ast_channel_lock(c); 04041 ast_channel_setwhentohangup_tv(c, when); 04042 ast_channel_unlock(c); 04043 c = ast_channel_unref(c); 04044 04045 astman_send_ack(s, m, "Timeout Set"); 04046 04047 return 0; 04048 }
static int action_updateconfig | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2660 of file manager.c.
References ast_config_destroy(), ast_config_load2(), ast_config_text_file_save(), ast_include_rename(), ast_module_reload(), ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, config_flags, CONFIG_STATUS_FILEINVALID, FAILURE_ALLOCATION, FAILURE_DELCAT, FAILURE_DELETE, FAILURE_EMPTYCAT, FAILURE_NEWCAT, FAILURE_UPDATE, handle_updates(), UNKNOWN_ACTION, UNKNOWN_CATEGORY, UNSPECIFIED_ARGUMENT, and UNSPECIFIED_CATEGORY.
Referenced by __init_manager().
02661 { 02662 struct ast_config *cfg; 02663 const char *sfn = astman_get_header(m, "SrcFilename"); 02664 const char *dfn = astman_get_header(m, "DstFilename"); 02665 int res; 02666 const char *rld = astman_get_header(m, "Reload"); 02667 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02668 enum error_type result; 02669 02670 if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) { 02671 astman_send_error(s, m, "Filename not specified"); 02672 return 0; 02673 } 02674 if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) { 02675 astman_send_error(s, m, "Config file not found"); 02676 return 0; 02677 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02678 astman_send_error(s, m, "Config file has invalid format"); 02679 return 0; 02680 } 02681 result = handle_updates(s, m, cfg, dfn); 02682 if (!result) { 02683 ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */ 02684 res = ast_config_text_file_save(dfn, cfg, "Manager"); 02685 ast_config_destroy(cfg); 02686 if (res) { 02687 astman_send_error(s, m, "Save of config failed"); 02688 return 0; 02689 } 02690 astman_send_ack(s, m, NULL); 02691 if (!ast_strlen_zero(rld)) { 02692 if (ast_true(rld)) { 02693 rld = NULL; 02694 } 02695 ast_module_reload(rld); 02696 } 02697 } else { 02698 ast_config_destroy(cfg); 02699 switch(result) { 02700 case UNKNOWN_ACTION: 02701 astman_send_error(s, m, "Unknown action command"); 02702 break; 02703 case UNKNOWN_CATEGORY: 02704 astman_send_error(s, m, "Given category does not exist"); 02705 break; 02706 case UNSPECIFIED_CATEGORY: 02707 astman_send_error(s, m, "Category not specified"); 02708 break; 02709 case UNSPECIFIED_ARGUMENT: 02710 astman_send_error(s, m, "Problem with category, value, or line (if required)"); 02711 break; 02712 case FAILURE_ALLOCATION: 02713 astman_send_error(s, m, "Memory allocation failure, this should not happen"); 02714 break; 02715 case FAILURE_NEWCAT: 02716 astman_send_error(s, m, "Create category did not complete successfully"); 02717 break; 02718 case FAILURE_DELCAT: 02719 astman_send_error(s, m, "Delete category did not complete successfully"); 02720 break; 02721 case FAILURE_EMPTYCAT: 02722 astman_send_error(s, m, "Empty category did not complete successfully"); 02723 break; 02724 case FAILURE_UPDATE: 02725 astman_send_error(s, m, "Update did not complete successfully"); 02726 break; 02727 case FAILURE_DELETE: 02728 astman_send_error(s, m, "Delete did not complete successfully"); 02729 break; 02730 case FAILURE_APPEND: 02731 astman_send_error(s, m, "Append did not complete successfully"); 02732 break; 02733 } 02734 } 02735 return 0; 02736 }
static int action_userevent | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4132 of file manager.c.
References ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_thread_get(), astman_get_header(), astman_send_ack(), EVENT_FLAG_USER, message::hdrcount, message::headers, manager_event, and userevent_buf.
Referenced by __init_manager().
04133 { 04134 const char *event = astman_get_header(m, "UserEvent"); 04135 struct ast_str *body = ast_str_thread_get(&userevent_buf, 16); 04136 int x; 04137 04138 ast_str_reset(body); 04139 04140 for (x = 0; x < m->hdrcount; x++) { 04141 if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) { 04142 ast_str_append(&body, 0, "%s\r\n", m->headers[x]); 04143 } 04144 } 04145 04146 astman_send_ack(s, m, "Event Sent"); 04147 manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, ast_str_buffer(body)); 04148 return 0; 04149 }
static int action_waitevent | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2756 of file manager.c.
References ao2_lock, ao2_unlock, ast_debug, AST_PTHREADT_NULL, AST_RWLIST_NEXT, ast_strlen_zero(), astman_get_header(), mansession_session::last_ev, mansession_session::managerid, mansession_session::needdestroy, mansession_session::send_events, mansession::session, mansession_session::sessiontimeout, and mansession_session::waiting_thread.
Referenced by __init_manager().
02757 { 02758 const char *timeouts = astman_get_header(m, "Timeout"); 02759 int timeout = -1; 02760 int x; 02761 int needexit = 0; 02762 const char *id = astman_get_header(m, "ActionID"); 02763 char idText[256]; 02764 02765 if (!ast_strlen_zero(id)) { 02766 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 02767 } else { 02768 idText[0] = '\0'; 02769 } 02770 02771 if (!ast_strlen_zero(timeouts)) { 02772 sscanf(timeouts, "%30i", &timeout); 02773 if (timeout < -1) { 02774 timeout = -1; 02775 } 02776 /* XXX maybe put an upper bound, or prevent the use of 0 ? */ 02777 } 02778 02779 ao2_lock(s->session); 02780 if (s->session->waiting_thread != AST_PTHREADT_NULL) { 02781 pthread_kill(s->session->waiting_thread, SIGURG); 02782 } 02783 02784 if (s->session->managerid) { /* AMI-over-HTTP session */ 02785 /* 02786 * Make sure the timeout is within the expire time of the session, 02787 * as the client will likely abort the request if it does not see 02788 * data coming after some amount of time. 02789 */ 02790 time_t now = time(NULL); 02791 int max = s->session->sessiontimeout - now - 10; 02792 02793 if (max < 0) { /* We are already late. Strange but possible. */ 02794 max = 0; 02795 } 02796 if (timeout < 0 || timeout > max) { 02797 timeout = max; 02798 } 02799 if (!s->session->send_events) { /* make sure we record events */ 02800 s->session->send_events = -1; 02801 } 02802 } 02803 ao2_unlock(s->session); 02804 02805 /* XXX should this go inside the lock ? */ 02806 s->session->waiting_thread = pthread_self(); /* let new events wake up this thread */ 02807 ast_debug(1, "Starting waiting for an event!\n"); 02808 02809 for (x = 0; x < timeout || timeout < 0; x++) { 02810 ao2_lock(s->session); 02811 if (AST_RWLIST_NEXT(s->session->last_ev, eq_next)) { 02812 needexit = 1; 02813 } 02814 /* We can have multiple HTTP session point to the same mansession entry. 02815 * The way we deal with it is not very nice: newcomers kick out the previous 02816 * HTTP session. XXX this needs to be improved. 02817 */ 02818 if (s->session->waiting_thread != pthread_self()) { 02819 needexit = 1; 02820 } 02821 if (s->session->needdestroy) { 02822 needexit = 1; 02823 } 02824 ao2_unlock(s->session); 02825 if (needexit) { 02826 break; 02827 } 02828 if (s->session->managerid == 0) { /* AMI session */ 02829 if (ast_wait_for_input(s->session->fd, 1000)) { 02830 break; 02831 } 02832 } else { /* HTTP session */ 02833 sleep(1); 02834 } 02835 } 02836 ast_debug(1, "Finished waiting for an event!\n"); 02837 02838 ao2_lock(s->session); 02839 if (s->session->waiting_thread == pthread_self()) { 02840 struct eventqent *eqe = s->session->last_ev; 02841 astman_send_response(s, m, "Success", "Waiting for Event completed."); 02842 while ((eqe = advance_event(eqe))) { 02843 if (((s->session->readperm & eqe->category) == eqe->category) && 02844 ((s->session->send_events & eqe->category) == eqe->category)) { 02845 astman_append(s, "%s", eqe->eventdata); 02846 } 02847 s->session->last_ev = eqe; 02848 } 02849 astman_append(s, 02850 "Event: WaitEventComplete\r\n" 02851 "%s" 02852 "\r\n", idText); 02853 s->session->waiting_thread = AST_PTHREADT_NULL; 02854 } else { 02855 ast_debug(1, "Abandoning event request!\n"); 02856 } 02857 ao2_unlock(s->session); 02858 02859 return 0; 02860 }
Definition at line 1687 of file manager.c.
References ast_atomic_fetchadd_int(), AST_RWLIST_NEXT, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, eventqent::eq_next, eventqent::next, and eventqent::usecount.
Referenced by process_events().
01688 { 01689 struct eventqent *next; 01690 01691 AST_RWLIST_RDLOCK(&all_events); 01692 if ((next = AST_RWLIST_NEXT(e, eq_next))) { 01693 ast_atomic_fetchadd_int(&next->usecount, 1); 01694 ast_atomic_fetchadd_int(&e->usecount, -1); 01695 } 01696 AST_RWLIST_UNLOCK(&all_events); 01697 return next; 01698 }
static int aocmessage_get_unit_entry | ( | const struct message * | m, | |
struct ast_aoc_unit_entry * | entry, | |||
unsigned int | entry_num | |||
) | [static] |
Definition at line 3585 of file manager.c.
References ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_strlen_zero(), astman_get_header(), and str.
Referenced by action_aocmessage().
03586 { 03587 const char *unitamount; 03588 const char *unittype; 03589 struct ast_str *str = ast_str_alloca(32); 03590 03591 memset(entry, 0, sizeof(*entry)); 03592 03593 ast_str_set(&str, 0, "UnitAmount(%u)", entry_num); 03594 unitamount = astman_get_header(m, ast_str_buffer(str)); 03595 03596 ast_str_set(&str, 0, "UnitType(%u)", entry_num); 03597 unittype = astman_get_header(m, ast_str_buffer(str)); 03598 03599 if (!ast_strlen_zero(unitamount) && (sscanf(unitamount, "%30u", &entry->amount) == 1)) { 03600 entry->valid_amount = 1; 03601 } 03602 03603 if (!ast_strlen_zero(unittype) && sscanf(unittype, "%30u", &entry->type) == 1) { 03604 entry->valid_type = 1; 03605 } 03606 03607 return 0; 03608 }
static void append_channel_vars | ( | struct ast_str ** | pbuf, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 4809 of file manager.c.
References ast_func_read2(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_str_append(), ast_str_buffer(), ast_str_thread_get(), manager_event_funcbuf, ast_channel::name, pbx_builtin_getvar_helper(), and var.
Referenced by __ast_manager_event_multichan().
04810 { 04811 struct manager_channel_variable *var; 04812 AST_RWLIST_RDLOCK(&channelvars); 04813 AST_LIST_TRAVERSE(&channelvars, var, entry) { 04814 const char *val = ""; 04815 if (var->isfunc) { 04816 struct ast_str *res = ast_str_thread_get(&manager_event_funcbuf, 16); 04817 int ret; 04818 if (res && (ret = ast_func_read2(chan, var->name, &res, 0)) == 0) { 04819 val = ast_str_buffer(res); 04820 } 04821 } else { 04822 val = pbx_builtin_getvar_helper(chan, var->name); 04823 } 04824 ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", chan->name, var->name, val ? val : ""); 04825 } 04826 AST_RWLIST_UNLOCK(&channelvars); 04827 }
static int append_event | ( | const char * | str, | |
int | category | |||
) | [static] |
Definition at line 4783 of file manager.c.
References ast_atomic_fetchadd_int(), ast_malloc, AST_RWLIST_INSERT_TAIL, AST_RWLIST_NEXT, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_tvnow(), and seq.
Referenced by __ast_manager_event_multichan(), and __init_manager().
04784 { 04785 struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str)); 04786 static int seq; /* sequence number */ 04787 04788 if (!tmp) { 04789 return -1; 04790 } 04791 04792 /* need to init all fields, because ast_malloc() does not */ 04793 tmp->usecount = 0; 04794 tmp->category = category; 04795 tmp->seq = ast_atomic_fetchadd_int(&seq, 1); 04796 tmp->tv = ast_tvnow(); 04797 AST_RWLIST_NEXT(tmp, eq_next) = NULL; 04798 strcpy(tmp->eventdata, str); 04799 04800 AST_RWLIST_WRLOCK(&all_events); 04801 AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next); 04802 AST_RWLIST_UNLOCK(&all_events); 04803 04804 return 0; 04805 }
int ast_hook_send_action | ( | struct manager_custom_hook * | hook, | |
const char * | msg | |||
) |
Registered hooks can call this function to invoke actions and they will receive responses through registered callback.
hook | the file identifier specified in manager_custom_hook struct when registering a hook | |
msg | ami action mesage string e.g. "Action: SipPeers\r\n" |
0 | on Success | |
non-zero | on Failure |
Definition at line 1786 of file manager.c.
References manager_action::action, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdupa, astman_get_header(), mansession::f, manager_action::func, message::hdrcount, message::headers, mansession::hook, and mansession::session.
01787 { 01788 const char *action; 01789 int ret = 0; 01790 struct manager_action *tmp; 01791 struct mansession s = {.session = NULL, }; 01792 struct message m = { 0 }; 01793 char header_buf[1025] = { '\0' }; 01794 const char *src = msg; 01795 int x = 0; 01796 int curlen; 01797 01798 if (hook == NULL) { 01799 return -1; 01800 } 01801 01802 /* convert msg string to message struct */ 01803 curlen = strlen(msg); 01804 for (x = 0; x < curlen; x++) { 01805 int cr; /* set if we have \r */ 01806 if (src[x] == '\r' && x+1 < curlen && src[x+1] == '\n') 01807 cr = 2; /* Found. Update length to include \r\n */ 01808 else if (src[x] == '\n') 01809 cr = 1; /* also accept \n only */ 01810 else 01811 continue; 01812 /* don't copy empty lines */ 01813 if (x) { 01814 memmove(header_buf, src, x); /*... but trim \r\n */ 01815 header_buf[x] = '\0'; /* terminate the string */ 01816 m.headers[m.hdrcount++] = ast_strdupa(header_buf); 01817 } 01818 x += cr; 01819 curlen -= x; /* remaining size */ 01820 src += x; /* update pointer */ 01821 x = -1; /* reset loop */ 01822 } 01823 01824 action = astman_get_header(&m,"Action"); 01825 if (action && strcasecmp(action,"login")) { 01826 01827 AST_RWLIST_RDLOCK(&actions); 01828 AST_RWLIST_TRAVERSE(&actions, tmp, list) { 01829 if (strcasecmp(action, tmp->action)) 01830 continue; 01831 /* 01832 * we have to simulate a session for this action request 01833 * to be able to pass it down for processing 01834 * This is necessary to meet the previous design of manager.c 01835 */ 01836 s.hook = hook; 01837 s.f = (void*)1; /* set this to something so our request will make it through all functions that test it*/ 01838 ret = tmp->func(&s, &m); 01839 break; 01840 } 01841 AST_RWLIST_UNLOCK(&actions); 01842 } 01843 return ret; 01844 }
static int ast_instring | ( | const char * | bigstr, | |
const char * | smallstr, | |||
const char | delim | |||
) | [static] |
Tells you if smallstr exists inside bigstr which is delim by delim and uses no buf or stringsep ast_instring("this|that|more","this",'|') == 1;
feel free to move this to app.c -anthm
Definition at line 1157 of file manager.c.
References eventqent::next.
Referenced by get_perm().
01158 { 01159 const char *val = bigstr, *next; 01160 01161 do { 01162 if ((next = strchr(val, delim))) { 01163 if (!strncmp(val, smallstr, (next - val))) { 01164 return 1; 01165 } else { 01166 continue; 01167 } 01168 } else { 01169 return !strcmp(smallstr, val); 01170 } 01171 } while (*(val = (next + 1))); 01172 01173 return 0; 01174 }
int ast_manager_register2 | ( | const char * | action, | |
int | authority, | |||
int(*)(struct mansession *s, const struct message *m) | func, | |||
const char * | synopsis, | |||
const char * | description | |||
) |
Register a manager command with the manager interface.
action | Name of the requested Action: | |
authority | Required authority for this command | |
func | Function to call for this command | |
synopsis | Help text (one line, up to 30 chars) for CLI manager show commands | |
description | Help text, several lines |
Definition at line 4991 of file manager.c.
References manager_action::action, ast_calloc_with_stringfields, ast_free, ast_manager_register_struct(), AST_STATIC_DOC, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), manager_action::authority, manager_action::docsrc, and manager_action::func.
Referenced by load_module().
04992 { 04993 struct manager_action *cur = NULL; 04994 #ifdef AST_XML_DOCS 04995 char *tmpxml; 04996 #endif 04997 04998 if (!(cur = ast_calloc_with_stringfields(1, struct manager_action, 128))) { 04999 return -1; 05000 } 05001 05002 cur->action = action; 05003 cur->authority = auth; 05004 cur->func = func; 05005 #ifdef AST_XML_DOCS 05006 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 05007 tmpxml = ast_xmldoc_build_synopsis("manager", action); 05008 ast_string_field_set(cur, synopsis, tmpxml); 05009 ast_free(tmpxml); 05010 05011 tmpxml = ast_xmldoc_build_syntax("manager", action); 05012 ast_string_field_set(cur, syntax, tmpxml); 05013 ast_free(tmpxml); 05014 05015 tmpxml = ast_xmldoc_build_description("manager", action); 05016 ast_string_field_set(cur, description, tmpxml); 05017 ast_free(tmpxml); 05018 05019 tmpxml = ast_xmldoc_build_seealso("manager", action); 05020 ast_string_field_set(cur, seealso, tmpxml); 05021 ast_free(tmpxml); 05022 05023 tmpxml = ast_xmldoc_build_arguments("manager", action); 05024 ast_string_field_set(cur, arguments, tmpxml); 05025 ast_free(tmpxml); 05026 05027 cur->docsrc = AST_XML_DOC; 05028 } else { 05029 #endif 05030 ast_string_field_set(cur, synopsis, synopsis); 05031 ast_string_field_set(cur, description, description); 05032 #ifdef AST_XML_DOCS 05033 cur->docsrc = AST_STATIC_DOC; 05034 } 05035 #endif 05036 if (ast_manager_register_struct(cur)) { 05037 ast_free(cur); 05038 return -1; 05039 } 05040 05041 return 0; 05042 }
void ast_manager_register_hook | ( | struct manager_custom_hook * | hook | ) |
Add a custom hook to be called when an event is fired.
Add a custom hook to be called when an event is fired
hook | struct manager_custom_hook object to add |
Definition at line 1027 of file manager.c.
References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
01028 { 01029 AST_RWLIST_WRLOCK(&manager_hooks); 01030 AST_RWLIST_INSERT_TAIL(&manager_hooks, hook, list); 01031 AST_RWLIST_UNLOCK(&manager_hooks); 01032 }
static int ast_manager_register_struct | ( | struct manager_action * | act | ) | [static] |
Definition at line 4954 of file manager.c.
References manager_action::action, ast_log(), AST_RWLIST_INSERT_AFTER, AST_RWLIST_INSERT_HEAD, AST_RWLIST_TIMEDWRLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_verb, LOG_ERROR, LOG_WARNING, and tv.
Referenced by ast_manager_register2().
04955 { 04956 struct manager_action *cur, *prev = NULL; 04957 struct timespec tv = { 5, }; 04958 04959 if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) { 04960 ast_log(LOG_ERROR, "Could not obtain lock on manager list\n"); 04961 return -1; 04962 } 04963 AST_RWLIST_TRAVERSE(&actions, cur, list) { 04964 int ret = strcasecmp(cur->action, act->action); 04965 if (ret == 0) { 04966 ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action); 04967 AST_RWLIST_UNLOCK(&actions); 04968 return -1; 04969 } 04970 if (ret > 0) { /* Insert these alphabetically */ 04971 prev = cur; 04972 break; 04973 } 04974 } 04975 04976 if (prev) { 04977 AST_RWLIST_INSERT_AFTER(&actions, prev, act, list); 04978 } else { 04979 AST_RWLIST_INSERT_HEAD(&actions, act, list); 04980 } 04981 04982 ast_verb(2, "Manager registered action %s\n", act->action); 04983 04984 AST_RWLIST_UNLOCK(&actions); 04985 04986 return 0; 04987 }
int ast_manager_unregister | ( | char * | action | ) |
Unregister a registered manager command.
action | Name of registered Action: |
Definition at line 4920 of file manager.c.
References manager_action::action, ast_free, ast_log(), AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TIMEDWRLOCK, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, ast_string_field_free_memory, ast_verb, LOG_ERROR, and tv.
Referenced by __unload_module(), and unload_module().
04921 { 04922 struct manager_action *cur; 04923 struct timespec tv = { 5, }; 04924 04925 if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) { 04926 ast_log(LOG_ERROR, "Could not obtain lock on manager list\n"); 04927 return -1; 04928 } 04929 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) { 04930 if (!strcasecmp(action, cur->action)) { 04931 AST_RWLIST_REMOVE_CURRENT(list); 04932 ast_string_field_free_memory(cur); 04933 ast_free(cur); 04934 ast_verb(2, "Manager unregistered action %s\n", action); 04935 break; 04936 } 04937 } 04938 AST_RWLIST_TRAVERSE_SAFE_END; 04939 AST_RWLIST_UNLOCK(&actions); 04940 04941 return 0; 04942 }
void ast_manager_unregister_hook | ( | struct manager_custom_hook * | hook | ) |
Delete a custom hook to be called when an event is fired.
Delete a custom hook to be called when an event is fired
hook | struct manager_custom_hook object to delete |
Definition at line 1035 of file manager.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
01036 { 01037 AST_RWLIST_WRLOCK(&manager_hooks); 01038 AST_RWLIST_REMOVE(&manager_hooks, hook, list); 01039 AST_RWLIST_UNLOCK(&manager_hooks); 01040 }
void astman_append | ( | struct mansession * | s, | |
const char * | fmt, | |||
... | ||||
) |
utility functions for creating AMI replies
Definition at line 1884 of file manager.c.
References ast_str_buffer(), ast_str_set_va(), ast_str_thread_get(), ast_verbose, astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE, mansession_session::f, mansession::f, send_string(), and mansession::session.
Referenced by __iax2_show_peers(), _sip_show_peer(), _sip_show_peers(), _skinny_show_device(), _skinny_show_devices(), _skinny_show_line(), _skinny_show_lines(), action_agents(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_dahdishowchannels(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_listcategories(), action_listcommands(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_ping(), ast_cli_netstats(), astman_send_response_full(), data_result_manager_output(), do_print(), manager_data_get(), manager_dbget(), manager_iax2_show_netstats(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_jabber_send(), manager_list_voicemail_users(), manager_modulecheck(), manager_mute_mixmonitor(), manager_mutestream(), manager_parking_status(), manager_queue_rule_show(), manager_queues_show(), manager_queues_status(), manager_queues_summary(), manager_rpt_local_nodes(), manager_rpt_status(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_show_registry(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), rpt_manager_do_stats(), rpt_manager_success(), and session_do().
01885 { 01886 va_list ap; 01887 struct ast_str *buf; 01888 01889 if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) { 01890 return; 01891 } 01892 01893 va_start(ap, fmt); 01894 ast_str_set_va(&buf, 0, fmt, ap); 01895 va_end(ap); 01896 01897 if (s->f != NULL || s->session->f != NULL) { 01898 send_string(s, ast_str_buffer(buf)); 01899 } else { 01900 ast_verbose("fd == -1 in astman_append, should not happen\n"); 01901 } 01902 }
const char* astman_get_header | ( | const struct message * | m, | |
char * | var | |||
) |
Get header from mananger transaction.
Definition at line 1737 of file manager.c.
References __astman_get_header(), and GET_HEADER_FIRST_MATCH.
Referenced by _sip_show_peer(), _sip_show_peers(), _skinny_show_devices(), _skinny_show_lines(), action_add_agi_cmd(), action_agent_logoff(), action_agents(), action_aocmessage(), action_atxfer(), action_bridge(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdishowchannels(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_originate(), action_ping(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), action_waitevent(), aocmessage_get_unit_entry(), ast_hook_send_action(), astman_send_response_full(), authenticate(), change_monitor_action(), do_pause_or_unpause(), handle_updates(), manager_add_queue_member(), manager_data_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_jabber_send(), manager_list_voicemail_users(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_optimize_away(), manager_park(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_queue_rule_show(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), manager_rpt_status(), manager_show_dialplan(), manager_show_registry(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), meetmemute(), process_message(), rpt_manager_do_stats(), rpt_manager_success(), start_monitor_action(), and stop_monitor_action().
01738 { 01739 return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH); 01740 }
struct ast_variable* astman_get_variables | ( | const struct message * | m | ) |
Get a linked list of the Variable: headers.
Definition at line 1743 of file manager.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_variable_new(), message::hdrcount, message::headers, parse(), strsep(), and var.
Referenced by action_originate(), and manager_sipnotify().
01744 { 01745 int varlen, x, y; 01746 struct ast_variable *head = NULL, *cur; 01747 01748 AST_DECLARE_APP_ARGS(args, 01749 AST_APP_ARG(vars)[32]; 01750 ); 01751 01752 varlen = strlen("Variable: "); 01753 01754 for (x = 0; x < m->hdrcount; x++) { 01755 char *parse, *var, *val; 01756 01757 if (strncasecmp("Variable: ", m->headers[x], varlen)) { 01758 continue; 01759 } 01760 parse = ast_strdupa(m->headers[x] + varlen); 01761 01762 AST_STANDARD_APP_ARGS(args, parse); 01763 if (!args.argc) { 01764 continue; 01765 } 01766 for (y = 0; y < args.argc; y++) { 01767 if (!args.vars[y]) { 01768 continue; 01769 } 01770 var = val = ast_strdupa(args.vars[y]); 01771 strsep(&val, "="); 01772 if (!val || ast_strlen_zero(var)) { 01773 continue; 01774 } 01775 cur = ast_variable_new(var, val, ""); 01776 cur->next = head; 01777 head = cur; 01778 } 01779 } 01780 01781 return head; 01782 }
void astman_send_ack | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | msg | |||
) |
Send ack in manager transaction.
Definition at line 1951 of file manager.c.
References astman_send_response_full().
Referenced by action_add_agi_cmd(), action_agent_logoff(), action_agents(), action_aocmessage(), action_atxfer(), action_bridge(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_dahdishowchannels(), action_hangup(), action_login(), action_originate(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), change_monitor_action(), do_pause_or_unpause(), manager_add_queue_member(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_jabber_send(), manager_list_voicemail_users(), manager_moduleload(), manager_optimize_away(), manager_park(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), meetmemute(), start_monitor_action(), and stop_monitor_action().
01952 { 01953 astman_send_response_full(s, m, "Success", msg, NULL); 01954 }
void astman_send_error | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | error | |||
) |
Send error in manager transaction.
Definition at line 1946 of file manager.c.
References astman_send_response_full().
Referenced by _sip_qualify_peer(), _sip_show_peer(), action_add_agi_cmd(), action_agent_logoff(), action_aocmessage(), action_atxfer(), action_bridge(), action_challenge(), action_command(), action_coreshowchannels(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_originate(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), change_monitor_action(), do_pause_or_unpause(), manager_add_queue_member(), manager_data_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_jabber_send(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_optimize_away(), manager_park(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_remove_queue_member(), manager_rpt_status(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_line(), meetmemute(), process_message(), start_monitor_action(), and stop_monitor_action().
01947 { 01948 astman_send_response_full(s, m, "Error", error, NULL); 01949 }
void astman_send_listack | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | msg, | |||
char * | listflag | |||
) |
Send ack in manager list transaction.
Definition at line 1961 of file manager.c.
References astman_send_response_full().
Referenced by action_coreshowchannels(), action_meetmelist(), manager_dpsendack(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_show_registry(), manager_sip_show_peers(), manager_skinny_show_devices(), and manager_skinny_show_lines().
01962 { 01963 astman_send_response_full(s, m, "Success", msg, listflag); 01964 }
void astman_send_response | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | resp, | |||
char * | msg | |||
) |
Send response in manager transaction.
Definition at line 1941 of file manager.c.
References astman_send_response_full().
Referenced by action_logoff().
01942 { 01943 astman_send_response_full(s, m, resp, msg, NULL); 01944 }
static void astman_send_response_full | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | resp, | |||
char * | msg, | |||
char * | listflag | |||
) | [static] |
Definition at line 1921 of file manager.c.
References ast_strlen_zero(), astman_append(), astman_get_header(), and MSG_MOREDATA.
Referenced by astman_send_ack(), astman_send_error(), astman_send_listack(), astman_send_response(), and astman_start_ack().
01922 { 01923 const char *id = astman_get_header(m, "ActionID"); 01924 01925 astman_append(s, "Response: %s\r\n", resp); 01926 if (!ast_strlen_zero(id)) { 01927 astman_append(s, "ActionID: %s\r\n", id); 01928 } 01929 if (listflag) { 01930 astman_append(s, "EventList: %s\r\n", listflag); /* Start, complete, cancelled */ 01931 } 01932 if (msg == MSG_MOREDATA) { 01933 return; 01934 } else if (msg) { 01935 astman_append(s, "Message: %s\r\n\r\n", msg); 01936 } else { 01937 astman_append(s, "\r\n"); 01938 } 01939 }
static void astman_start_ack | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 1956 of file manager.c.
References astman_send_response_full(), and MSG_MOREDATA.
Referenced by action_challenge(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_listcategories(), action_listcommands(), action_mailboxcount(), and action_mailboxstatus().
01957 { 01958 astman_send_response_full(s, m, "Success", MSG_MOREDATA, NULL); 01959 }
static int authenticate | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2238 of file manager.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_t_link, ao2_t_ref, ast_apply_ha(), ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_sockaddr_from_sin, ast_strlen_zero(), ast_tvnow(), astman_get_header(), mansession_session::blackfilters, mansession_session::challenge, get_manager_by_name_locked(), len(), LOG_NOTICE, md5(), MD5Final(), MD5Init(), MD5Update(), mansession_session::readperm, report_auth_success(), report_failed_acl(), report_failed_challenge_response(), report_inval_password(), report_invalid_user(), S_OR, mansession::session, mansession_session::sessionstart, mansession_session::sessionstart_tv, set_eventmask(), mansession_session::sin, user, mansession_session::username, mansession_session::whitefilters, mansession_session::writeperm, and mansession_session::writetimeout.
02239 { 02240 const char *username = astman_get_header(m, "Username"); 02241 const char *password = astman_get_header(m, "Secret"); 02242 int error = -1; 02243 struct ast_manager_user *user = NULL; 02244 regex_t *regex_filter; 02245 struct ao2_iterator filter_iter; 02246 struct ast_sockaddr addr; 02247 02248 if (ast_strlen_zero(username)) { /* missing username */ 02249 return -1; 02250 } 02251 02252 /* locate user in locked state */ 02253 AST_RWLIST_WRLOCK(&users); 02254 02255 ast_sockaddr_from_sin(&addr, &s->session->sin); 02256 02257 if (!(user = get_manager_by_name_locked(username))) { 02258 report_invalid_user(s, username); 02259 ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02260 } else if (user->ha && !ast_apply_ha(user->ha, &addr)) { 02261 report_failed_acl(s, username); 02262 ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02263 } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) { 02264 const char *key = astman_get_header(m, "Key"); 02265 if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) { 02266 int x; 02267 int len = 0; 02268 char md5key[256] = ""; 02269 struct MD5Context md5; 02270 unsigned char digest[16]; 02271 02272 MD5Init(&md5); 02273 MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge)); 02274 MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret)); 02275 MD5Final(digest, &md5); 02276 for (x = 0; x < 16; x++) 02277 len += sprintf(md5key + len, "%2.2x", digest[x]); 02278 if (!strcmp(md5key, key)) { 02279 error = 0; 02280 } else { 02281 report_failed_challenge_response(s, key, md5key); 02282 } 02283 } else { 02284 ast_debug(1, "MD5 authentication is not possible. challenge: '%s'\n", 02285 S_OR(s->session->challenge, "")); 02286 } 02287 } else if (user->secret) { 02288 if (!strcmp(password, user->secret)) { 02289 error = 0; 02290 } else { 02291 report_inval_password(s, username); 02292 } 02293 } 02294 02295 if (error) { 02296 ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02297 AST_RWLIST_UNLOCK(&users); 02298 return -1; 02299 } 02300 02301 /* auth complete */ 02302 02303 /* All of the user parameters are copied to the session so that in the event 02304 * of a reload and a configuration change, the session parameters are not 02305 * changed. */ 02306 ast_copy_string(s->session->username, username, sizeof(s->session->username)); 02307 s->session->readperm = user->readperm; 02308 s->session->writeperm = user->writeperm; 02309 s->session->writetimeout = user->writetimeout; 02310 02311 filter_iter = ao2_iterator_init(user->whitefilters, 0); 02312 while ((regex_filter = ao2_iterator_next(&filter_iter))) { 02313 ao2_t_link(s->session->whitefilters, regex_filter, "add white user filter to session"); 02314 ao2_t_ref(regex_filter, -1, "remove iterator ref"); 02315 } 02316 ao2_iterator_destroy(&filter_iter); 02317 02318 filter_iter = ao2_iterator_init(user->blackfilters, 0); 02319 while ((regex_filter = ao2_iterator_next(&filter_iter))) { 02320 ao2_t_link(s->session->blackfilters, regex_filter, "add black user filter to session"); 02321 ao2_t_ref(regex_filter, -1, "remove iterator ref"); 02322 } 02323 ao2_iterator_destroy(&filter_iter); 02324 02325 s->session->sessionstart = time(NULL); 02326 s->session->sessionstart_tv = ast_tvnow(); 02327 set_eventmask(s, astman_get_header(m, "Events")); 02328 02329 report_auth_success(s); 02330 02331 AST_RWLIST_UNLOCK(&users); 02332 return 0; 02333 }
static const char* authority_to_str | ( | int | authority, | |
struct ast_str ** | res | |||
) | [static] |
Convert authority code to a list of options.
Definition at line 1133 of file manager.c.
References ARRAY_LEN, ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_strlen(), and perms.
Referenced by __ast_manager_event_multichan(), action_listcommands(), handle_showmanager(), handle_showmancmd(), and handle_showmancmds().
01134 { 01135 int i; 01136 char *sep = ""; 01137 01138 ast_str_reset(*res); 01139 for (i = 0; i < ARRAY_LEN(perms) - 1; i++) { 01140 if (authority & perms[i].num) { 01141 ast_str_append(res, 0, "%s%s", sep, perms[i].label); 01142 sep = ","; 01143 } 01144 } 01145 01146 if (ast_str_strlen(*res) == 0) /* replace empty string with something sensible */ 01147 ast_str_append(res, 0, "<none>"); 01148 01149 return ast_str_buffer(*res); 01150 }
static int blackfilter_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 4064 of file manager.c.
References CMP_MATCH, and CMP_STOP.
Referenced by match_filter().
04065 { 04066 regex_t *regex_filter = obj; 04067 const char *eventdata = arg; 04068 int *result = data; 04069 04070 if (regexec(regex_filter, eventdata, 0, NULL, 0)) { 04071 *result = 1; 04072 return (CMP_MATCH | CMP_STOP); 04073 } 04074 04075 return 0; 04076 }
static struct mansession_session* build_mansession | ( | struct sockaddr_in | sin | ) | [static] |
Allocate manager session structure and add it to the list of sessions.
Definition at line 1274 of file manager.c.
References ao2_alloc, ao2_container_alloc, ao2_link, ao2_ref, AST_PTHREADT_NULL, and session_destructor().
Referenced by session_do().
01275 { 01276 struct mansession_session *newsession; 01277 01278 if (!(newsession = ao2_alloc(sizeof(*newsession), session_destructor))) { 01279 return NULL; 01280 } 01281 01282 if (!(newsession->whitefilters = ao2_container_alloc(1, NULL, NULL))) { 01283 ao2_ref(newsession, -1); 01284 return NULL; 01285 } 01286 01287 if (!(newsession->blackfilters = ao2_container_alloc(1, NULL, NULL))) { 01288 ao2_ref(newsession, -1); /* session_destructor will cleanup the other filter */ 01289 return NULL; 01290 } 01291 01292 newsession->fd = -1; 01293 newsession->waiting_thread = AST_PTHREADT_NULL; 01294 newsession->writetimeout = 100; 01295 newsession->send_events = -1; 01296 newsession->sin = sin; 01297 01298 ao2_link(sessions, newsession); 01299 01300 return newsession; 01301 }
static int check_blacklist | ( | const char * | cmd | ) | [static] |
Definition at line 3426 of file manager.c.
References ARRAY_LEN, ast_strdupa, ast_strip(), ast_strlen_zero(), command_blacklist, match(), MAX_BLACKLIST_CMD_LEN, strsep(), and words.
Referenced by action_command().
03427 { 03428 char *cmd_copy, *cur_cmd; 03429 char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, }; 03430 int i; 03431 03432 cmd_copy = ast_strdupa(cmd); 03433 for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) { 03434 cur_cmd = ast_strip(cur_cmd); 03435 if (ast_strlen_zero(cur_cmd)) { 03436 i--; 03437 continue; 03438 } 03439 03440 cmd_words[i] = cur_cmd; 03441 } 03442 03443 for (i = 0; i < ARRAY_LEN(command_blacklist); i++) { 03444 int j, match = 1; 03445 03446 for (j = 0; command_blacklist[i].words[j]; j++) { 03447 if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) { 03448 match = 0; 03449 break; 03450 } 03451 } 03452 03453 if (match) { 03454 return 1; 03455 } 03456 } 03457 03458 return 0; 03459 }
int check_manager_enabled | ( | void | ) |
Check if AMI is enabled.
Definition at line 1042 of file manager.c.
Referenced by handle_show_settings().
01043 { 01044 return manager_enabled; 01045 }
static int check_manager_session_inuse | ( | const char * | name | ) | [static] |
Definition at line 1317 of file manager.c.
References ao2_find, mansession_session::inuse, and unref_mansession().
Referenced by process_message().
01318 { 01319 struct mansession_session *session = ao2_find(sessions, (char *) name, 0); 01320 int inuse = 0; 01321 01322 if (session) { 01323 inuse = 1; 01324 unref_mansession(session); 01325 } 01326 return inuse; 01327 }
int check_webmanager_enabled | ( | void | ) |
Check if AMI/HTTP is enabled.
Definition at line 1047 of file manager.c.
Referenced by action_coresettings(), and handle_show_settings().
01048 { 01049 return (webmanager_enabled && manager_enabled); 01050 }
static int do_message | ( | struct mansession * | s | ) | [static] |
Definition at line 4607 of file manager.c.
References ast_inet_ntoa(), ast_log(), AST_MAX_MANHEADERS, ast_strdupa, ast_strlen_zero(), ast_verb, authtimeout, displayconnects, errno, get_input(), message::hdrcount, message::headers, mansession_session::inbuf, LOG_ERROR, process_events(), process_message(), and mansession::session.
Referenced by session_do().
04608 { 04609 struct message m = { 0 }; 04610 char header_buf[sizeof(s->session->inbuf)] = { '\0' }; 04611 int res; 04612 time_t now; 04613 04614 for (;;) { 04615 /* Check if any events are pending and do them if needed */ 04616 if (process_events(s)) { 04617 return -1; 04618 } 04619 res = get_input(s, header_buf); 04620 if (res == 0) { 04621 if (!s->session->authenticated) { 04622 if(time(&now) == -1) { 04623 ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); 04624 return -1; 04625 } 04626 04627 if (now - s->session->authstart > authtimeout) { 04628 if (displayconnects) { 04629 ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout); 04630 } 04631 return -1; 04632 } 04633 } 04634 continue; 04635 } else if (res > 0) { 04636 if (ast_strlen_zero(header_buf)) { 04637 return process_message(s, &m) ? -1 : 0; 04638 } else if (m.hdrcount < (AST_MAX_MANHEADERS - 1)) { 04639 m.headers[m.hdrcount++] = ast_strdupa(header_buf); 04640 } 04641 } else { 04642 return res; 04643 } 04644 } 04645 }
static void event_filter_destructor | ( | void * | obj | ) | [static] |
static void* fast_originate | ( | void * | data | ) | [static] |
Definition at line 3535 of file manager.c.
References fast_originate_helper::account, fast_originate_helper::app, fast_originate_helper::appdata, AST_CHANNEL_NAME, ast_channel_unlock, ast_free, ast_manager_event_multichan, ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_strlen_zero(), fast_originate_helper::cid_name, fast_originate_helper::cid_num, fast_originate_helper::context, fast_originate_helper::data, EVENT_FLAG_CALL, fast_originate_helper::exten, fast_originate_helper::format, fast_originate_helper::idtext, ast_channel::name, fast_originate_helper::priority, S_OR, fast_originate_helper::tech, fast_originate_helper::timeout, ast_channel::uniqueid, and fast_originate_helper::vars.
Referenced by action_originate().
03536 { 03537 struct fast_originate_helper *in = data; 03538 int res; 03539 int reason = 0; 03540 struct ast_channel *chan = NULL, *chans[1]; 03541 char requested_channel[AST_CHANNEL_NAME]; 03542 03543 if (!ast_strlen_zero(in->app)) { 03544 res = ast_pbx_outgoing_app(in->tech, in->format, in->data, in->timeout, in->app, in->appdata, &reason, 1, 03545 S_OR(in->cid_num, NULL), 03546 S_OR(in->cid_name, NULL), 03547 in->vars, in->account, &chan); 03548 } else { 03549 res = ast_pbx_outgoing_exten(in->tech, in->format, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, 03550 S_OR(in->cid_num, NULL), 03551 S_OR(in->cid_name, NULL), 03552 in->vars, in->account, &chan); 03553 } 03554 03555 if (!chan) { 03556 snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data); 03557 } 03558 /* Tell the manager what happened with the channel */ 03559 chans[0] = chan; 03560 ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans, 03561 "%s%s" 03562 "Response: %s\r\n" 03563 "Channel: %s\r\n" 03564 "Context: %s\r\n" 03565 "Exten: %s\r\n" 03566 "Reason: %d\r\n" 03567 "Uniqueid: %s\r\n" 03568 "CallerIDNum: %s\r\n" 03569 "CallerIDName: %s\r\n", 03570 in->idtext, ast_strlen_zero(in->idtext) ? "" : "\r\n", res ? "Failure" : "Success", 03571 chan ? chan->name : requested_channel, in->context, in->exten, reason, 03572 chan ? chan->uniqueid : "<null>", 03573 S_OR(in->cid_num, "<unknown>"), 03574 S_OR(in->cid_name, "<unknown>") 03575 ); 03576 03577 /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */ 03578 if (chan) { 03579 ast_channel_unlock(chan); 03580 } 03581 ast_free(in); 03582 return NULL; 03583 }
static void free_channelvars | ( | void | ) | [static] |
Definition at line 6624 of file manager.c.
References ast_free, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, manager_channel_variable::entry, and var.
Referenced by __init_manager().
06625 { 06626 struct manager_channel_variable *var; 06627 AST_RWLIST_WRLOCK(&channelvars); 06628 while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) { 06629 ast_free(var); 06630 } 06631 AST_RWLIST_UNLOCK(&channelvars); 06632 }
static int get_input | ( | struct mansession * | s, | |
char * | output | |||
) | [static] |
Read one full line (including crlf) from the manager socket.
* \r\n is the only valid terminator for the line. * (Note that, later, '\0' will be considered as the end-of-line marker, * so everything between the '\0' and the '\r\n' will not be used). * Also note that we assume output to have at least "maxlen" space. *
Definition at line 4519 of file manager.c.
References mansession_session::inbuf, mansession_session::inlen, mansession::session, and ast_frame::src.
04520 { 04521 int res, x; 04522 int maxlen = sizeof(s->session->inbuf) - 1; 04523 char *src = s->session->inbuf; 04524 int timeout = -1; 04525 time_t now; 04526 04527 /* 04528 * Look for \r\n within the buffer. If found, copy to the output 04529 * buffer and return, trimming the \r\n (not used afterwards). 04530 */ 04531 for (x = 0; x < s->session->inlen; x++) { 04532 int cr; /* set if we have \r */ 04533 if (src[x] == '\r' && x+1 < s->session->inlen && src[x + 1] == '\n') { 04534 cr = 2; /* Found. Update length to include \r\n */ 04535 } else if (src[x] == '\n') { 04536 cr = 1; /* also accept \n only */ 04537 } else { 04538 continue; 04539 } 04540 memmove(output, src, x); /*... but trim \r\n */ 04541 output[x] = '\0'; /* terminate the string */ 04542 x += cr; /* number of bytes used */ 04543 s->session->inlen -= x; /* remaining size */ 04544 memmove(src, src + x, s->session->inlen); /* remove used bytes */ 04545 return 1; 04546 } 04547 if (s->session->inlen >= maxlen) { 04548 /* no crlf found, and buffer full - sorry, too long for us */ 04549 ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", ast_inet_ntoa(s->session->sin.sin_addr), src); 04550 s->session->inlen = 0; 04551 } 04552 res = 0; 04553 while (res == 0) { 04554 /* calculate a timeout if we are not authenticated */ 04555 if (!s->session->authenticated) { 04556 if(time(&now) == -1) { 04557 ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); 04558 return -1; 04559 } 04560 04561 timeout = (authtimeout - (now - s->session->authstart)) * 1000; 04562 if (timeout < 0) { 04563 /* we have timed out */ 04564 return 0; 04565 } 04566 } 04567 04568 ao2_lock(s->session); 04569 if (s->session->pending_event) { 04570 s->session->pending_event = 0; 04571 ao2_unlock(s->session); 04572 return 0; 04573 } 04574 s->session->waiting_thread = pthread_self(); 04575 ao2_unlock(s->session); 04576 04577 res = ast_wait_for_input(s->session->fd, timeout); 04578 04579 ao2_lock(s->session); 04580 s->session->waiting_thread = AST_PTHREADT_NULL; 04581 ao2_unlock(s->session); 04582 } 04583 if (res < 0) { 04584 /* If we get a signal from some other thread (typically because 04585 * there are new events queued), return 0 to notify the caller. 04586 */ 04587 if (errno == EINTR || errno == EAGAIN) { 04588 return 0; 04589 } 04590 ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno)); 04591 return -1; 04592 } 04593 04594 ao2_lock(s->session); 04595 res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f); 04596 if (res < 1) { 04597 res = -1; /* error return */ 04598 } else { 04599 s->session->inlen += res; 04600 src[s->session->inlen] = '\0'; 04601 res = 0; 04602 } 04603 ao2_unlock(s->session); 04604 return res; 04605 }
static struct ast_manager_user* get_manager_by_name_locked | ( | const char * | name | ) | [static] |
lookup an entry in the list of registered users. must be called with the list lock held.
Definition at line 1334 of file manager.c.
References AST_RWLIST_TRAVERSE, ast_manager_user::list, and user.
Referenced by authenticate(), handle_showmanager(), and manager_displayconnects().
01335 { 01336 struct ast_manager_user *user = NULL; 01337 01338 AST_RWLIST_TRAVERSE(&users, user, list) { 01339 if (!strcasecmp(user->username, name)) { 01340 break; 01341 } 01342 } 01343 01344 return user; 01345 }
static int get_perm | ( | const char * | instr | ) | [static] |
Definition at line 1176 of file manager.c.
References ARRAY_LEN, ast_instring(), permalias::num, and perms.
Referenced by strings_to_mask().
01177 { 01178 int x = 0, ret = 0; 01179 01180 if (!instr) { 01181 return 0; 01182 } 01183 01184 for (x = 0; x < ARRAY_LEN(perms); x++) { 01185 if (ast_instring(instr, perms[x].label, ',')) { 01186 ret |= perms[x].num; 01187 } 01188 } 01189 01190 return ret; 01191 }
static struct eventqent* grab_last | ( | void | ) | [static] |
Grab a reference to the last event, update usecount as needed. Can handle a NULL pointer.
Definition at line 1056 of file manager.c.
References ast_atomic_fetchadd_int(), AST_RWLIST_LAST, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and eventqent::usecount.
Referenced by session_do().
01057 { 01058 struct eventqent *ret; 01059 01060 AST_RWLIST_WRLOCK(&all_events); 01061 ret = AST_RWLIST_LAST(&all_events); 01062 /* the list is never empty now, but may become so when 01063 * we optimize it in the future, so be prepared. 01064 */ 01065 if (ret) { 01066 ast_atomic_fetchadd_int(&ret->usecount, 1); 01067 } 01068 AST_RWLIST_UNLOCK(&all_events); 01069 return ret; 01070 }
static char* handle_manager_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
CLI command manager reload.
Definition at line 1668 of file manager.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, reload_manager(), and ast_cli_entry::usage.
01669 { 01670 switch (cmd) { 01671 case CLI_INIT: 01672 e->command = "manager reload"; 01673 e->usage = 01674 "Usage: manager reload\n" 01675 " Reloads the manager configuration.\n"; 01676 return NULL; 01677 case CLI_GENERATE: 01678 return NULL; 01679 } 01680 if (a->argc > 2) { 01681 return CLI_SHOWUSAGE; 01682 } 01683 reload_manager(); 01684 return CLI_SUCCESS; 01685 }
static char* handle_mandebug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1443 of file manager.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, manager_debug, and ast_cli_entry::usage.
01444 { 01445 switch (cmd) { 01446 case CLI_INIT: 01447 e->command = "manager set debug [on|off]"; 01448 e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n"; 01449 return NULL; 01450 case CLI_GENERATE: 01451 return NULL; 01452 } 01453 01454 if (a->argc == 3) { 01455 ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off"); 01456 } else if (a->argc == 4) { 01457 if (!strcasecmp(a->argv[3], "on")) { 01458 manager_debug = 1; 01459 } else if (!strcasecmp(a->argv[3], "off")) { 01460 manager_debug = 0; 01461 } else { 01462 return CLI_SHOWUSAGE; 01463 } 01464 } 01465 return CLI_SUCCESS; 01466 }
static char* handle_showmanager | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1468 of file manager.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_strdup, authority_to_str(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_manager_by_name_locked(), ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, user, and ast_cli_args::word.
01469 { 01470 struct ast_manager_user *user = NULL; 01471 int l, which; 01472 char *ret = NULL; 01473 struct ast_str *rauthority = ast_str_alloca(128); 01474 struct ast_str *wauthority = ast_str_alloca(128); 01475 01476 switch (cmd) { 01477 case CLI_INIT: 01478 e->command = "manager show user"; 01479 e->usage = 01480 " Usage: manager show user <user>\n" 01481 " Display all information related to the manager user specified.\n"; 01482 return NULL; 01483 case CLI_GENERATE: 01484 l = strlen(a->word); 01485 which = 0; 01486 if (a->pos != 3) { 01487 return NULL; 01488 } 01489 AST_RWLIST_RDLOCK(&users); 01490 AST_RWLIST_TRAVERSE(&users, user, list) { 01491 if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) { 01492 ret = ast_strdup(user->username); 01493 break; 01494 } 01495 } 01496 AST_RWLIST_UNLOCK(&users); 01497 return ret; 01498 } 01499 01500 if (a->argc != 4) { 01501 return CLI_SHOWUSAGE; 01502 } 01503 01504 AST_RWLIST_RDLOCK(&users); 01505 01506 if (!(user = get_manager_by_name_locked(a->argv[3]))) { 01507 ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]); 01508 AST_RWLIST_UNLOCK(&users); 01509 return CLI_SUCCESS; 01510 } 01511 01512 ast_cli(a->fd, "\n"); 01513 ast_cli(a->fd, 01514 " username: %s\n" 01515 " secret: %s\n" 01516 " acl: %s\n" 01517 " read perm: %s\n" 01518 " write perm: %s\n" 01519 "displayconnects: %s\n", 01520 (user->username ? user->username : "(N/A)"), 01521 (user->secret ? "<Set>" : "(N/A)"), 01522 (user->ha ? "yes" : "no"), 01523 authority_to_str(user->readperm, &rauthority), 01524 authority_to_str(user->writeperm, &wauthority), 01525 (user->displayconnects ? "yes" : "no")); 01526 01527 AST_RWLIST_UNLOCK(&users); 01528 01529 return CLI_SUCCESS; 01530 }
static char* handle_showmanagers | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1532 of file manager.c.
References ast_cli_args::argc, ast_cli(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_manager_user::list, ast_cli_entry::usage, and user.
01533 { 01534 struct ast_manager_user *user = NULL; 01535 int count_amu = 0; 01536 switch (cmd) { 01537 case CLI_INIT: 01538 e->command = "manager show users"; 01539 e->usage = 01540 "Usage: manager show users\n" 01541 " Prints a listing of all managers that are currently configured on that\n" 01542 " system.\n"; 01543 return NULL; 01544 case CLI_GENERATE: 01545 return NULL; 01546 } 01547 if (a->argc != 3) { 01548 return CLI_SHOWUSAGE; 01549 } 01550 01551 AST_RWLIST_RDLOCK(&users); 01552 01553 /* If there are no users, print out something along those lines */ 01554 if (AST_RWLIST_EMPTY(&users)) { 01555 ast_cli(a->fd, "There are no manager users.\n"); 01556 AST_RWLIST_UNLOCK(&users); 01557 return CLI_SUCCESS; 01558 } 01559 01560 ast_cli(a->fd, "\nusername\n--------\n"); 01561 01562 AST_RWLIST_TRAVERSE(&users, user, list) { 01563 ast_cli(a->fd, "%s\n", user->username); 01564 count_amu++; 01565 } 01566 01567 AST_RWLIST_UNLOCK(&users); 01568 01569 ast_cli(a->fd,"-------------------\n" 01570 "%d manager users configured.\n", count_amu); 01571 return CLI_SUCCESS; 01572 }
static char* handle_showmancmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1365 of file manager.c.
References manager_action::action, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_strdup, AST_XML_DOC, ast_xmldoc_printable(), manager_action::authority, authority_to_str(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, COLOR_MAGENTA, ast_cli_entry::command, manager_action::docsrc, ast_cli_args::fd, ast_cli_args::n, S_OR, term_color(), ast_cli_entry::usage, and ast_cli_args::word.
01366 { 01367 struct manager_action *cur; 01368 struct ast_str *authority; 01369 int num, l, which; 01370 char *ret = NULL; 01371 #ifdef AST_XML_DOCS 01372 char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64]; 01373 #endif 01374 01375 switch (cmd) { 01376 case CLI_INIT: 01377 e->command = "manager show command"; 01378 e->usage = 01379 "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n" 01380 " Shows the detailed description for a specific Asterisk manager interface command.\n"; 01381 return NULL; 01382 case CLI_GENERATE: 01383 l = strlen(a->word); 01384 which = 0; 01385 AST_RWLIST_RDLOCK(&actions); 01386 AST_RWLIST_TRAVERSE(&actions, cur, list) { 01387 if (!strncasecmp(a->word, cur->action, l) && ++which > a->n) { 01388 ret = ast_strdup(cur->action); 01389 break; /* make sure we exit even if ast_strdup() returns NULL */ 01390 } 01391 } 01392 AST_RWLIST_UNLOCK(&actions); 01393 return ret; 01394 } 01395 authority = ast_str_alloca(80); 01396 if (a->argc < 4) { 01397 return CLI_SHOWUSAGE; 01398 } 01399 01400 #ifdef AST_XML_DOCS 01401 /* setup the titles */ 01402 term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01403 term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40); 01404 term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01405 term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40); 01406 term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 01407 #endif 01408 01409 AST_RWLIST_RDLOCK(&actions); 01410 AST_RWLIST_TRAVERSE(&actions, cur, list) { 01411 for (num = 3; num < a->argc; num++) { 01412 if (!strcasecmp(cur->action, a->argv[num])) { 01413 #ifdef AST_XML_DOCS 01414 if (cur->docsrc == AST_XML_DOC) { 01415 ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n", 01416 syntax_title, 01417 ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1), 01418 synopsis_title, 01419 ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1), 01420 description_title, 01421 ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1), 01422 arguments_title, 01423 ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1), 01424 seealso_title, 01425 ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1)); 01426 } else { 01427 #endif 01428 ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n", 01429 cur->action, cur->synopsis, 01430 authority_to_str(cur->authority, &authority), 01431 S_OR(cur->description, "")); 01432 #ifdef AST_XML_DOCS 01433 } 01434 #endif 01435 } 01436 } 01437 } 01438 AST_RWLIST_UNLOCK(&actions); 01439 01440 return CLI_SUCCESS; 01441 }
static char* handle_showmancmds | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
CLI command manager list commands.
Definition at line 1575 of file manager.c.
References manager_action::action, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, manager_action::authority, authority_to_str(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, HSMC_FORMAT, and ast_cli_entry::usage.
01576 { 01577 struct manager_action *cur; 01578 struct ast_str *authority; 01579 #define HSMC_FORMAT " %-15.15s %-15.15s %-55.55s\n" 01580 switch (cmd) { 01581 case CLI_INIT: 01582 e->command = "manager show commands"; 01583 e->usage = 01584 "Usage: manager show commands\n" 01585 " Prints a listing of all the available Asterisk manager interface commands.\n"; 01586 return NULL; 01587 case CLI_GENERATE: 01588 return NULL; 01589 } 01590 authority = ast_str_alloca(80); 01591 ast_cli(a->fd, HSMC_FORMAT, "Action", "Privilege", "Synopsis"); 01592 ast_cli(a->fd, HSMC_FORMAT, "------", "---------", "--------"); 01593 01594 AST_RWLIST_RDLOCK(&actions); 01595 AST_RWLIST_TRAVERSE(&actions, cur, list) 01596 ast_cli(a->fd, HSMC_FORMAT, cur->action, authority_to_str(cur->authority, &authority), cur->synopsis); 01597 AST_RWLIST_UNLOCK(&actions); 01598 01599 return CLI_SUCCESS; 01600 }
static char* handle_showmanconn | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
CLI command manager list connected.
Definition at line 1603 of file manager.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_cli(), ast_inet_ntoa(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, HSMCONN_FORMAT1, HSMCONN_FORMAT2, unref_mansession(), and ast_cli_entry::usage.
01604 { 01605 struct mansession_session *session; 01606 time_t now = time(NULL); 01607 #define HSMCONN_FORMAT1 " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n" 01608 #define HSMCONN_FORMAT2 " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n" 01609 int count = 0; 01610 struct ao2_iterator i; 01611 01612 switch (cmd) { 01613 case CLI_INIT: 01614 e->command = "manager show connected"; 01615 e->usage = 01616 "Usage: manager show connected\n" 01617 " Prints a listing of the users that are currently connected to the\n" 01618 "Asterisk manager interface.\n"; 01619 return NULL; 01620 case CLI_GENERATE: 01621 return NULL; 01622 } 01623 01624 ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write"); 01625 01626 i = ao2_iterator_init(sessions, 0); 01627 while ((session = ao2_iterator_next(&i))) { 01628 ao2_lock(session); 01629 ast_cli(a->fd, HSMCONN_FORMAT2, session->username, ast_inet_ntoa(session->sin.sin_addr), (int)(session->sessionstart), (int)(now - session->sessionstart), session->fd, session->inuse, session->readperm, session->writeperm); 01630 count++; 01631 ao2_unlock(session); 01632 unref_mansession(session); 01633 } 01634 ao2_iterator_destroy(&i); 01635 ast_cli(a->fd, "%d users connected.\n", count); 01636 01637 return CLI_SUCCESS; 01638 }
static char* handle_showmaneventq | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
CLI command manager list eventq.
Definition at line 1642 of file manager.c.
References ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, eventqent::category, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, eventqent::eq_next, eventqent::eventdata, ast_cli_args::fd, ast_cli_entry::usage, and eventqent::usecount.
01643 { 01644 struct eventqent *s; 01645 switch (cmd) { 01646 case CLI_INIT: 01647 e->command = "manager show eventq"; 01648 e->usage = 01649 "Usage: manager show eventq\n" 01650 " Prints a listing of all events pending in the Asterisk manger\n" 01651 "event queue.\n"; 01652 return NULL; 01653 case CLI_GENERATE: 01654 return NULL; 01655 } 01656 AST_RWLIST_RDLOCK(&all_events); 01657 AST_RWLIST_TRAVERSE(&all_events, s, eq_next) { 01658 ast_cli(a->fd, "Usecount: %d\n", s->usecount); 01659 ast_cli(a->fd, "Category: %d\n", s->category); 01660 ast_cli(a->fd, "Event:\n%s", s->eventdata); 01661 } 01662 AST_RWLIST_UNLOCK(&all_events); 01663 01664 return CLI_SUCCESS; 01665 }
static enum error_type handle_updates | ( | struct mansession * | s, | |
const struct message * | m, | |||
struct ast_config * | cfg, | |||
const char * | dfn | |||
) | [static] |
Definition at line 2515 of file manager.c.
References ast_category_append(), ast_category_delete(), ast_category_empty(), ast_category_get(), ast_category_insert(), ast_category_new(), ast_category_rename(), ast_free, ast_log(), ast_str_create(), ast_strlen_zero(), ast_variable_append(), ast_variable_delete(), ast_variable_insert(), ast_variable_new(), ast_variable_update(), astman_get_header(), FAILURE_ALLOCATION, FAILURE_DELCAT, FAILURE_DELETE, FAILURE_EMPTYCAT, FAILURE_NEWCAT, FAILURE_UPDATE, LOG_WARNING, match(), ast_variable::object, UNKNOWN_ACTION, UNKNOWN_CATEGORY, UNSPECIFIED_ARGUMENT, UNSPECIFIED_CATEGORY, value, and var.
Referenced by action_updateconfig().
02516 { 02517 int x; 02518 char hdr[40]; 02519 const char *action, *cat, *var, *value, *match, *line; 02520 struct ast_category *category; 02521 struct ast_variable *v; 02522 struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16); 02523 enum error_type result = 0; 02524 02525 for (x = 0; x < 100000; x++) { /* 100000 = the max number of allowed updates + 1 */ 02526 unsigned int object = 0; 02527 02528 snprintf(hdr, sizeof(hdr), "Action-%06d", x); 02529 action = astman_get_header(m, hdr); 02530 if (ast_strlen_zero(action)) /* breaks the for loop if no action header */ 02531 break; /* this could cause problems if actions come in misnumbered */ 02532 02533 snprintf(hdr, sizeof(hdr), "Cat-%06d", x); 02534 cat = astman_get_header(m, hdr); 02535 if (ast_strlen_zero(cat)) { /* every action needs a category */ 02536 result = UNSPECIFIED_CATEGORY; 02537 break; 02538 } 02539 02540 snprintf(hdr, sizeof(hdr), "Var-%06d", x); 02541 var = astman_get_header(m, hdr); 02542 02543 snprintf(hdr, sizeof(hdr), "Value-%06d", x); 02544 value = astman_get_header(m, hdr); 02545 02546 if (!ast_strlen_zero(value) && *value == '>') { 02547 object = 1; 02548 value++; 02549 } 02550 02551 snprintf(hdr, sizeof(hdr), "Match-%06d", x); 02552 match = astman_get_header(m, hdr); 02553 02554 snprintf(hdr, sizeof(hdr), "Line-%06d", x); 02555 line = astman_get_header(m, hdr); 02556 02557 if (!strcasecmp(action, "newcat")) { 02558 if (ast_category_get(cfg,cat)) { /* check to make sure the cat doesn't */ 02559 result = FAILURE_NEWCAT; /* already exist */ 02560 break; 02561 } 02562 if (!(category = ast_category_new(cat, dfn, -1))) { 02563 result = FAILURE_ALLOCATION; 02564 break; 02565 } 02566 if (ast_strlen_zero(match)) { 02567 ast_category_append(cfg, category); 02568 } else { 02569 ast_category_insert(cfg, category, match); 02570 } 02571 } else if (!strcasecmp(action, "renamecat")) { 02572 if (ast_strlen_zero(value)) { 02573 result = UNSPECIFIED_ARGUMENT; 02574 break; 02575 } 02576 if (!(category = ast_category_get(cfg, cat))) { 02577 result = UNKNOWN_CATEGORY; 02578 break; 02579 } 02580 ast_category_rename(category, value); 02581 } else if (!strcasecmp(action, "delcat")) { 02582 if (ast_category_delete(cfg, cat)) { 02583 result = FAILURE_DELCAT; 02584 break; 02585 } 02586 } else if (!strcasecmp(action, "emptycat")) { 02587 if (ast_category_empty(cfg, cat)) { 02588 result = FAILURE_EMPTYCAT; 02589 break; 02590 } 02591 } else if (!strcasecmp(action, "update")) { 02592 if (ast_strlen_zero(var)) { 02593 result = UNSPECIFIED_ARGUMENT; 02594 break; 02595 } 02596 if (!(category = ast_category_get(cfg,cat))) { 02597 result = UNKNOWN_CATEGORY; 02598 break; 02599 } 02600 if (ast_variable_update(category, var, value, match, object)) { 02601 result = FAILURE_UPDATE; 02602 break; 02603 } 02604 } else if (!strcasecmp(action, "delete")) { 02605 if ((ast_strlen_zero(var) && ast_strlen_zero(line))) { 02606 result = UNSPECIFIED_ARGUMENT; 02607 break; 02608 } 02609 if (!(category = ast_category_get(cfg, cat))) { 02610 result = UNKNOWN_CATEGORY; 02611 break; 02612 } 02613 if (ast_variable_delete(category, var, match, line)) { 02614 result = FAILURE_DELETE; 02615 break; 02616 } 02617 } else if (!strcasecmp(action, "append")) { 02618 if (ast_strlen_zero(var)) { 02619 result = UNSPECIFIED_ARGUMENT; 02620 break; 02621 } 02622 if (!(category = ast_category_get(cfg, cat))) { 02623 result = UNKNOWN_CATEGORY; 02624 break; 02625 } 02626 if (!(v = ast_variable_new(var, value, dfn))) { 02627 result = FAILURE_ALLOCATION; 02628 break; 02629 } 02630 if (object || (match && !strcasecmp(match, "object"))) { 02631 v->object = 1; 02632 } 02633 ast_variable_append(category, v); 02634 } else if (!strcasecmp(action, "insert")) { 02635 if (ast_strlen_zero(var) || ast_strlen_zero(line)) { 02636 result = UNSPECIFIED_ARGUMENT; 02637 break; 02638 } 02639 if (!(category = ast_category_get(cfg, cat))) { 02640 result = UNKNOWN_CATEGORY; 02641 break; 02642 } 02643 if (!(v = ast_variable_new(var, value, dfn))) { 02644 result = FAILURE_ALLOCATION; 02645 break; 02646 } 02647 ast_variable_insert(category, v, line); 02648 } 02649 else { 02650 ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action); 02651 result = UNKNOWN_ACTION; 02652 break; 02653 } 02654 } 02655 ast_free(str1); 02656 ast_free(str2); 02657 return result; 02658 }
static void json_escape | ( | char * | out, | |
const char * | in | |||
) | [static] |
The amount of space in out must be at least ( 2 * strlen(in) + 1 )
Definition at line 2434 of file manager.c.
Referenced by action_getconfigjson().
02435 { 02436 for (; *in; in++) { 02437 if (*in == '\\' || *in == '\"') { 02438 *out++ = '\\'; 02439 } 02440 *out++ = *in; 02441 } 02442 *out = '\0'; 02443 }
static int manager_displayconnects | ( | struct mansession_session * | session | ) | [static] |
Get displayconnects config option.
session | manager session to get parameter from. |
Definition at line 1351 of file manager.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, get_manager_by_name_locked(), user, and mansession_session::username.
Referenced by action_login(), purge_sessions(), and session_do().
01352 { 01353 struct ast_manager_user *user = NULL; 01354 int ret = 0; 01355 01356 AST_RWLIST_RDLOCK(&users); 01357 if ((user = get_manager_by_name_locked (session->username))) { 01358 ret = user->displayconnects; 01359 } 01360 AST_RWLIST_UNLOCK(&users); 01361 01362 return ret; 01363 }
static int manager_modulecheck | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4326 of file manager.c.
References ast_copy_string(), ast_file_version_find(), ast_log(), ast_module_check(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), LOG_DEBUG, and version.
Referenced by __init_manager().
04327 { 04328 int res; 04329 const char *module = astman_get_header(m, "Module"); 04330 const char *id = astman_get_header(m, "ActionID"); 04331 char idText[256]; 04332 #if !defined(LOW_MEMORY) 04333 const char *version; 04334 #endif 04335 char filename[PATH_MAX]; 04336 char *cut; 04337 04338 ast_copy_string(filename, module, sizeof(filename)); 04339 if ((cut = strchr(filename, '.'))) { 04340 *cut = '\0'; 04341 } else { 04342 cut = filename + strlen(filename); 04343 } 04344 snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".so"); 04345 ast_log(LOG_DEBUG, "**** ModuleCheck .so file %s\n", filename); 04346 res = ast_module_check(filename); 04347 if (!res) { 04348 astman_send_error(s, m, "Module not loaded"); 04349 return 0; 04350 } 04351 snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".c"); 04352 ast_log(LOG_DEBUG, "**** ModuleCheck .c file %s\n", filename); 04353 #if !defined(LOW_MEMORY) 04354 version = ast_file_version_find(filename); 04355 #endif 04356 04357 if (!ast_strlen_zero(id)) { 04358 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 04359 } else { 04360 idText[0] = '\0'; 04361 } 04362 astman_append(s, "Response: Success\r\n%s", idText); 04363 #if !defined(LOW_MEMORY) 04364 astman_append(s, "Version: %s\r\n\r\n", version ? version : ""); 04365 #endif 04366 return 0; 04367 }
static int manager_moduleload | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4369 of file manager.c.
References AST_FORCE_SOFT, ast_load_resource(), ast_module_reload(), ast_unload_resource(), astman_get_header(), astman_send_ack(), and astman_send_error().
Referenced by __init_manager().
04370 { 04371 int res; 04372 const char *module = astman_get_header(m, "Module"); 04373 const char *loadtype = astman_get_header(m, "LoadType"); 04374 04375 if (!loadtype || strlen(loadtype) == 0) { 04376 astman_send_error(s, m, "Incomplete ModuleLoad action."); 04377 } 04378 if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0) { 04379 astman_send_error(s, m, "Need module name"); 04380 } 04381 04382 if (!strcasecmp(loadtype, "load")) { 04383 res = ast_load_resource(module); 04384 if (res) { 04385 astman_send_error(s, m, "Could not load module."); 04386 } else { 04387 astman_send_ack(s, m, "Module loaded."); 04388 } 04389 } else if (!strcasecmp(loadtype, "unload")) { 04390 res = ast_unload_resource(module, AST_FORCE_SOFT); 04391 if (res) { 04392 astman_send_error(s, m, "Could not unload module."); 04393 } else { 04394 astman_send_ack(s, m, "Module unloaded."); 04395 } 04396 } else if (!strcasecmp(loadtype, "reload")) { 04397 if (module != NULL) { 04398 res = ast_module_reload(module); 04399 if (res == 0) { 04400 astman_send_error(s, m, "No such module."); 04401 } else if (res == 1) { 04402 astman_send_error(s, m, "Module does not support reload action."); 04403 } else { 04404 astman_send_ack(s, m, "Module reloaded."); 04405 } 04406 } else { 04407 ast_module_reload(NULL); /* Reload all modules */ 04408 astman_send_ack(s, m, "All modules reloaded"); 04409 } 04410 } else 04411 astman_send_error(s, m, "Incomplete ModuleLoad action."); 04412 return 0; 04413 }
static int manager_state_cb | ( | char * | context, | |
char * | exten, | |||
int | state, | |||
void * | data | |||
) | [static] |
Definition at line 4944 of file manager.c.
References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.
Referenced by __init_manager().
04945 { 04946 /* Notify managers of change */ 04947 char hint[512]; 04948 ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten); 04949 04950 manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state); 04951 return 0; 04952 }
static int mansession_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1303 of file manager.c.
References CMP_MATCH, str, and mansession_session::username.
01304 { 01305 struct mansession_session *s = obj; 01306 char *str = arg; 01307 return !strcasecmp(s->username, str) ? CMP_MATCH : 0; 01308 }
static struct sockaddr_in* mansession_encode_sin_local | ( | const struct mansession * | s, | |
struct sockaddr_in * | sin_local | |||
) | [static] |
Definition at line 2001 of file manager.c.
References ast_sockaddr_to_sin, ast_tcptls_session_args::local_address, ast_tcptls_session_instance::parent, and mansession::tcptls_session.
Referenced by report_auth_success(), report_failed_acl(), report_failed_challenge_response(), report_inval_password(), report_invalid_user(), report_req_bad_format(), report_req_not_allowed(), and report_session_limit().
02003 { 02004 ast_sockaddr_to_sin(&s->tcptls_session->parent->local_address, 02005 sin_local); 02006 02007 return sin_local; 02008 }
static enum ast_security_event_transport_type mansession_get_transport | ( | const struct mansession * | s | ) | [static] |
Definition at line 1995 of file manager.c.
References AST_SECURITY_EVENT_TRANSPORT_TCP, AST_SECURITY_EVENT_TRANSPORT_TLS, ast_tcptls_session_instance::parent, mansession::tcptls_session, and ast_tcptls_session_args::tls_cfg.
Referenced by report_auth_success(), report_failed_acl(), report_failed_challenge_response(), report_inval_password(), report_invalid_user(), report_req_bad_format(), report_req_not_allowed(), and report_session_limit().
01996 { 01997 return s->tcptls_session->parent->tls_cfg ? AST_SECURITY_EVENT_TRANSPORT_TLS : 01998 AST_SECURITY_EVENT_TRANSPORT_TCP; 01999 }
static void mansession_lock | ( | struct mansession * | s | ) | [static] |
Lock the 'mansession' structure.
Definition at line 1967 of file manager.c.
References ast_mutex_lock, and mansession::lock.
Referenced by action_challenge(), and process_message().
01968 { 01969 ast_mutex_lock(&s->lock); 01970 }
static void mansession_unlock | ( | struct mansession * | s | ) | [static] |
Unlock the 'mansession' structure.
Definition at line 1973 of file manager.c.
References ast_mutex_unlock, and mansession::lock.
Referenced by action_challenge(), and process_message().
01974 { 01975 ast_mutex_unlock(&s->lock); 01976 }
static int match_filter | ( | struct mansession * | s, | |
char * | eventdata | |||
) | [static] |
Definition at line 4078 of file manager.c.
References ao2_container_count(), ao2_t_callback_data, ast_debug, blackfilter_cmp_fn(), mansession_session::blackfilters, OBJ_NODATA, mansession::session, whitefilter_cmp_fn(), and mansession_session::whitefilters.
Referenced by process_events().
04079 { 04080 int result = 0; 04081 04082 ast_debug(3, "Examining event:\n%s\n", eventdata); 04083 if (!ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) { 04084 return 1; /* no filtering means match all */ 04085 } else if (ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) { 04086 /* white filters only: implied black all filter processed first, then white filters */ 04087 ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04088 } else if (!ao2_container_count(s->session->whitefilters) && ao2_container_count(s->session->blackfilters)) { 04089 /* black filters only: implied white all filter processed first, then black filters */ 04090 ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04091 } else { 04092 /* white and black filters: implied black all filter processed first, then white filters, and lastly black filters */ 04093 ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04094 if (result) { 04095 result = 0; 04096 ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04097 } 04098 } 04099 04100 return result; 04101 }
static int process_events | ( | struct mansession * | s | ) | [static] |
Send any applicable events to the client listening on this socket. Wait only for a finite time on each event, and drop all events whether they are successfully sent or not.
Definition at line 4108 of file manager.c.
References advance_event(), ao2_lock, ao2_unlock, mansession_session::authenticated, eventqent::category, eventqent::eventdata, mansession_session::f, mansession_session::last_ev, match_filter(), mansession_session::readperm, mansession_session::send_events, send_string(), and mansession::session.
Referenced by do_message(), and process_message().
04109 { 04110 int ret = 0; 04111 04112 ao2_lock(s->session); 04113 if (s->session->f != NULL) { 04114 struct eventqent *eqe = s->session->last_ev; 04115 04116 while ((eqe = advance_event(eqe))) { 04117 if (!ret && s->session->authenticated && 04118 (s->session->readperm & eqe->category) == eqe->category && 04119 (s->session->send_events & eqe->category) == eqe->category) { 04120 if (match_filter(s, eqe->eventdata)) { 04121 if (send_string(s, eqe->eventdata) < 0) 04122 ret = -1; /* don't send more */ 04123 } 04124 } 04125 s->session->last_ev = eqe; 04126 } 04127 } 04128 ao2_unlock(s->session); 04129 return ret; 04130 }
static int process_message | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4428 of file manager.c.
References __astman_get_header(), manager_action::action, allowmultiplelogin, ast_copy_string(), ast_debug, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strlen_zero(), astman_get_header(), astman_send_error(), mansession_session::authenticated, manager_action::authority, check_manager_session_inuse(), manager_action::func, GET_HEADER_SKIP_EMPTY, mansession_lock(), mansession_unlock(), process_events(), report_req_bad_format(), report_req_not_allowed(), report_session_limit(), mansession::session, and mansession_session::writeperm.
Referenced by do_message().
04429 { 04430 char action[80] = ""; 04431 int ret = 0; 04432 struct manager_action *tmp; 04433 const char *user = astman_get_header(m, "Username"); 04434 int (*call_func)(struct mansession *s, const struct message *m) = NULL; 04435 04436 ast_copy_string(action, __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY), sizeof(action)); 04437 04438 if (ast_strlen_zero(action)) { 04439 report_req_bad_format(s, "NONE"); 04440 mansession_lock(s); 04441 astman_send_error(s, m, "Missing action in request"); 04442 mansession_unlock(s); 04443 return 0; 04444 } 04445 04446 if (!s->session->authenticated && strcasecmp(action, "Login") && strcasecmp(action, "Logoff") && strcasecmp(action, "Challenge")) { 04447 if (!s->session->authenticated) { 04448 report_req_not_allowed(s, action); 04449 } 04450 mansession_lock(s); 04451 astman_send_error(s, m, "Permission denied"); 04452 mansession_unlock(s); 04453 return 0; 04454 } 04455 04456 if (!allowmultiplelogin && !s->session->authenticated && user && 04457 (!strcasecmp(action, "Login") || !strcasecmp(action, "Challenge"))) { 04458 if (check_manager_session_inuse(user)) { 04459 report_session_limit(s); 04460 sleep(1); 04461 mansession_lock(s); 04462 astman_send_error(s, m, "Login Already In Use"); 04463 mansession_unlock(s); 04464 return -1; 04465 } 04466 } 04467 04468 AST_RWLIST_RDLOCK(&actions); 04469 AST_RWLIST_TRAVERSE(&actions, tmp, list) { 04470 if (strcasecmp(action, tmp->action)) { 04471 continue; 04472 } 04473 if (s->session->writeperm & tmp->authority || tmp->authority == 0) { 04474 call_func = tmp->func; 04475 } else { 04476 astman_send_error(s, m, "Permission denied"); 04477 report_req_not_allowed(s, action); 04478 } 04479 break; 04480 } 04481 AST_RWLIST_UNLOCK(&actions); 04482 04483 if (tmp && call_func) { 04484 /* call AMI function after actions list are unlocked */ 04485 ast_debug(1, "Running action '%s'\n", tmp->action); 04486 ret = call_func(s, m); 04487 } else { 04488 char buf[512]; 04489 if (!tmp) { 04490 report_req_bad_format(s, action); 04491 } 04492 snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action); 04493 mansession_lock(s); 04494 astman_send_error(s, m, buf); 04495 mansession_unlock(s); 04496 } 04497 if (ret) { 04498 return ret; 04499 } 04500 /* Once done with our message, deliver any pending events unless the 04501 requester doesn't want them as part of this response. 04502 */ 04503 if (ast_strlen_zero(astman_get_header(m, "SuppressEvents"))) { 04504 return process_events(s); 04505 } else { 04506 return ret; 04507 } 04508 }
static void purge_events | ( | void | ) | [static] |
Purge unused events. Remove elements from the head as long as their usecount is 0 and there is a next element.
Definition at line 1076 of file manager.c.
References ast_free, AST_RWLIST_FIRST, AST_RWLIST_NEXT, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_tvdiff_sec(), ast_tvnow(), eventqent::eq_next, eventqent::tv, and eventqent::usecount.
Referenced by purge_old_stuff().
01077 { 01078 struct eventqent *ev; 01079 struct timeval now = ast_tvnow(); 01080 01081 AST_RWLIST_WRLOCK(&all_events); 01082 while ( (ev = AST_RWLIST_FIRST(&all_events)) && 01083 ev->usecount == 0 && AST_RWLIST_NEXT(ev, eq_next)) { 01084 AST_RWLIST_REMOVE_HEAD(&all_events, eq_next); 01085 ast_free(ev); 01086 } 01087 01088 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&all_events, ev, eq_next) { 01089 /* Never release the last event */ 01090 if (!AST_RWLIST_NEXT(ev, eq_next)) { 01091 break; 01092 } 01093 01094 /* 2.5 times whatever the HTTP timeout is (maximum 2.5 hours) is the maximum time that we will definitely cache an event */ 01095 if (ev->usecount == 0 && ast_tvdiff_sec(now, ev->tv) > (httptimeout > 3600 ? 3600 : httptimeout) * 2.5) { 01096 AST_RWLIST_REMOVE_CURRENT(eq_next); 01097 ast_free(ev); 01098 } 01099 } 01100 AST_RWLIST_TRAVERSE_SAFE_END; 01101 AST_RWLIST_UNLOCK(&all_events); 01102 }
static void purge_sessions | ( | int | n_max | ) | [static] |
remove at most n_max stale session from the list.
Definition at line 4754 of file manager.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_inet_ntoa(), ast_verb, mansession_session::authenticated, mansession_session::inuse, manager_displayconnects(), session_destroy(), mansession_session::sessiontimeout, mansession_session::sin, unref_mansession(), mansession_session::username, and VERBOSITY_ATLEAST.
Referenced by purge_old_stuff().
04755 { 04756 struct mansession_session *session; 04757 time_t now = time(NULL); 04758 struct ao2_iterator i; 04759 04760 i = ao2_iterator_init(sessions, 0); 04761 while ((session = ao2_iterator_next(&i)) && n_max > 0) { 04762 ao2_lock(session); 04763 if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) { 04764 if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) { 04765 ast_verb(2, "HTTP Manager '%s' timed out from %s\n", 04766 session->username, ast_inet_ntoa(session->sin.sin_addr)); 04767 } 04768 ao2_unlock(session); 04769 session_destroy(session); 04770 n_max--; 04771 } else { 04772 ao2_unlock(session); 04773 unref_mansession(session); 04774 } 04775 } 04776 ao2_iterator_destroy(&i); 04777 }
static void report_auth_success | ( | const struct mansession * | s | ) | [static] |
Definition at line 2088 of file manager.c.
References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_SUCCESSFUL_AUTH, AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION, ast_security_event_successful_auth::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.
Referenced by authenticate().
02089 { 02090 struct sockaddr_in sin_local; 02091 char session_id[32]; 02092 struct ast_security_event_successful_auth successful_auth = { 02093 .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH, 02094 .common.version = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION, 02095 .common.service = "AMI", 02096 .common.account_id = s->session->username, 02097 .common.session_tv = &s->session->sessionstart_tv, 02098 .common.local_addr = { 02099 .sin = mansession_encode_sin_local(s, &sin_local), 02100 .transport = mansession_get_transport(s), 02101 }, 02102 .common.remote_addr = { 02103 .sin = &s->session->sin, 02104 .transport = mansession_get_transport(s), 02105 }, 02106 .common.session_id = session_id, 02107 }; 02108 02109 snprintf(session_id, sizeof(session_id), "%p", s->session); 02110 02111 ast_security_event_report(AST_SEC_EVT(&successful_auth)); 02112 }
static void report_failed_acl | ( | const struct mansession * | s, | |
const char * | username | |||
) | [static] |
Definition at line 2036 of file manager.c.
References AST_SEC_EVT, AST_SECURITY_EVENT_FAILED_ACL, AST_SECURITY_EVENT_FAILED_ACL_VERSION, ast_security_event_report(), ast_security_event_failed_acl::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, and mansession_session::sin.
Referenced by authenticate().
02037 { 02038 struct sockaddr_in sin_local; 02039 char session_id[32]; 02040 struct ast_security_event_failed_acl failed_acl_event = { 02041 .common.event_type = AST_SECURITY_EVENT_FAILED_ACL, 02042 .common.version = AST_SECURITY_EVENT_FAILED_ACL_VERSION, 02043 .common.service = "AMI", 02044 .common.account_id = username, 02045 .common.session_tv = &s->session->sessionstart_tv, 02046 .common.local_addr = { 02047 .sin = mansession_encode_sin_local(s, &sin_local), 02048 .transport = mansession_get_transport(s), 02049 }, 02050 .common.remote_addr = { 02051 .sin = &s->session->sin, 02052 .transport = mansession_get_transport(s), 02053 }, 02054 .common.session_id = session_id, 02055 }; 02056 02057 snprintf(session_id, sizeof(session_id), "%p", s->session); 02058 02059 ast_security_event_report(AST_SEC_EVT(&failed_acl_event)); 02060 }
static void report_failed_challenge_response | ( | const struct mansession * | s, | |
const char * | response, | |||
const char * | expected_response | |||
) | [static] |
Definition at line 2174 of file manager.c.
References AST_SEC_EVT, AST_SECURITY_EVENT_CHAL_RESP_FAILED, AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION, ast_security_event_report(), mansession_session::challenge, ast_security_event_chal_resp_failed::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.
Referenced by authenticate().
02176 { 02177 struct sockaddr_in sin_local; 02178 char session_id[32]; 02179 struct ast_security_event_chal_resp_failed chal_resp_failed = { 02180 .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED, 02181 .common.version = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION, 02182 .common.service = "AMI", 02183 .common.account_id = s->session->username, 02184 .common.session_tv = &s->session->sessionstart_tv, 02185 .common.local_addr = { 02186 .sin = mansession_encode_sin_local(s, &sin_local), 02187 .transport = mansession_get_transport(s), 02188 }, 02189 .common.remote_addr = { 02190 .sin = &s->session->sin, 02191 .transport = mansession_get_transport(s), 02192 }, 02193 .common.session_id = session_id, 02194 02195 .challenge = s->session->challenge, 02196 .response = response, 02197 .expected_response = expected_response, 02198 }; 02199 02200 snprintf(session_id, sizeof(session_id), "%p", s->session); 02201 02202 ast_security_event_report(AST_SEC_EVT(&chal_resp_failed)); 02203 }
static void report_inval_password | ( | const struct mansession * | s, | |
const char * | username | |||
) | [static] |
Definition at line 2062 of file manager.c.
References AST_SEC_EVT, AST_SECURITY_EVENT_INVAL_PASSWORD, AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION, ast_security_event_report(), ast_security_event_inval_password::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, and mansession_session::sin.
Referenced by authenticate().
02063 { 02064 struct sockaddr_in sin_local; 02065 char session_id[32]; 02066 struct ast_security_event_inval_password inval_password = { 02067 .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD, 02068 .common.version = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION, 02069 .common.service = "AMI", 02070 .common.account_id = username, 02071 .common.session_tv = &s->session->sessionstart_tv, 02072 .common.local_addr = { 02073 .sin = mansession_encode_sin_local(s, &sin_local), 02074 .transport = mansession_get_transport(s), 02075 }, 02076 .common.remote_addr = { 02077 .sin = &s->session->sin, 02078 .transport = mansession_get_transport(s), 02079 }, 02080 .common.session_id = session_id, 02081 }; 02082 02083 snprintf(session_id, sizeof(session_id), "%p", s->session); 02084 02085 ast_security_event_report(AST_SEC_EVT(&inval_password)); 02086 }
static void report_invalid_user | ( | const struct mansession * | s, | |
const char * | username | |||
) | [static] |
Definition at line 2010 of file manager.c.
References AST_SEC_EVT, AST_SECURITY_EVENT_INVAL_ACCT_ID, AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION, ast_security_event_report(), ast_security_event_inval_acct_id::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, and mansession_session::sin.
Referenced by authenticate().
02011 { 02012 struct sockaddr_in sin_local; 02013 char session_id[32]; 02014 struct ast_security_event_inval_acct_id inval_acct_id = { 02015 .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID, 02016 .common.version = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION, 02017 .common.service = "AMI", 02018 .common.account_id = username, 02019 .common.session_tv = &s->session->sessionstart_tv, 02020 .common.local_addr = { 02021 .sin = mansession_encode_sin_local(s, &sin_local), 02022 .transport = mansession_get_transport(s), 02023 }, 02024 .common.remote_addr = { 02025 .sin = &s->session->sin, 02026 .transport = mansession_get_transport(s), 02027 }, 02028 .common.session_id = session_id, 02029 }; 02030 02031 snprintf(session_id, sizeof(session_id), "%p", s); 02032 02033 ast_security_event_report(AST_SEC_EVT(&inval_acct_id)); 02034 }
static void report_req_bad_format | ( | const struct mansession * | s, | |
const char * | action | |||
) | [static] |
Definition at line 2144 of file manager.c.
References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_REQ_BAD_FORMAT, AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION, ast_security_event_req_bad_format::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.
Referenced by process_message().
02145 { 02146 struct sockaddr_in sin_local; 02147 char session_id[32]; 02148 char request_type[64]; 02149 struct ast_security_event_req_bad_format req_bad_format = { 02150 .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT, 02151 .common.version = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION, 02152 .common.service = "AMI", 02153 .common.account_id = s->session->username, 02154 .common.session_tv = &s->session->sessionstart_tv, 02155 .common.local_addr = { 02156 .sin = mansession_encode_sin_local(s, &sin_local), 02157 .transport = mansession_get_transport(s), 02158 }, 02159 .common.remote_addr = { 02160 .sin = &s->session->sin, 02161 .transport = mansession_get_transport(s), 02162 }, 02163 .common.session_id = session_id, 02164 02165 .request_type = request_type, 02166 }; 02167 02168 snprintf(session_id, sizeof(session_id), "%p", s->session); 02169 snprintf(request_type, sizeof(request_type), "Action: %s", action); 02170 02171 ast_security_event_report(AST_SEC_EVT(&req_bad_format)); 02172 }
static void report_req_not_allowed | ( | const struct mansession * | s, | |
const char * | action | |||
) | [static] |
Definition at line 2114 of file manager.c.
References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_REQ_NOT_ALLOWED, AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION, ast_security_event_req_not_allowed::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.
Referenced by process_message().
02115 { 02116 struct sockaddr_in sin_local; 02117 char session_id[32]; 02118 char request_type[64]; 02119 struct ast_security_event_req_not_allowed req_not_allowed = { 02120 .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED, 02121 .common.version = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION, 02122 .common.service = "AMI", 02123 .common.account_id = s->session->username, 02124 .common.session_tv = &s->session->sessionstart_tv, 02125 .common.local_addr = { 02126 .sin = mansession_encode_sin_local(s, &sin_local), 02127 .transport = mansession_get_transport(s), 02128 }, 02129 .common.remote_addr = { 02130 .sin = &s->session->sin, 02131 .transport = mansession_get_transport(s), 02132 }, 02133 .common.session_id = session_id, 02134 02135 .request_type = request_type, 02136 }; 02137 02138 snprintf(session_id, sizeof(session_id), "%p", s->session); 02139 snprintf(request_type, sizeof(request_type), "Action: %s", action); 02140 02141 ast_security_event_report(AST_SEC_EVT(&req_not_allowed)); 02142 }
static void report_session_limit | ( | const struct mansession * | s | ) | [static] |
Definition at line 2205 of file manager.c.
References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_SESSION_LIMIT, AST_SECURITY_EVENT_SESSION_LIMIT_VERSION, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, session_limit, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.
Referenced by process_message().
02206 { 02207 struct sockaddr_in sin_local; 02208 char session_id[32]; 02209 struct ast_security_event_session_limit session_limit = { 02210 .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT, 02211 .common.version = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION, 02212 .common.service = "AMI", 02213 .common.account_id = s->session->username, 02214 .common.session_tv = &s->session->sessionstart_tv, 02215 .common.local_addr = { 02216 .sin = mansession_encode_sin_local(s, &sin_local), 02217 .transport = mansession_get_transport(s), 02218 }, 02219 .common.remote_addr = { 02220 .sin = &s->session->sin, 02221 .transport = mansession_get_transport(s), 02222 }, 02223 .common.session_id = session_id, 02224 }; 02225 02226 snprintf(session_id, sizeof(session_id), "%p", s->session); 02227 02228 ast_security_event_report(AST_SEC_EVT(&session_limit)); 02229 }
static int send_string | ( | struct mansession * | s, | |
char * | string | |||
) | [static] |
helper function to send a string to the socket. Return -1 on error (e.g. buffer full).
Definition at line 1851 of file manager.c.
References ast_careful_fwrite(), EVENT_FLAG_HOOKRESPONSE, mansession_session::f, mansession::f, mansession_session::fd, mansession::fd, manager_custom_hook::helper, mansession::hook, mansession::session, and mansession_session::writetimeout.
Referenced by astman_append(), and process_events().
01852 { 01853 /* It's a result from one of the hook's action invocation */ 01854 if (s->hook) { 01855 /* 01856 * to send responses, we're using the same function 01857 * as for receiving events. We call the event "HookResponse" 01858 */ 01859 s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string); 01860 return 0; 01861 } else if (s->f) { 01862 return ast_careful_fwrite(s->f, s->fd, string, strlen(string), s->session->writetimeout); 01863 } else { 01864 return ast_careful_fwrite(s->session->f, s->session->fd, string, strlen(string), s->session->writetimeout); 01865 } 01866 }
static void session_destroy | ( | struct mansession_session * | s | ) | [static] |
Definition at line 1310 of file manager.c.
References ao2_unlink, and unref_mansession().
Referenced by purge_sessions(), session_do(), and spandsp_fax_destroy().
01311 { 01312 unref_mansession(s); 01313 ao2_unlink(sessions, s); 01314 }
static void session_destructor | ( | void * | obj | ) | [static] |
Definition at line 1243 of file manager.c.
References ao2_t_callback, ao2_t_ref, ast_atomic_fetchadd_int(), ast_datastore_free(), AST_LIST_REMOVE_HEAD, mansession_session::blackfilters, mansession_session::datastores, ast_datastore::entry, mansession_session::f, mansession_session::last_ev, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, eventqent::usecount, and mansession_session::whitefilters.
Referenced by build_mansession().
01244 { 01245 struct mansession_session *session = obj; 01246 struct eventqent *eqe = session->last_ev; 01247 struct ast_datastore *datastore; 01248 01249 /* Get rid of each of the data stores on the session */ 01250 while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) { 01251 /* Free the data store */ 01252 ast_datastore_free(datastore); 01253 } 01254 01255 if (session->f != NULL) { 01256 fclose(session->f); 01257 } 01258 if (eqe) { 01259 ast_atomic_fetchadd_int(&eqe->usecount, -1); 01260 } 01261 01262 if (session->whitefilters) { 01263 ao2_t_callback(session->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters"); 01264 ao2_t_ref(session->whitefilters, -1 , "decrement ref for white container, should be last one"); 01265 } 01266 01267 if (session->blackfilters) { 01268 ao2_t_callback(session->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters"); 01269 ao2_t_ref(session->blackfilters, -1 , "decrement ref for black container, should be last one"); 01270 } 01271 }
static void* session_do | ( | void * | data | ) | [static] |
The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ).
Definition at line 4655 of file manager.c.
References AMI_VERSION, ao2_lock, ao2_unlock, ast_atomic_fetchadd_int(), ast_inet_ntoa(), AST_LIST_HEAD_INIT_NOLOCK, ast_log(), ast_mutex_init, ast_sockaddr_to_sin, ast_verb, astman_append(), mansession_session::authenticated, authlimit, mansession_session::authstart, block_sockets, build_mansession(), mansession_session::datastores, do_message(), errno, mansession::f, mansession_session::f, ast_tcptls_session_instance::f, mansession::fd, mansession_session::fd, ast_tcptls_session_instance::fd, ast_frame::flags, grab_last(), mansession_session::last_ev, mansession::lock, LOG_ERROR, LOG_WARNING, manager_displayconnects(), ast_tcptls_session_instance::remote_address, mansession::session, session_destroy(), mansession_session::sin, mansession::tcptls_session, and unauth_sessions.
04656 { 04657 struct ast_tcptls_session_instance *ser = data; 04658 struct mansession_session *session; 04659 struct mansession s = { 04660 .tcptls_session = data, 04661 }; 04662 int flags; 04663 int res; 04664 struct sockaddr_in ser_remote_address_tmp; 04665 struct protoent *p; 04666 04667 if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) { 04668 fclose(ser->f); 04669 ast_atomic_fetchadd_int(&unauth_sessions, -1); 04670 goto done; 04671 } 04672 04673 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 04674 session = build_mansession(ser_remote_address_tmp); 04675 04676 if (session == NULL) { 04677 fclose(ser->f); 04678 ast_atomic_fetchadd_int(&unauth_sessions, -1); 04679 goto done; 04680 } 04681 04682 /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm. 04683 * This is necessary to prevent delays (caused by buffering) as we 04684 * write to the socket in bits and peices. */ 04685 p = getprotobyname("tcp"); 04686 if (p) { 04687 int arg = 1; 04688 if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) { 04689 ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY mode: %s\nSome manager actions may be slow to respond.\n", strerror(errno)); 04690 } 04691 } else { 04692 ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY, getprotobyname(\"tcp\") failed\nSome manager actions may be slow to respond.\n"); 04693 } 04694 04695 flags = fcntl(ser->fd, F_GETFL); 04696 if (!block_sockets) { /* make sure socket is non-blocking */ 04697 flags |= O_NONBLOCK; 04698 } else { 04699 flags &= ~O_NONBLOCK; 04700 } 04701 fcntl(ser->fd, F_SETFL, flags); 04702 04703 ao2_lock(session); 04704 /* Hook to the tail of the event queue */ 04705 session->last_ev = grab_last(); 04706 04707 ast_mutex_init(&s.lock); 04708 04709 /* these fields duplicate those in the 'ser' structure */ 04710 session->fd = s.fd = ser->fd; 04711 session->f = s.f = ser->f; 04712 session->sin = ser_remote_address_tmp; 04713 s.session = session; 04714 04715 AST_LIST_HEAD_INIT_NOLOCK(&session->datastores); 04716 04717 if(time(&session->authstart) == -1) { 04718 ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno)); 04719 ast_atomic_fetchadd_int(&unauth_sessions, -1); 04720 ao2_unlock(session); 04721 session_destroy(session); 04722 goto done; 04723 } 04724 ao2_unlock(session); 04725 04726 astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */ 04727 for (;;) { 04728 if ((res = do_message(&s)) < 0) { 04729 break; 04730 } 04731 } 04732 /* session is over, explain why and terminate */ 04733 if (session->authenticated) { 04734 if (manager_displayconnects(session)) { 04735 ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 04736 } 04737 } else { 04738 ast_atomic_fetchadd_int(&unauth_sessions, -1); 04739 if (displayconnects) { 04740 ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr)); 04741 } 04742 } 04743 04744 session_destroy(session); 04745 04746 ast_mutex_destroy(&s.lock); 04747 done: 04748 ao2_ref(ser, -1); 04749 ser = NULL; 04750 return NULL; 04751 }
static int set_eventmask | ( | struct mansession * | s, | |
const char * | eventmask | |||
) | [static] |
Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm.
Definition at line 1982 of file manager.c.
References ao2_lock, ao2_unlock, mansession_session::send_events, mansession::session, and strings_to_mask().
Referenced by action_events(), and authenticate().
01983 { 01984 int maskint = strings_to_mask(eventmask); 01985 01986 ao2_lock(s->session); 01987 if (maskint >= 0) { 01988 s->session->send_events = maskint; 01989 } 01990 ao2_unlock(s->session); 01991 01992 return maskint; 01993 }
static int strings_to_mask | ( | const char * | string | ) | [static] |
A number returns itself, false returns 0, true returns all flags, other strings return the flags that are set.
Definition at line 1197 of file manager.c.
References ARRAY_LEN, ast_false(), ast_strlen_zero(), ast_true(), get_perm(), and perms.
Referenced by set_eventmask().
01198 { 01199 const char *p; 01200 01201 if (ast_strlen_zero(string)) { 01202 return -1; 01203 } 01204 01205 for (p = string; *p; p++) { 01206 if (*p < '0' || *p > '9') { 01207 break; 01208 } 01209 } 01210 if (!*p) { /* all digits */ 01211 return atoi(string); 01212 } 01213 if (ast_false(string)) { 01214 return 0; 01215 } 01216 if (ast_true(string)) { /* all permissions */ 01217 int x, ret = 0; 01218 for (x = 0; x < ARRAY_LEN(perms); x++) { 01219 ret |= perms[x].num; 01220 } 01221 return ret; 01222 } 01223 return get_perm(string); 01224 }
static struct mansession_session* unref_mansession | ( | struct mansession_session * | s | ) | [static] |
Unreference manager session object. If no more references, then go ahead and delete it.
Definition at line 1228 of file manager.c.
References ao2_ref, ast_log(), LOG_DEBUG, and manager_debug.
Referenced by __ast_manager_event_multichan(), astman_is_authed(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), check_manager_session_inuse(), find_session(), find_session_by_nonce(), handle_showmanconn(), purge_sessions(), and session_destroy().
01229 { 01230 int refcount = ao2_ref(s, -1); 01231 if (manager_debug) { 01232 ast_log(LOG_DEBUG, "Mansession: %p refcount now %d\n", s, refcount - 1); 01233 } 01234 return s; 01235 }
static int whitefilter_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 4050 of file manager.c.
References CMP_MATCH, and CMP_STOP.
Referenced by match_filter().
04051 { 04052 regex_t *regex_filter = obj; 04053 const char *eventdata = arg; 04054 int *result = data; 04055 04056 if (!regexec(regex_filter, eventdata, 0, NULL, 0)) { 04057 *result = 1; 04058 return (CMP_MATCH | CMP_STOP); 04059 } 04060 04061 return 0; 04062 }
int allowmultiplelogin = 1 [static] |
Definition at line 867 of file manager.c.
Referenced by handle_manager_show_settings(), and process_message().
struct ast_threadstorage astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , } [static] |
int authtimeout [static] |
int block_sockets [static] |
Definition at line 880 of file manager.c.
Referenced by __init_manager(), handle_manager_show_settings(), and session_do().
int broken_events_action [static] |
struct { ... } command_blacklist[] [static] |
Referenced by check_blacklist().
const int DEFAULT_AUTHLIMIT = 50 [static] |
Default setting for authlimit
Definition at line 864 of file manager.c.
Referenced by __init_manager().
const int DEFAULT_AUTHTIMEOUT = 30 [static] |
Default setting for authtimeout
Definition at line 863 of file manager.c.
Referenced by __init_manager().
const int DEFAULT_BLOCKSOCKETS = 0 [static] |
Default setting for block-sockets
Definition at line 858 of file manager.c.
Referenced by __init_manager().
const int DEFAULT_BROKENEVENTSACTION = 0 [static] |
Default setting for brokeneventsaction
Definition at line 862 of file manager.c.
Referenced by __init_manager().
const int DEFAULT_DISPLAYCONNECTS = 1 [static] |
Default setting for displaying manager connections
Definition at line 859 of file manager.c.
Referenced by __init_manager().
const int DEFAULT_ENABLED = 0 [static] |
Default setting for manager to be enabled
Definition at line 856 of file manager.c.
Referenced by __init_manager().
const int DEFAULT_HTTPTIMEOUT = 60 [static] |
Default manager http timeout
Definition at line 861 of file manager.c.
Referenced by __init_manager().
const int DEFAULT_TIMESTAMPEVENTS = 0 [static] |
Default setting for timestampevents
Definition at line 860 of file manager.c.
Referenced by __init_manager().
const int DEFAULT_WEBENABLED = 0 [static] |
Default setting for the web interface to be enabled
Definition at line 857 of file manager.c.
Referenced by __init_manager().
int displayconnects [static] |
Definition at line 866 of file manager.c.
Referenced by __init_manager(), do_message(), and handle_manager_show_settings().
char global_realm[MAXHOSTNAMELEN] [static] |
int httptimeout [static] |
Definition at line 869 of file manager.c.
Referenced by __init_manager(), and handle_manager_show_settings().
char* manager_channelvars [static] |
int manager_debug [static] |
enable some debugging code in the manager
Definition at line 883 of file manager.c.
Referenced by __ast_manager_event_multichan(), handle_manager_show_settings(), handle_mandebug(), and unref_mansession().
int manager_enabled = 0 [static] |
Definition at line 871 of file manager.c.
Referenced by __init_manager(), and handle_manager_show_settings().
struct ast_threadstorage manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , } [static] |
struct ast_threadstorage manager_event_funcbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_funcbuf , .custom_init = NULL , } [static] |
helper functions to convert back and forth between string and numeric representation of set of flags
Referenced by action_events(), authority_to_str(), get_perm(), and strings_to_mask().
struct ao2_container* sessions = NULL [static] |
int timestampevents [static] |
Definition at line 868 of file manager.c.
Referenced by __ast_manager_event_multichan(), __init_manager(), and handle_manager_show_settings().
int unauth_sessions = 0 [static] |
struct ast_threadstorage userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , } [static] |
int webmanager_enabled = 0 [static] |
Definition at line 872 of file manager.c.
Referenced by __init_manager(), and handle_manager_show_settings().