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 | block_sockets |
static int | broken_events_action |
struct { | |
const char * words [AST_MAX_CMD_LEN] | |
} | command_blacklist [] |
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 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 1880 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 1703 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 890 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 1921 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 4785 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().
04787 { 04788 struct mansession_session *session; 04789 struct manager_custom_hook *hook; 04790 struct ast_str *auth = ast_str_alloca(80); 04791 const char *cat_str; 04792 va_list ap; 04793 struct timeval now; 04794 struct ast_str *buf; 04795 int i; 04796 04797 if (!(sessions && ao2_container_count(sessions)) && AST_RWLIST_EMPTY(&manager_hooks)) { 04798 return 0; 04799 } 04800 04801 if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) { 04802 return -1; 04803 } 04804 04805 cat_str = authority_to_str(category, &auth); 04806 ast_str_set(&buf, 0, 04807 "Event: %s\r\nPrivilege: %s\r\n", 04808 event, cat_str); 04809 04810 if (timestampevents) { 04811 now = ast_tvnow(); 04812 ast_str_append(&buf, 0, 04813 "Timestamp: %ld.%06lu\r\n", 04814 (long)now.tv_sec, (unsigned long) now.tv_usec); 04815 } 04816 if (manager_debug) { 04817 static int seq; 04818 ast_str_append(&buf, 0, 04819 "SequenceNumber: %d\r\n", 04820 ast_atomic_fetchadd_int(&seq, 1)); 04821 ast_str_append(&buf, 0, 04822 "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func); 04823 } 04824 04825 va_start(ap, fmt); 04826 ast_str_append_va(&buf, 0, fmt, ap); 04827 va_end(ap); 04828 for (i = 0; i < chancount; i++) { 04829 append_channel_vars(&buf, chans[i]); 04830 } 04831 04832 ast_str_append(&buf, 0, "\r\n"); 04833 04834 append_event(ast_str_buffer(buf), category); 04835 04836 /* Wake up any sleeping sessions */ 04837 if (sessions) { 04838 struct ao2_iterator i; 04839 i = ao2_iterator_init(sessions, 0); 04840 while ((session = ao2_iterator_next(&i))) { 04841 ao2_lock(session); 04842 if (session->waiting_thread != AST_PTHREADT_NULL) { 04843 pthread_kill(session->waiting_thread, SIGURG); 04844 } else { 04845 /* We have an event to process, but the mansession is 04846 * not waiting for it. We still need to indicate that there 04847 * is an event waiting so that get_input processes the pending 04848 * event instead of polling. 04849 */ 04850 session->pending_event = 1; 04851 } 04852 ao2_unlock(session); 04853 unref_mansession(session); 04854 } 04855 ao2_iterator_destroy(&i); 04856 } 04857 04858 if (!AST_RWLIST_EMPTY(&manager_hooks)) { 04859 AST_RWLIST_RDLOCK(&manager_hooks); 04860 AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) { 04861 hook->helper(category, event, ast_str_buffer(buf)); 04862 } 04863 AST_RWLIST_UNLOCK(&manager_hooks); 04864 } 04865 04866 return 0; 04867 }
static const char* __astman_get_header | ( | const struct message * | m, | |
char * | var, | |||
int | mode | |||
) | [static] |
Definition at line 1704 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().
01705 { 01706 int x, l = strlen(var); 01707 const char *result = ""; 01708 01709 for (x = 0; x < m->hdrcount; x++) { 01710 const char *h = m->headers[x]; 01711 if (!strncasecmp(var, h, l) && h[l] == ':') { 01712 const char *value = h + l + 1; 01713 value = ast_skip_blanks(value); /* ignore leading spaces in the value */ 01714 /* found a potential candidate */ 01715 if (mode & GET_HEADER_SKIP_EMPTY && ast_strlen_zero(value)) 01716 continue; /* not interesting */ 01717 if (mode & GET_HEADER_LAST_MATCH) 01718 result = value; /* record the last match so far */ 01719 else 01720 return value; 01721 } 01722 } 01723 01724 return ""; 01725 }
static void __init_astman_append_buf | ( | void | ) | [static] |
thread local buffer for astman_append
Definition at line 1876 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 3612 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().
03613 { 03614 const char *channel = astman_get_header(m, "Channel"); 03615 const char *pchannel = astman_get_header(m, "ChannelPrefix"); 03616 const char *msgtype = astman_get_header(m, "MsgType"); 03617 const char *chargetype = astman_get_header(m, "ChargeType"); 03618 const char *currencyname = astman_get_header(m, "CurrencyName"); 03619 const char *currencyamount = astman_get_header(m, "CurrencyAmount"); 03620 const char *mult = astman_get_header(m, "CurrencyMultiplier"); 03621 const char *totaltype = astman_get_header(m, "TotalType"); 03622 const char *aocbillingid = astman_get_header(m, "AOCBillingId"); 03623 const char *association_id= astman_get_header(m, "ChargingAssociationId"); 03624 const char *association_num = astman_get_header(m, "ChargingAssociationNumber"); 03625 const char *association_plan = astman_get_header(m, "ChargingAssociationPlan"); 03626 03627 enum ast_aoc_type _msgtype; 03628 enum ast_aoc_charge_type _chargetype; 03629 enum ast_aoc_currency_multiplier _mult = AST_AOC_MULT_ONE; 03630 enum ast_aoc_total_type _totaltype = AST_AOC_TOTAL; 03631 enum ast_aoc_billing_id _billingid = AST_AOC_BILLING_NA; 03632 unsigned int _currencyamount = 0; 03633 int _association_id = 0; 03634 unsigned int _association_plan = 0; 03635 struct ast_channel *chan = NULL; 03636 03637 struct ast_aoc_decoded *decoded = NULL; 03638 struct ast_aoc_encoded *encoded = NULL; 03639 size_t encoded_size = 0; 03640 03641 if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) { 03642 astman_send_error(s, m, "Channel and PartialChannel are not specified. Specify at least one of these."); 03643 goto aocmessage_cleanup; 03644 } 03645 03646 if (!(chan = ast_channel_get_by_name(channel)) && !ast_strlen_zero(pchannel)) { 03647 chan = ast_channel_get_by_name_prefix(pchannel, strlen(pchannel)); 03648 } 03649 03650 if (!chan) { 03651 astman_send_error(s, m, "No such channel"); 03652 goto aocmessage_cleanup; 03653 } 03654 03655 if (ast_strlen_zero(msgtype) || (strcasecmp(msgtype, "d") && strcasecmp(msgtype, "e"))) { 03656 astman_send_error(s, m, "Invalid MsgType"); 03657 goto aocmessage_cleanup; 03658 } 03659 03660 if (ast_strlen_zero(chargetype)) { 03661 astman_send_error(s, m, "ChargeType not specified"); 03662 goto aocmessage_cleanup; 03663 } 03664 03665 _msgtype = strcasecmp(msgtype, "d") ? AST_AOC_E : AST_AOC_D; 03666 03667 if (!strcasecmp(chargetype, "NA")) { 03668 _chargetype = AST_AOC_CHARGE_NA; 03669 } else if (!strcasecmp(chargetype, "Free")) { 03670 _chargetype = AST_AOC_CHARGE_FREE; 03671 } else if (!strcasecmp(chargetype, "Currency")) { 03672 _chargetype = AST_AOC_CHARGE_CURRENCY; 03673 } else if (!strcasecmp(chargetype, "Unit")) { 03674 _chargetype = AST_AOC_CHARGE_UNIT; 03675 } else { 03676 astman_send_error(s, m, "Invalid ChargeType"); 03677 goto aocmessage_cleanup; 03678 } 03679 03680 if (_chargetype == AST_AOC_CHARGE_CURRENCY) { 03681 03682 if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u", &_currencyamount) != 1)) { 03683 astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency"); 03684 goto aocmessage_cleanup; 03685 } 03686 03687 if (ast_strlen_zero(mult)) { 03688 astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency."); 03689 goto aocmessage_cleanup; 03690 } else if (!strcasecmp(mult, "onethousandth")) { 03691 _mult = AST_AOC_MULT_ONETHOUSANDTH; 03692 } else if (!strcasecmp(mult, "onehundredth")) { 03693 _mult = AST_AOC_MULT_ONEHUNDREDTH; 03694 } else if (!strcasecmp(mult, "onetenth")) { 03695 _mult = AST_AOC_MULT_ONETENTH; 03696 } else if (!strcasecmp(mult, "one")) { 03697 _mult = AST_AOC_MULT_ONE; 03698 } else if (!strcasecmp(mult, "ten")) { 03699 _mult = AST_AOC_MULT_TEN; 03700 } else if (!strcasecmp(mult, "hundred")) { 03701 _mult = AST_AOC_MULT_HUNDRED; 03702 } else if (!strcasecmp(mult, "thousand")) { 03703 _mult = AST_AOC_MULT_THOUSAND; 03704 } else { 03705 astman_send_error(s, m, "Invalid ChargeMultiplier"); 03706 goto aocmessage_cleanup; 03707 } 03708 } 03709 03710 /* create decoded object and start setting values */ 03711 if (!(decoded = ast_aoc_create(_msgtype, _chargetype, 0))) { 03712 astman_send_error(s, m, "Message Creation Failed"); 03713 goto aocmessage_cleanup; 03714 } 03715 03716 if (_msgtype == AST_AOC_D) { 03717 if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype, "subtotal")) { 03718 _totaltype = AST_AOC_SUBTOTAL; 03719 } 03720 03721 if (ast_strlen_zero(aocbillingid)) { 03722 /* ignore this is optional */ 03723 } else if (!strcasecmp(aocbillingid, "Normal")) { 03724 _billingid = AST_AOC_BILLING_NORMAL; 03725 } else if (!strcasecmp(aocbillingid, "ReverseCharge")) { 03726 _billingid = AST_AOC_BILLING_REVERSE_CHARGE; 03727 } else if (!strcasecmp(aocbillingid, "CreditCard")) { 03728 _billingid = AST_AOC_BILLING_CREDIT_CARD; 03729 } else { 03730 astman_send_error(s, m, "Invalid AOC-D AOCBillingId"); 03731 goto aocmessage_cleanup; 03732 } 03733 } else { 03734 if (ast_strlen_zero(aocbillingid)) { 03735 /* ignore this is optional */ 03736 } else if (!strcasecmp(aocbillingid, "Normal")) { 03737 _billingid = AST_AOC_BILLING_NORMAL; 03738 } else if (!strcasecmp(aocbillingid, "ReverseCharge")) { 03739 _billingid = AST_AOC_BILLING_REVERSE_CHARGE; 03740 } else if (!strcasecmp(aocbillingid, "CreditCard")) { 03741 _billingid = AST_AOC_BILLING_CREDIT_CARD; 03742 } else if (!strcasecmp(aocbillingid, "CallFwdUnconditional")) { 03743 _billingid = AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL; 03744 } else if (!strcasecmp(aocbillingid, "CallFwdBusy")) { 03745 _billingid = AST_AOC_BILLING_CALL_FWD_BUSY; 03746 } else if (!strcasecmp(aocbillingid, "CallFwdNoReply")) { 03747 _billingid = AST_AOC_BILLING_CALL_FWD_NO_REPLY; 03748 } else if (!strcasecmp(aocbillingid, "CallDeflection")) { 03749 _billingid = AST_AOC_BILLING_CALL_DEFLECTION; 03750 } else if (!strcasecmp(aocbillingid, "CallTransfer")) { 03751 _billingid = AST_AOC_BILLING_CALL_TRANSFER; 03752 } else { 03753 astman_send_error(s, m, "Invalid AOC-E AOCBillingId"); 03754 goto aocmessage_cleanup; 03755 } 03756 03757 if (!ast_strlen_zero(association_id) && (sscanf(association_id, "%30d", &_association_id) != 1)) { 03758 astman_send_error(s, m, "Invalid ChargingAssociationId"); 03759 goto aocmessage_cleanup; 03760 } 03761 if (!ast_strlen_zero(association_plan) && (sscanf(association_plan, "%30u", &_association_plan) != 1)) { 03762 astman_send_error(s, m, "Invalid ChargingAssociationPlan"); 03763 goto aocmessage_cleanup; 03764 } 03765 03766 if (_association_id) { 03767 ast_aoc_set_association_id(decoded, _association_id); 03768 } else if (!ast_strlen_zero(association_num)) { 03769 ast_aoc_set_association_number(decoded, association_num, _association_plan); 03770 } 03771 } 03772 03773 if (_chargetype == AST_AOC_CHARGE_CURRENCY) { 03774 ast_aoc_set_currency_info(decoded, _currencyamount, _mult, ast_strlen_zero(currencyname) ? NULL : currencyname); 03775 } else if (_chargetype == AST_AOC_CHARGE_UNIT) { 03776 struct ast_aoc_unit_entry entry; 03777 int i; 03778 03779 /* multiple unit entries are possible, lets get them all */ 03780 for (i = 0; i < 32; i++) { 03781 if (aocmessage_get_unit_entry(m, &entry, i)) { 03782 break; /* that's the end then */ 03783 } 03784 03785 ast_aoc_add_unit_entry(decoded, entry.valid_amount, entry.amount, entry.valid_type, entry.type); 03786 } 03787 03788 /* at least one unit entry is required */ 03789 if (!i) { 03790 astman_send_error(s, m, "Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit"); 03791 goto aocmessage_cleanup; 03792 } 03793 03794 } 03795 03796 ast_aoc_set_billing_id(decoded, _billingid); 03797 ast_aoc_set_total_type(decoded, _totaltype); 03798 03799 03800 if ((encoded = ast_aoc_encode(decoded, &encoded_size, NULL)) && !ast_indicate_data(chan, AST_CONTROL_AOC, encoded, encoded_size)) { 03801 astman_send_ack(s, m, "AOC Message successfully queued on channel"); 03802 } else { 03803 astman_send_error(s, m, "Error encoding AOC message, could not queue onto channel"); 03804 } 03805 03806 aocmessage_cleanup: 03807 03808 ast_aoc_destroy_decoded(decoded); 03809 ast_aoc_destroy_encoded(encoded); 03810 03811 if (chan) { 03812 chan = ast_channel_unref(chan); 03813 } 03814 return 0; 03815 }
static int action_atxfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3379 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().
03380 { 03381 const char *name = astman_get_header(m, "Channel"); 03382 const char *exten = astman_get_header(m, "Exten"); 03383 const char *context = astman_get_header(m, "Context"); 03384 struct ast_channel *chan = NULL; 03385 struct ast_call_feature *atxfer_feature = NULL; 03386 char *feature_code = NULL; 03387 03388 if (ast_strlen_zero(name)) { 03389 astman_send_error(s, m, "No channel specified"); 03390 return 0; 03391 } 03392 if (ast_strlen_zero(exten)) { 03393 astman_send_error(s, m, "No extension specified"); 03394 return 0; 03395 } 03396 03397 if (!(atxfer_feature = ast_find_call_feature("atxfer"))) { 03398 astman_send_error(s, m, "No attended transfer feature found"); 03399 return 0; 03400 } 03401 03402 if (!(chan = ast_channel_get_by_name(name))) { 03403 astman_send_error(s, m, "Channel specified does not exist"); 03404 return 0; 03405 } 03406 03407 if (!ast_strlen_zero(context)) { 03408 pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context); 03409 } 03410 03411 for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) { 03412 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code }; 03413 ast_queue_frame(chan, &f); 03414 } 03415 03416 for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) { 03417 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code }; 03418 ast_queue_frame(chan, &f); 03419 } 03420 03421 chan = ast_channel_unref(chan); 03422 03423 astman_send_ack(s, m, "Atxfer successfully queued"); 03424 03425 return 0; 03426 }
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 3464 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().
03465 { 03466 const char *cmd = astman_get_header(m, "Command"); 03467 const char *id = astman_get_header(m, "ActionID"); 03468 char *buf, *final_buf; 03469 char template[] = "/tmp/ast-ami-XXXXXX"; /* template for temporary file */ 03470 int fd; 03471 off_t l; 03472 03473 if (ast_strlen_zero(cmd)) { 03474 astman_send_error(s, m, "No command provided"); 03475 return 0; 03476 } 03477 03478 if (check_blacklist(cmd)) { 03479 astman_send_error(s, m, "Command blacklisted"); 03480 return 0; 03481 } 03482 03483 fd = mkstemp(template); 03484 03485 astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n"); 03486 if (!ast_strlen_zero(id)) { 03487 astman_append(s, "ActionID: %s\r\n", id); 03488 } 03489 /* FIXME: Wedge a ActionID response in here, waiting for later changes */ 03490 ast_cli_command(fd, cmd); /* XXX need to change this to use a FILE * */ 03491 l = lseek(fd, 0, SEEK_END); /* how many chars available */ 03492 03493 /* This has a potential to overflow the stack. Hence, use the heap. */ 03494 buf = ast_calloc(1, l + 1); 03495 final_buf = ast_calloc(1, l + 1); 03496 if (buf) { 03497 lseek(fd, 0, SEEK_SET); 03498 if (read(fd, buf, l) < 0) { 03499 ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); 03500 } 03501 buf[l] = '\0'; 03502 if (final_buf) { 03503 term_strip(final_buf, buf, l); 03504 final_buf[l] = '\0'; 03505 } 03506 astman_append(s, "%s", S_OR(final_buf, buf)); 03507 ast_free(buf); 03508 } 03509 close(fd); 03510 unlink(template); 03511 astman_append(s, "--END COMMAND--\r\n\r\n"); 03512 if (final_buf) { 03513 ast_free(final_buf); 03514 } 03515 return 0; 03516 }
static int action_coresettings | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Show PBX core settings information.
Definition at line 4151 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().
04152 { 04153 const char *actionid = astman_get_header(m, "ActionID"); 04154 char idText[150]; 04155 04156 if (!ast_strlen_zero(actionid)) { 04157 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04158 } else { 04159 idText[0] = '\0'; 04160 } 04161 04162 astman_append(s, "Response: Success\r\n" 04163 "%s" 04164 "AMIversion: %s\r\n" 04165 "AsteriskVersion: %s\r\n" 04166 "SystemName: %s\r\n" 04167 "CoreMaxCalls: %d\r\n" 04168 "CoreMaxLoadAvg: %f\r\n" 04169 "CoreRunUser: %s\r\n" 04170 "CoreRunGroup: %s\r\n" 04171 "CoreMaxFilehandles: %d\r\n" 04172 "CoreRealTimeEnabled: %s\r\n" 04173 "CoreCDRenabled: %s\r\n" 04174 "CoreHTTPenabled: %s\r\n" 04175 "\r\n", 04176 idText, 04177 AMI_VERSION, 04178 ast_get_version(), 04179 ast_config_AST_SYSTEM_NAME, 04180 option_maxcalls, 04181 option_maxload, 04182 ast_config_AST_RUN_USER, 04183 ast_config_AST_RUN_GROUP, 04184 option_maxfiles, 04185 AST_CLI_YESNO(ast_realtime_enabled()), 04186 AST_CLI_YESNO(check_cdr_enabled()), 04187 AST_CLI_YESNO(check_webmanager_enabled()) 04188 ); 04189 return 0; 04190 }
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 4248 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().
04249 { 04250 const char *actionid = astman_get_header(m, "ActionID"); 04251 char idText[256]; 04252 struct ast_channel *c = NULL; 04253 int numchans = 0; 04254 int duration, durh, durm, durs; 04255 struct ast_channel_iterator *iter; 04256 04257 if (!ast_strlen_zero(actionid)) { 04258 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04259 } else { 04260 idText[0] = '\0'; 04261 } 04262 04263 if (!(iter = ast_channel_iterator_all_new())) { 04264 astman_send_error(s, m, "Memory Allocation Failure"); 04265 return 1; 04266 } 04267 04268 astman_send_listack(s, m, "Channels will follow", "start"); 04269 04270 for (; (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) { 04271 struct ast_channel *bc; 04272 char durbuf[10] = ""; 04273 04274 ast_channel_lock(c); 04275 04276 bc = ast_bridged_channel(c); 04277 if (c->cdr && !ast_tvzero(c->cdr->start)) { 04278 duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000); 04279 durh = duration / 3600; 04280 durm = (duration % 3600) / 60; 04281 durs = duration % 60; 04282 snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs); 04283 } 04284 04285 astman_append(s, 04286 "Event: CoreShowChannel\r\n" 04287 "%s" 04288 "Channel: %s\r\n" 04289 "UniqueID: %s\r\n" 04290 "Context: %s\r\n" 04291 "Extension: %s\r\n" 04292 "Priority: %d\r\n" 04293 "ChannelState: %d\r\n" 04294 "ChannelStateDesc: %s\r\n" 04295 "Application: %s\r\n" 04296 "ApplicationData: %s\r\n" 04297 "CallerIDnum: %s\r\n" 04298 "Duration: %s\r\n" 04299 "AccountCode: %s\r\n" 04300 "BridgedChannel: %s\r\n" 04301 "BridgedUniqueID: %s\r\n" 04302 "\r\n", idText, c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state, 04303 ast_state2str(c->_state), c->appl ? c->appl : "", c->data ? S_OR(c->data, "") : "", 04304 S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""), 04305 durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : ""); 04306 04307 ast_channel_unlock(c); 04308 04309 numchans++; 04310 } 04311 04312 astman_append(s, 04313 "Event: CoreShowChannelsComplete\r\n" 04314 "EventList: Complete\r\n" 04315 "ListItems: %d\r\n" 04316 "%s" 04317 "\r\n", numchans, idText); 04318 04319 ast_channel_iterator_destroy(iter); 04320 04321 return 0; 04322 }
static int action_corestatus | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Show PBX core status information.
Definition at line 4193 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().
04194 { 04195 const char *actionid = astman_get_header(m, "ActionID"); 04196 char idText[150]; 04197 char startuptime[150], startupdate[150]; 04198 char reloadtime[150], reloaddate[150]; 04199 struct ast_tm tm; 04200 04201 if (!ast_strlen_zero(actionid)) { 04202 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04203 } else { 04204 idText[0] = '\0'; 04205 } 04206 04207 ast_localtime(&ast_startuptime, &tm, NULL); 04208 ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm); 04209 ast_strftime(startupdate, sizeof(startupdate), "%Y-%m-%d", &tm); 04210 ast_localtime(&ast_lastreloadtime, &tm, NULL); 04211 ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm); 04212 ast_strftime(reloaddate, sizeof(reloaddate), "%Y-%m-%d", &tm); 04213 04214 astman_append(s, "Response: Success\r\n" 04215 "%s" 04216 "CoreStartupDate: %s\r\n" 04217 "CoreStartupTime: %s\r\n" 04218 "CoreReloadDate: %s\r\n" 04219 "CoreReloadTime: %s\r\n" 04220 "CoreCurrentCalls: %d\r\n" 04221 "\r\n", 04222 idText, 04223 startupdate, 04224 startuptime, 04225 reloaddate, 04226 reloadtime, 04227 ast_active_channels() 04228 ); 04229 return 0; 04230 }
static int action_createconfig | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2739 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().
02740 { 02741 int fd; 02742 const char *fn = astman_get_header(m, "Filename"); 02743 struct ast_str *filepath = ast_str_alloca(PATH_MAX); 02744 ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR); 02745 ast_str_append(&filepath, 0, "%s", fn); 02746 02747 if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) { 02748 close(fd); 02749 astman_send_ack(s, m, "New configuration file created successfully"); 02750 } else { 02751 astman_send_error(s, m, strerror(errno)); 02752 } 02753 02754 return 0; 02755 }
static int action_events | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2881 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().
02882 { 02883 const char *mask = astman_get_header(m, "EventMask"); 02884 int res, x; 02885 02886 res = set_eventmask(s, mask); 02887 if (broken_events_action) { 02888 /* if this option is set we should not return a response on 02889 * error, or when all events are set */ 02890 02891 if (res > 0) { 02892 for (x = 0; x < ARRAY_LEN(perms); x++) { 02893 if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) { 02894 return 0; 02895 } 02896 } 02897 astman_append(s, "Response: Success\r\n" 02898 "Events: On\r\n\r\n"); 02899 } else if (res == 0) 02900 astman_append(s, "Response: Success\r\n" 02901 "Events: Off\r\n\r\n"); 02902 return 0; 02903 } 02904 02905 if (res > 0) 02906 astman_append(s, "Response: Success\r\n" 02907 "Events: On\r\n\r\n"); 02908 else if (res == 0) 02909 astman_append(s, "Response: Success\r\n" 02910 "Events: Off\r\n\r\n"); 02911 else 02912 astman_send_error(s, m, "Invalid event mask"); 02913 02914 return 0; 02915 }
static int action_extensionstate | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3990 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().
03991 { 03992 const char *exten = astman_get_header(m, "Exten"); 03993 const char *context = astman_get_header(m, "Context"); 03994 char hint[256] = ""; 03995 int status; 03996 if (ast_strlen_zero(exten)) { 03997 astman_send_error(s, m, "Extension not specified"); 03998 return 0; 03999 } 04000 if (ast_strlen_zero(context)) { 04001 context = "default"; 04002 } 04003 status = ast_extension_state(NULL, context, exten); 04004 ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten); 04005 astman_start_ack(s, m); 04006 astman_append(s, "Message: Extension Status\r\n" 04007 "Exten: %s\r\n" 04008 "Context: %s\r\n" 04009 "Hint: %s\r\n" 04010 "Status: %d\r\n\r\n", 04011 exten, context, hint, status); 04012 return 0; 04013 }
static int action_getconfig | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2354 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().
02355 { 02356 struct ast_config *cfg; 02357 const char *fn = astman_get_header(m, "Filename"); 02358 const char *category = astman_get_header(m, "Category"); 02359 int catcount = 0; 02360 int lineno = 0; 02361 char *cur_category = NULL; 02362 struct ast_variable *v; 02363 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02364 02365 if (ast_strlen_zero(fn)) { 02366 astman_send_error(s, m, "Filename not specified"); 02367 return 0; 02368 } 02369 cfg = ast_config_load2(fn, "manager", config_flags); 02370 if (cfg == CONFIG_STATUS_FILEMISSING) { 02371 astman_send_error(s, m, "Config file not found"); 02372 return 0; 02373 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02374 astman_send_error(s, m, "Config file has invalid format"); 02375 return 0; 02376 } 02377 02378 astman_start_ack(s, m); 02379 while ((cur_category = ast_category_browse(cfg, cur_category))) { 02380 if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) { 02381 lineno = 0; 02382 astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category); 02383 for (v = ast_variable_browse(cfg, cur_category); v; v = v->next) { 02384 astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value); 02385 } 02386 catcount++; 02387 } 02388 } 02389 if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */ 02390 astman_append(s, "No categories found\r\n"); 02391 } 02392 ast_config_destroy(cfg); 02393 astman_append(s, "\r\n"); 02394 02395 return 0; 02396 }
static int action_getconfigjson | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2446 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().
02447 { 02448 struct ast_config *cfg; 02449 const char *fn = astman_get_header(m, "Filename"); 02450 char *category = NULL; 02451 struct ast_variable *v; 02452 int comma1 = 0; 02453 char *buf = NULL; 02454 unsigned int buf_len = 0; 02455 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02456 02457 if (ast_strlen_zero(fn)) { 02458 astman_send_error(s, m, "Filename not specified"); 02459 return 0; 02460 } 02461 02462 if (!(cfg = ast_config_load2(fn, "manager", config_flags))) { 02463 astman_send_error(s, m, "Config file not found"); 02464 return 0; 02465 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02466 astman_send_error(s, m, "Config file has invalid format"); 02467 return 0; 02468 } 02469 02470 buf_len = 512; 02471 buf = alloca(buf_len); 02472 02473 astman_start_ack(s, m); 02474 astman_append(s, "JSON: {"); 02475 while ((category = ast_category_browse(cfg, category))) { 02476 int comma2 = 0; 02477 if (buf_len < 2 * strlen(category) + 1) { 02478 buf_len *= 2; 02479 buf = alloca(buf_len); 02480 } 02481 json_escape(buf, category); 02482 astman_append(s, "%s\"%s\":[", comma1 ? "," : "", buf); 02483 if (!comma1) { 02484 comma1 = 1; 02485 } 02486 for (v = ast_variable_browse(cfg, category); v; v = v->next) { 02487 if (comma2) { 02488 astman_append(s, ","); 02489 } 02490 if (buf_len < 2 * strlen(v->name) + 1) { 02491 buf_len *= 2; 02492 buf = alloca(buf_len); 02493 } 02494 json_escape(buf, v->name); 02495 astman_append(s, "\"%s", buf); 02496 if (buf_len < 2 * strlen(v->value) + 1) { 02497 buf_len *= 2; 02498 buf = alloca(buf_len); 02499 } 02500 json_escape(buf, v->value); 02501 astman_append(s, "%s\"", buf); 02502 if (!comma2) { 02503 comma2 = 1; 02504 } 02505 } 02506 astman_append(s, "]"); 02507 } 02508 astman_append(s, "}\r\n\r\n"); 02509 02510 ast_config_destroy(cfg); 02511 02512 return 0; 02513 }
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 2398 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().
02399 { 02400 struct ast_config *cfg; 02401 const char *fn = astman_get_header(m, "Filename"); 02402 char *category = NULL; 02403 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02404 int catcount = 0; 02405 02406 if (ast_strlen_zero(fn)) { 02407 astman_send_error(s, m, "Filename not specified"); 02408 return 0; 02409 } 02410 if (!(cfg = ast_config_load2(fn, "manager", config_flags))) { 02411 astman_send_error(s, m, "Config file not found"); 02412 return 0; 02413 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02414 astman_send_error(s, m, "Config file has invalid format"); 02415 return 0; 02416 } 02417 astman_start_ack(s, m); 02418 while ((category = ast_category_browse(cfg, category))) { 02419 astman_append(s, "Category-%06d: %s\r\n", catcount, category); 02420 catcount++; 02421 } 02422 if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */ 02423 astman_append(s, "Error: no categories found\r\n"); 02424 } 02425 ast_config_destroy(cfg); 02426 astman_append(s, "\r\n"); 02427 02428 return 0; 02429 }
static int action_listcommands | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2864 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().
02865 { 02866 struct manager_action *cur; 02867 struct ast_str *temp = ast_str_alloca(BUFSIZ); /* XXX very large ? */ 02868 02869 astman_start_ack(s, m); 02870 AST_RWLIST_TRAVERSE(&actions, cur, list) { 02871 if (s->session->writeperm & cur->authority || cur->authority == 0) { 02872 astman_append(s, "%s: %s (Priv: %s)\r\n", 02873 cur->action, cur->synopsis, authority_to_str(cur->authority, &temp)); 02874 } 02875 } 02876 astman_append(s, "\r\n"); 02877 02878 return 0; 02879 }
static int action_login | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2923 of file manager.c.
References 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, and mansession_session::username.
Referenced by __init_manager().
02924 { 02925 02926 /* still authenticated - don't process again */ 02927 if (s->session->authenticated) { 02928 astman_send_ack(s, m, "Already authenticated"); 02929 return 0; 02930 } 02931 02932 if (authenticate(s, m)) { 02933 sleep(1); 02934 astman_send_error(s, m, "Authentication failed"); 02935 return -1; 02936 } 02937 s->session->authenticated = 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 2917 of file manager.c.
References astman_send_response().
Referenced by __init_manager().
02918 { 02919 astman_send_response(s, m, "Goodbye", "Thanks for all the fish."); 02920 return -1; 02921 }
static int action_mailboxcount | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3969 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().
03970 { 03971 const char *mailbox = astman_get_header(m, "Mailbox"); 03972 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;; 03973 03974 if (ast_strlen_zero(mailbox)) { 03975 astman_send_error(s, m, "Mailbox not specified"); 03976 return 0; 03977 } 03978 ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs); 03979 astman_start_ack(s, m); 03980 astman_append(s, "Message: Mailbox Message Count\r\n" 03981 "Mailbox: %s\r\n" 03982 "UrgMessages: %d\r\n" 03983 "NewMessages: %d\r\n" 03984 "OldMessages: %d\r\n" 03985 "\r\n", 03986 mailbox, urgentmsgs, newmsgs, oldmsgs); 03987 return 0; 03988 }
static int action_mailboxstatus | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3952 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().
03953 { 03954 const char *mailbox = astman_get_header(m, "Mailbox"); 03955 int ret; 03956 03957 if (ast_strlen_zero(mailbox)) { 03958 astman_send_error(s, m, "Mailbox not specified"); 03959 return 0; 03960 } 03961 ret = ast_app_has_voicemail(mailbox, NULL); 03962 astman_start_ack(s, m); 03963 astman_append(s, "Message: Mailbox Status\r\n" 03964 "Mailbox: %s\r\n" 03965 "Waiting: %d\r\n\r\n", mailbox, ret); 03966 return 0; 03967 }
static int action_originate | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3817 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().
03818 { 03819 const char *name = astman_get_header(m, "Channel"); 03820 const char *exten = astman_get_header(m, "Exten"); 03821 const char *context = astman_get_header(m, "Context"); 03822 const char *priority = astman_get_header(m, "Priority"); 03823 const char *timeout = astman_get_header(m, "Timeout"); 03824 const char *callerid = astman_get_header(m, "CallerID"); 03825 const char *account = astman_get_header(m, "Account"); 03826 const char *app = astman_get_header(m, "Application"); 03827 const char *appdata = astman_get_header(m, "Data"); 03828 const char *async = astman_get_header(m, "Async"); 03829 const char *id = astman_get_header(m, "ActionID"); 03830 const char *codecs = astman_get_header(m, "Codecs"); 03831 struct ast_variable *vars; 03832 char *tech, *data; 03833 char *l = NULL, *n = NULL; 03834 int pi = 0; 03835 int res; 03836 int to = 30000; 03837 int reason = 0; 03838 char tmp[256]; 03839 char tmp2[256]; 03840 format_t format = AST_FORMAT_SLINEAR; 03841 03842 pthread_t th; 03843 if (ast_strlen_zero(name)) { 03844 astman_send_error(s, m, "Channel not specified"); 03845 return 0; 03846 } 03847 if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) { 03848 if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) { 03849 astman_send_error(s, m, "Invalid priority"); 03850 return 0; 03851 } 03852 } 03853 if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) { 03854 astman_send_error(s, m, "Invalid timeout"); 03855 return 0; 03856 } 03857 ast_copy_string(tmp, name, sizeof(tmp)); 03858 tech = tmp; 03859 data = strchr(tmp, '/'); 03860 if (!data) { 03861 astman_send_error(s, m, "Invalid channel"); 03862 return 0; 03863 } 03864 *data++ = '\0'; 03865 ast_copy_string(tmp2, callerid, sizeof(tmp2)); 03866 ast_callerid_parse(tmp2, &n, &l); 03867 if (n) { 03868 if (ast_strlen_zero(n)) { 03869 n = NULL; 03870 } 03871 } 03872 if (l) { 03873 ast_shrink_phone_number(l); 03874 if (ast_strlen_zero(l)) { 03875 l = NULL; 03876 } 03877 } 03878 if (!ast_strlen_zero(codecs)) { 03879 format = 0; 03880 ast_parse_allow_disallow(NULL, &format, codecs, 1); 03881 } 03882 /* Allocate requested channel variables */ 03883 vars = astman_get_variables(m); 03884 03885 if (ast_true(async)) { 03886 struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast)); 03887 if (!fast) { 03888 res = -1; 03889 } else { 03890 if (!ast_strlen_zero(id)) 03891 snprintf(fast->idtext, sizeof(fast->idtext), "ActionID: %s", id); 03892 ast_copy_string(fast->tech, tech, sizeof(fast->tech)); 03893 ast_copy_string(fast->data, data, sizeof(fast->data)); 03894 ast_copy_string(fast->app, app, sizeof(fast->app)); 03895 ast_copy_string(fast->appdata, appdata, sizeof(fast->appdata)); 03896 if (l) { 03897 ast_copy_string(fast->cid_num, l, sizeof(fast->cid_num)); 03898 } 03899 if (n) { 03900 ast_copy_string(fast->cid_name, n, sizeof(fast->cid_name)); 03901 } 03902 fast->vars = vars; 03903 ast_copy_string(fast->context, context, sizeof(fast->context)); 03904 ast_copy_string(fast->exten, exten, sizeof(fast->exten)); 03905 ast_copy_string(fast->account, account, sizeof(fast->account)); 03906 fast->format = format; 03907 fast->timeout = to; 03908 fast->priority = pi; 03909 if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) { 03910 ast_free(fast); 03911 res = -1; 03912 } else { 03913 res = 0; 03914 } 03915 } 03916 } else if (!ast_strlen_zero(app)) { 03917 /* To run the System application (or anything else that goes to shell), you must have the additional System privilege */ 03918 if (!(s->session->writeperm & EVENT_FLAG_SYSTEM) 03919 && ( 03920 strcasestr(app, "system") || /* System(rm -rf /) 03921 TrySystem(rm -rf /) */ 03922 strcasestr(app, "exec") || /* Exec(System(rm -rf /)) 03923 TryExec(System(rm -rf /)) */ 03924 strcasestr(app, "agi") || /* AGI(/bin/rm,-rf /) 03925 EAGI(/bin/rm,-rf /) */ 03926 strstr(appdata, "SHELL") || /* NoOp(${SHELL(rm -rf /)}) */ 03927 strstr(appdata, "EVAL") /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ 03928 )) { 03929 astman_send_error(s, m, "Originate with certain 'Application' arguments requires the additional System privilege, which you do not have."); 03930 return 0; 03931 } 03932 res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL); 03933 } else { 03934 if (exten && context && pi) { 03935 res = ast_pbx_outgoing_exten(tech, format, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL); 03936 } else { 03937 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'"); 03938 if (vars) { 03939 ast_variables_destroy(vars); 03940 } 03941 return 0; 03942 } 03943 } 03944 if (!res) { 03945 astman_send_ack(s, m, "Originate successfully queued"); 03946 } else { 03947 astman_send_error(s, m, "Originate failed"); 03948 } 03949 return 0; 03950 }
static int action_ping | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2336 of file manager.c.
References ast_strlen_zero(), ast_tvnow(), astman_append(), and astman_get_header().
Referenced by __init_manager().
02337 { 02338 const char *actionid = astman_get_header(m, "ActionID"); 02339 struct timeval now = ast_tvnow(); 02340 02341 astman_append(s, "Response: Success\r\n"); 02342 if (!ast_strlen_zero(actionid)){ 02343 astman_append(s, "ActionID: %s\r\n", actionid); 02344 } 02345 astman_append( 02346 s, 02347 "Ping: Pong\r\n" 02348 "Timestamp: %ld.%06lu\r\n" 02349 "\r\n", 02350 (long) now.tv_sec, (unsigned long) now.tv_usec); 02351 return 0; 02352 }
static int action_redirect | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
action_redirect: The redirect manager command
Definition at line 3276 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().
03277 { 03278 const char *name = astman_get_header(m, "Channel"); 03279 const char *name2 = astman_get_header(m, "ExtraChannel"); 03280 const char *exten = astman_get_header(m, "Exten"); 03281 const char *exten2 = astman_get_header(m, "ExtraExten"); 03282 const char *context = astman_get_header(m, "Context"); 03283 const char *context2 = astman_get_header(m, "ExtraContext"); 03284 const char *priority = astman_get_header(m, "Priority"); 03285 const char *priority2 = astman_get_header(m, "ExtraPriority"); 03286 struct ast_channel *chan, *chan2 = NULL; 03287 int pi, pi2 = 0; 03288 int res; 03289 03290 if (ast_strlen_zero(name)) { 03291 astman_send_error(s, m, "Channel not specified"); 03292 return 0; 03293 } 03294 03295 if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) { 03296 if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) { 03297 astman_send_error(s, m, "Invalid priority"); 03298 return 0; 03299 } 03300 } 03301 03302 if (!ast_strlen_zero(priority2) && (sscanf(priority2, "%30d", &pi2) != 1)) { 03303 if ((pi2 = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL)) < 1) { 03304 astman_send_error(s, m, "Invalid ExtraPriority"); 03305 return 0; 03306 } 03307 } 03308 03309 if (!(chan = ast_channel_get_by_name(name))) { 03310 char buf[256]; 03311 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name); 03312 astman_send_error(s, m, buf); 03313 return 0; 03314 } 03315 03316 if (ast_check_hangup_locked(chan)) { 03317 astman_send_error(s, m, "Redirect failed, channel not up."); 03318 chan = ast_channel_unref(chan); 03319 return 0; 03320 } 03321 03322 if (!ast_strlen_zero(name2)) { 03323 chan2 = ast_channel_get_by_name(name2); 03324 } 03325 03326 if (chan2 && ast_check_hangup_locked(chan2)) { 03327 astman_send_error(s, m, "Redirect failed, extra channel not up."); 03328 chan = ast_channel_unref(chan); 03329 chan2 = ast_channel_unref(chan2); 03330 return 0; 03331 } 03332 03333 if (chan->pbx) { 03334 ast_channel_lock(chan); 03335 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */ 03336 ast_channel_unlock(chan); 03337 } 03338 03339 res = ast_async_goto(chan, context, exten, pi); 03340 if (!res) { 03341 if (!ast_strlen_zero(name2)) { 03342 if (chan2) { 03343 if (chan2->pbx) { 03344 ast_channel_lock(chan2); 03345 ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */ 03346 ast_channel_unlock(chan2); 03347 } 03348 if (context2) { 03349 res = ast_async_goto(chan2, context2, exten2, pi2); 03350 } else { 03351 res = ast_async_goto(chan2, context, exten, pi); 03352 } 03353 } else { 03354 res = -1; 03355 } 03356 if (!res) { 03357 astman_send_ack(s, m, "Dual Redirect successful"); 03358 } else { 03359 astman_send_error(s, m, "Secondary redirect failed"); 03360 } 03361 } else { 03362 astman_send_ack(s, m, "Redirect successful"); 03363 } 03364 } else { 03365 astman_send_error(s, m, "Redirect failed"); 03366 } 03367 03368 if (chan) { 03369 chan = ast_channel_unref(chan); 03370 } 03371 03372 if (chan2) { 03373 chan2 = ast_channel_unref(chan2); 03374 } 03375 03376 return 0; 03377 }
static int action_reload | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Send a reload event.
Definition at line 4233 of file manager.c.
References ast_module_reload(), astman_get_header(), astman_send_ack(), astman_send_error(), and S_OR.
Referenced by __init_manager().
04234 { 04235 const char *module = astman_get_header(m, "Module"); 04236 int res = ast_module_reload(S_OR(module, NULL)); 04237 04238 if (res == 2) { 04239 astman_send_ack(s, m, "Module Reloaded"); 04240 } else { 04241 astman_send_error(s, m, s == 0 ? "No such module" : "Module does not support reload"); 04242 } 04243 return 0; 04244 }
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_lock, ast_channel_unlock, 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 ast_channel_lock(c); 03262 res = ast_sendtext(c, textmsg); 03263 ast_channel_unlock(c); 03264 c = ast_channel_unref(c); 03265 03266 if (res > 0) { 03267 astman_send_ack(s, m, "Success"); 03268 } else { 03269 astman_send_error(s, m, "Failure"); 03270 } 03271 03272 return res; 03273 }
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 4015 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().
04016 { 04017 struct ast_channel *c; 04018 const char *name = astman_get_header(m, "Channel"); 04019 double timeout = atof(astman_get_header(m, "Timeout")); 04020 struct timeval when = { timeout, 0 }; 04021 04022 if (ast_strlen_zero(name)) { 04023 astman_send_error(s, m, "No channel specified"); 04024 return 0; 04025 } 04026 04027 if (!timeout || timeout < 0) { 04028 astman_send_error(s, m, "No timeout specified"); 04029 return 0; 04030 } 04031 04032 if (!(c = ast_channel_get_by_name(name))) { 04033 astman_send_error(s, m, "No such channel"); 04034 return 0; 04035 } 04036 04037 when.tv_usec = (timeout - when.tv_sec) * 1000000.0; 04038 04039 ast_channel_lock(c); 04040 ast_channel_setwhentohangup_tv(c, when); 04041 ast_channel_unlock(c); 04042 c = ast_channel_unref(c); 04043 04044 astman_send_ack(s, m, "Timeout Set"); 04045 04046 return 0; 04047 }
static int action_updateconfig | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2661 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().
02662 { 02663 struct ast_config *cfg; 02664 const char *sfn = astman_get_header(m, "SrcFilename"); 02665 const char *dfn = astman_get_header(m, "DstFilename"); 02666 int res; 02667 const char *rld = astman_get_header(m, "Reload"); 02668 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02669 enum error_type result; 02670 02671 if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) { 02672 astman_send_error(s, m, "Filename not specified"); 02673 return 0; 02674 } 02675 if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) { 02676 astman_send_error(s, m, "Config file not found"); 02677 return 0; 02678 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02679 astman_send_error(s, m, "Config file has invalid format"); 02680 return 0; 02681 } 02682 result = handle_updates(s, m, cfg, dfn); 02683 if (!result) { 02684 ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */ 02685 res = ast_config_text_file_save(dfn, cfg, "Manager"); 02686 ast_config_destroy(cfg); 02687 if (res) { 02688 astman_send_error(s, m, "Save of config failed"); 02689 return 0; 02690 } 02691 astman_send_ack(s, m, NULL); 02692 if (!ast_strlen_zero(rld)) { 02693 if (ast_true(rld)) { 02694 rld = NULL; 02695 } 02696 ast_module_reload(rld); 02697 } 02698 } else { 02699 ast_config_destroy(cfg); 02700 switch(result) { 02701 case UNKNOWN_ACTION: 02702 astman_send_error(s, m, "Unknown action command"); 02703 break; 02704 case UNKNOWN_CATEGORY: 02705 astman_send_error(s, m, "Given category does not exist"); 02706 break; 02707 case UNSPECIFIED_CATEGORY: 02708 astman_send_error(s, m, "Category not specified"); 02709 break; 02710 case UNSPECIFIED_ARGUMENT: 02711 astman_send_error(s, m, "Problem with category, value, or line (if required)"); 02712 break; 02713 case FAILURE_ALLOCATION: 02714 astman_send_error(s, m, "Memory allocation failure, this should not happen"); 02715 break; 02716 case FAILURE_NEWCAT: 02717 astman_send_error(s, m, "Create category did not complete successfully"); 02718 break; 02719 case FAILURE_DELCAT: 02720 astman_send_error(s, m, "Delete category did not complete successfully"); 02721 break; 02722 case FAILURE_EMPTYCAT: 02723 astman_send_error(s, m, "Empty category did not complete successfully"); 02724 break; 02725 case FAILURE_UPDATE: 02726 astman_send_error(s, m, "Update did not complete successfully"); 02727 break; 02728 case FAILURE_DELETE: 02729 astman_send_error(s, m, "Delete did not complete successfully"); 02730 break; 02731 case FAILURE_APPEND: 02732 astman_send_error(s, m, "Append did not complete successfully"); 02733 break; 02734 } 02735 } 02736 return 0; 02737 }
static int action_userevent | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4131 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().
04132 { 04133 const char *event = astman_get_header(m, "UserEvent"); 04134 struct ast_str *body = ast_str_thread_get(&userevent_buf, 16); 04135 int x; 04136 04137 ast_str_reset(body); 04138 04139 for (x = 0; x < m->hdrcount; x++) { 04140 if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) { 04141 ast_str_append(&body, 0, "%s\r\n", m->headers[x]); 04142 } 04143 } 04144 04145 astman_send_ack(s, m, "Event Sent"); 04146 manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, ast_str_buffer(body)); 04147 return 0; 04148 }
static int action_waitevent | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2757 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().
02758 { 02759 const char *timeouts = astman_get_header(m, "Timeout"); 02760 int timeout = -1; 02761 int x; 02762 int needexit = 0; 02763 const char *id = astman_get_header(m, "ActionID"); 02764 char idText[256]; 02765 02766 if (!ast_strlen_zero(id)) { 02767 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 02768 } else { 02769 idText[0] = '\0'; 02770 } 02771 02772 if (!ast_strlen_zero(timeouts)) { 02773 sscanf(timeouts, "%30i", &timeout); 02774 if (timeout < -1) { 02775 timeout = -1; 02776 } 02777 /* XXX maybe put an upper bound, or prevent the use of 0 ? */ 02778 } 02779 02780 ao2_lock(s->session); 02781 if (s->session->waiting_thread != AST_PTHREADT_NULL) { 02782 pthread_kill(s->session->waiting_thread, SIGURG); 02783 } 02784 02785 if (s->session->managerid) { /* AMI-over-HTTP session */ 02786 /* 02787 * Make sure the timeout is within the expire time of the session, 02788 * as the client will likely abort the request if it does not see 02789 * data coming after some amount of time. 02790 */ 02791 time_t now = time(NULL); 02792 int max = s->session->sessiontimeout - now - 10; 02793 02794 if (max < 0) { /* We are already late. Strange but possible. */ 02795 max = 0; 02796 } 02797 if (timeout < 0 || timeout > max) { 02798 timeout = max; 02799 } 02800 if (!s->session->send_events) { /* make sure we record events */ 02801 s->session->send_events = -1; 02802 } 02803 } 02804 ao2_unlock(s->session); 02805 02806 /* XXX should this go inside the lock ? */ 02807 s->session->waiting_thread = pthread_self(); /* let new events wake up this thread */ 02808 ast_debug(1, "Starting waiting for an event!\n"); 02809 02810 for (x = 0; x < timeout || timeout < 0; x++) { 02811 ao2_lock(s->session); 02812 if (AST_RWLIST_NEXT(s->session->last_ev, eq_next)) { 02813 needexit = 1; 02814 } 02815 /* We can have multiple HTTP session point to the same mansession entry. 02816 * The way we deal with it is not very nice: newcomers kick out the previous 02817 * HTTP session. XXX this needs to be improved. 02818 */ 02819 if (s->session->waiting_thread != pthread_self()) { 02820 needexit = 1; 02821 } 02822 if (s->session->needdestroy) { 02823 needexit = 1; 02824 } 02825 ao2_unlock(s->session); 02826 if (needexit) { 02827 break; 02828 } 02829 if (s->session->managerid == 0) { /* AMI session */ 02830 if (ast_wait_for_input(s->session->fd, 1000)) { 02831 break; 02832 } 02833 } else { /* HTTP session */ 02834 sleep(1); 02835 } 02836 } 02837 ast_debug(1, "Finished waiting for an event!\n"); 02838 02839 ao2_lock(s->session); 02840 if (s->session->waiting_thread == pthread_self()) { 02841 struct eventqent *eqe = s->session->last_ev; 02842 astman_send_response(s, m, "Success", "Waiting for Event completed."); 02843 while ((eqe = advance_event(eqe))) { 02844 if (((s->session->readperm & eqe->category) == eqe->category) && 02845 ((s->session->send_events & eqe->category) == eqe->category)) { 02846 astman_append(s, "%s", eqe->eventdata); 02847 } 02848 s->session->last_ev = eqe; 02849 } 02850 astman_append(s, 02851 "Event: WaitEventComplete\r\n" 02852 "%s" 02853 "\r\n", idText); 02854 s->session->waiting_thread = AST_PTHREADT_NULL; 02855 } else { 02856 ast_debug(1, "Abandoning event request!\n"); 02857 } 02858 ao2_unlock(s->session); 02859 02860 return 0; 02861 }
Definition at line 1682 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().
01683 { 01684 struct eventqent *next; 01685 01686 AST_RWLIST_RDLOCK(&all_events); 01687 if ((next = AST_RWLIST_NEXT(e, eq_next))) { 01688 ast_atomic_fetchadd_int(&next->usecount, 1); 01689 ast_atomic_fetchadd_int(&e->usecount, -1); 01690 } 01691 AST_RWLIST_UNLOCK(&all_events); 01692 return next; 01693 }
static int aocmessage_get_unit_entry | ( | const struct message * | m, | |
struct ast_aoc_unit_entry * | entry, | |||
unsigned int | entry_num | |||
) | [static] |
Definition at line 3587 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().
03588 { 03589 const char *unitamount; 03590 const char *unittype; 03591 struct ast_str *str = ast_str_alloca(32); 03592 03593 memset(entry, 0, sizeof(*entry)); 03594 03595 ast_str_set(&str, 0, "UnitAmount(%u)", entry_num); 03596 unitamount = astman_get_header(m, ast_str_buffer(str)); 03597 03598 ast_str_set(&str, 0, "UnitType(%u)", entry_num); 03599 unittype = astman_get_header(m, ast_str_buffer(str)); 03600 03601 if (!ast_strlen_zero(unitamount) && (sscanf(unitamount, "%30u", &entry->amount) == 1)) { 03602 entry->valid_amount = 1; 03603 } 03604 03605 if (!ast_strlen_zero(unittype) && sscanf(unittype, "%30u", &entry->type) == 1) { 03606 entry->valid_type = 1; 03607 } 03608 03609 return 0; 03610 }
static void append_channel_vars | ( | struct ast_str ** | pbuf, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 4761 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().
04762 { 04763 struct manager_channel_variable *var; 04764 AST_RWLIST_RDLOCK(&channelvars); 04765 AST_LIST_TRAVERSE(&channelvars, var, entry) { 04766 const char *val = ""; 04767 if (var->isfunc) { 04768 struct ast_str *res = ast_str_thread_get(&manager_event_funcbuf, 16); 04769 int ret; 04770 if (res && (ret = ast_func_read2(chan, var->name, &res, 0)) == 0) { 04771 val = ast_str_buffer(res); 04772 } 04773 } else { 04774 val = pbx_builtin_getvar_helper(chan, var->name); 04775 } 04776 ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", chan->name, var->name, val ? val : ""); 04777 } 04778 AST_RWLIST_UNLOCK(&channelvars); 04779 }
static int append_event | ( | const char * | str, | |
int | category | |||
) | [static] |
Definition at line 4735 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().
04736 { 04737 struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str)); 04738 static int seq; /* sequence number */ 04739 04740 if (!tmp) { 04741 return -1; 04742 } 04743 04744 /* need to init all fields, because ast_malloc() does not */ 04745 tmp->usecount = 0; 04746 tmp->category = category; 04747 tmp->seq = ast_atomic_fetchadd_int(&seq, 1); 04748 tmp->tv = ast_tvnow(); 04749 AST_RWLIST_NEXT(tmp, eq_next) = NULL; 04750 strcpy(tmp->eventdata, str); 04751 04752 AST_RWLIST_WRLOCK(&all_events); 04753 AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next); 04754 AST_RWLIST_UNLOCK(&all_events); 04755 04756 return 0; 04757 }
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 1781 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.
01782 { 01783 const char *action; 01784 int ret = 0; 01785 struct manager_action *tmp; 01786 struct mansession s = {.session = NULL, }; 01787 struct message m = { 0 }; 01788 char header_buf[1025] = { '\0' }; 01789 const char *src = msg; 01790 int x = 0; 01791 int curlen; 01792 01793 if (hook == NULL) { 01794 return -1; 01795 } 01796 01797 /* convert msg string to message struct */ 01798 curlen = strlen(msg); 01799 for (x = 0; x < curlen; x++) { 01800 int cr; /* set if we have \r */ 01801 if (src[x] == '\r' && x+1 < curlen && src[x+1] == '\n') 01802 cr = 2; /* Found. Update length to include \r\n */ 01803 else if (src[x] == '\n') 01804 cr = 1; /* also accept \n only */ 01805 else 01806 continue; 01807 /* don't copy empty lines */ 01808 if (x) { 01809 memmove(header_buf, src, x); /*... but trim \r\n */ 01810 header_buf[x] = '\0'; /* terminate the string */ 01811 m.headers[m.hdrcount++] = ast_strdupa(header_buf); 01812 } 01813 x += cr; 01814 curlen -= x; /* remaining size */ 01815 src += x; /* update pointer */ 01816 x = -1; /* reset loop */ 01817 } 01818 01819 action = astman_get_header(&m,"Action"); 01820 if (action && strcasecmp(action,"login")) { 01821 01822 AST_RWLIST_RDLOCK(&actions); 01823 AST_RWLIST_TRAVERSE(&actions, tmp, list) { 01824 if (strcasecmp(action, tmp->action)) 01825 continue; 01826 /* 01827 * we have to simulate a session for this action request 01828 * to be able to pass it down for processing 01829 * This is necessary to meet the previous design of manager.c 01830 */ 01831 s.hook = hook; 01832 s.f = (void*)1; /* set this to something so our request will make it through all functions that test it*/ 01833 ret = tmp->func(&s, &m); 01834 break; 01835 } 01836 AST_RWLIST_UNLOCK(&actions); 01837 } 01838 return ret; 01839 }
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 1152 of file manager.c.
References eventqent::next.
Referenced by get_perm().
01153 { 01154 const char *val = bigstr, *next; 01155 01156 do { 01157 if ((next = strchr(val, delim))) { 01158 if (!strncmp(val, smallstr, (next - val))) { 01159 return 1; 01160 } else { 01161 continue; 01162 } 01163 } else { 01164 return !strcmp(smallstr, val); 01165 } 01166 } while (*(val = (next + 1))); 01167 01168 return 0; 01169 }
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 4943 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().
04944 { 04945 struct manager_action *cur = NULL; 04946 #ifdef AST_XML_DOCS 04947 char *tmpxml; 04948 #endif 04949 04950 if (!(cur = ast_calloc_with_stringfields(1, struct manager_action, 128))) { 04951 return -1; 04952 } 04953 04954 cur->action = action; 04955 cur->authority = auth; 04956 cur->func = func; 04957 #ifdef AST_XML_DOCS 04958 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 04959 tmpxml = ast_xmldoc_build_synopsis("manager", action); 04960 ast_string_field_set(cur, synopsis, tmpxml); 04961 ast_free(tmpxml); 04962 04963 tmpxml = ast_xmldoc_build_syntax("manager", action); 04964 ast_string_field_set(cur, syntax, tmpxml); 04965 ast_free(tmpxml); 04966 04967 tmpxml = ast_xmldoc_build_description("manager", action); 04968 ast_string_field_set(cur, description, tmpxml); 04969 ast_free(tmpxml); 04970 04971 tmpxml = ast_xmldoc_build_seealso("manager", action); 04972 ast_string_field_set(cur, seealso, tmpxml); 04973 ast_free(tmpxml); 04974 04975 tmpxml = ast_xmldoc_build_arguments("manager", action); 04976 ast_string_field_set(cur, arguments, tmpxml); 04977 ast_free(tmpxml); 04978 04979 cur->docsrc = AST_XML_DOC; 04980 } else { 04981 #endif 04982 ast_string_field_set(cur, synopsis, synopsis); 04983 ast_string_field_set(cur, description, description); 04984 #ifdef AST_XML_DOCS 04985 cur->docsrc = AST_STATIC_DOC; 04986 } 04987 #endif 04988 if (ast_manager_register_struct(cur)) { 04989 ast_free(cur); 04990 return -1; 04991 } 04992 04993 return 0; 04994 }
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 1022 of file manager.c.
References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
01023 { 01024 AST_RWLIST_WRLOCK(&manager_hooks); 01025 AST_RWLIST_INSERT_TAIL(&manager_hooks, hook, list); 01026 AST_RWLIST_UNLOCK(&manager_hooks); 01027 }
static int ast_manager_register_struct | ( | struct manager_action * | act | ) | [static] |
Definition at line 4906 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().
04907 { 04908 struct manager_action *cur, *prev = NULL; 04909 struct timespec tv = { 5, }; 04910 04911 if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) { 04912 ast_log(LOG_ERROR, "Could not obtain lock on manager list\n"); 04913 return -1; 04914 } 04915 AST_RWLIST_TRAVERSE(&actions, cur, list) { 04916 int ret = strcasecmp(cur->action, act->action); 04917 if (ret == 0) { 04918 ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action); 04919 AST_RWLIST_UNLOCK(&actions); 04920 return -1; 04921 } 04922 if (ret > 0) { /* Insert these alphabetically */ 04923 prev = cur; 04924 break; 04925 } 04926 } 04927 04928 if (prev) { 04929 AST_RWLIST_INSERT_AFTER(&actions, prev, act, list); 04930 } else { 04931 AST_RWLIST_INSERT_HEAD(&actions, act, list); 04932 } 04933 04934 ast_verb(2, "Manager registered action %s\n", act->action); 04935 04936 AST_RWLIST_UNLOCK(&actions); 04937 04938 return 0; 04939 }
int ast_manager_unregister | ( | char * | action | ) |
Unregister a registered manager command.
action | Name of registered Action: |
Definition at line 4872 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().
04873 { 04874 struct manager_action *cur; 04875 struct timespec tv = { 5, }; 04876 04877 if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) { 04878 ast_log(LOG_ERROR, "Could not obtain lock on manager list\n"); 04879 return -1; 04880 } 04881 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) { 04882 if (!strcasecmp(action, cur->action)) { 04883 AST_RWLIST_REMOVE_CURRENT(list); 04884 ast_string_field_free_memory(cur); 04885 ast_free(cur); 04886 ast_verb(2, "Manager unregistered action %s\n", action); 04887 break; 04888 } 04889 } 04890 AST_RWLIST_TRAVERSE_SAFE_END; 04891 AST_RWLIST_UNLOCK(&actions); 04892 04893 return 0; 04894 }
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 1030 of file manager.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.
01031 { 01032 AST_RWLIST_WRLOCK(&manager_hooks); 01033 AST_RWLIST_REMOVE(&manager_hooks, hook, list); 01034 AST_RWLIST_UNLOCK(&manager_hooks); 01035 }
void astman_append | ( | struct mansession * | s, | |
const char * | fmt, | |||
... | ||||
) |
utility functions for creating AMI replies
Definition at line 1885 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().
01886 { 01887 va_list ap; 01888 struct ast_str *buf; 01889 01890 if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) { 01891 return; 01892 } 01893 01894 va_start(ap, fmt); 01895 ast_str_set_va(&buf, 0, fmt, ap); 01896 va_end(ap); 01897 01898 if (s->f != NULL || s->session->f != NULL) { 01899 send_string(s, ast_str_buffer(buf)); 01900 } else { 01901 ast_verbose("fd == -1 in astman_append, should not happen\n"); 01902 } 01903 }
const char* astman_get_header | ( | const struct message * | m, | |
char * | var | |||
) |
Get header from mananger transaction.
Definition at line 1732 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().
01733 { 01734 return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH); 01735 }
struct ast_variable* astman_get_variables | ( | const struct message * | m | ) |
Get a linked list of the Variable: headers.
Definition at line 1738 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().
01739 { 01740 int varlen, x, y; 01741 struct ast_variable *head = NULL, *cur; 01742 01743 AST_DECLARE_APP_ARGS(args, 01744 AST_APP_ARG(vars)[32]; 01745 ); 01746 01747 varlen = strlen("Variable: "); 01748 01749 for (x = 0; x < m->hdrcount; x++) { 01750 char *parse, *var, *val; 01751 01752 if (strncasecmp("Variable: ", m->headers[x], varlen)) { 01753 continue; 01754 } 01755 parse = ast_strdupa(m->headers[x] + varlen); 01756 01757 AST_STANDARD_APP_ARGS(args, parse); 01758 if (!args.argc) { 01759 continue; 01760 } 01761 for (y = 0; y < args.argc; y++) { 01762 if (!args.vars[y]) { 01763 continue; 01764 } 01765 var = val = ast_strdupa(args.vars[y]); 01766 strsep(&val, "="); 01767 if (!val || ast_strlen_zero(var)) { 01768 continue; 01769 } 01770 cur = ast_variable_new(var, val, ""); 01771 cur->next = head; 01772 head = cur; 01773 } 01774 } 01775 01776 return head; 01777 }
void astman_send_ack | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | msg | |||
) |
Send ack in manager transaction.
Definition at line 1952 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().
01953 { 01954 astman_send_response_full(s, m, "Success", msg, NULL); 01955 }
void astman_send_error | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | error | |||
) |
Send error in manager transaction.
Definition at line 1947 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().
01948 { 01949 astman_send_response_full(s, m, "Error", error, NULL); 01950 }
void astman_send_listack | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | msg, | |||
char * | listflag | |||
) |
Send ack in manager list transaction.
Definition at line 1962 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().
01963 { 01964 astman_send_response_full(s, m, "Success", msg, listflag); 01965 }
void astman_send_response | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | resp, | |||
char * | msg | |||
) |
Send response in manager transaction.
Definition at line 1942 of file manager.c.
References astman_send_response_full().
Referenced by action_logoff().
01943 { 01944 astman_send_response_full(s, m, resp, msg, NULL); 01945 }
static void astman_send_response_full | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | resp, | |||
char * | msg, | |||
char * | listflag | |||
) | [static] |
Definition at line 1922 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().
01923 { 01924 const char *id = astman_get_header(m, "ActionID"); 01925 01926 astman_append(s, "Response: %s\r\n", resp); 01927 if (!ast_strlen_zero(id)) { 01928 astman_append(s, "ActionID: %s\r\n", id); 01929 } 01930 if (listflag) { 01931 astman_append(s, "EventList: %s\r\n", listflag); /* Start, complete, cancelled */ 01932 } 01933 if (msg == MSG_MOREDATA) { 01934 return; 01935 } else if (msg) { 01936 astman_append(s, "Message: %s\r\n\r\n", msg); 01937 } else { 01938 astman_append(s, "\r\n"); 01939 } 01940 }
static void astman_start_ack | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 1957 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().
01958 { 01959 astman_send_response_full(s, m, "Success", MSG_MOREDATA, NULL); 01960 }
static int authenticate | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2239 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.
02240 { 02241 const char *username = astman_get_header(m, "Username"); 02242 const char *password = astman_get_header(m, "Secret"); 02243 int error = -1; 02244 struct ast_manager_user *user = NULL; 02245 regex_t *regex_filter; 02246 struct ao2_iterator filter_iter; 02247 struct ast_sockaddr addr; 02248 02249 if (ast_strlen_zero(username)) { /* missing username */ 02250 return -1; 02251 } 02252 02253 /* locate user in locked state */ 02254 AST_RWLIST_WRLOCK(&users); 02255 02256 ast_sockaddr_from_sin(&addr, &s->session->sin); 02257 02258 if (!(user = get_manager_by_name_locked(username))) { 02259 report_invalid_user(s, username); 02260 ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02261 } else if (user->ha && !ast_apply_ha(user->ha, &addr)) { 02262 report_failed_acl(s, username); 02263 ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02264 } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) { 02265 const char *key = astman_get_header(m, "Key"); 02266 if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) { 02267 int x; 02268 int len = 0; 02269 char md5key[256] = ""; 02270 struct MD5Context md5; 02271 unsigned char digest[16]; 02272 02273 MD5Init(&md5); 02274 MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge)); 02275 MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret)); 02276 MD5Final(digest, &md5); 02277 for (x = 0; x < 16; x++) 02278 len += sprintf(md5key + len, "%2.2x", digest[x]); 02279 if (!strcmp(md5key, key)) { 02280 error = 0; 02281 } else { 02282 report_failed_challenge_response(s, key, md5key); 02283 } 02284 } else { 02285 ast_debug(1, "MD5 authentication is not possible. challenge: '%s'\n", 02286 S_OR(s->session->challenge, "")); 02287 } 02288 } else if (user->secret) { 02289 if (!strcmp(password, user->secret)) { 02290 error = 0; 02291 } else { 02292 report_inval_password(s, username); 02293 } 02294 } 02295 02296 if (error) { 02297 ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02298 AST_RWLIST_UNLOCK(&users); 02299 return -1; 02300 } 02301 02302 /* auth complete */ 02303 02304 /* All of the user parameters are copied to the session so that in the event 02305 * of a reload and a configuration change, the session parameters are not 02306 * changed. */ 02307 ast_copy_string(s->session->username, username, sizeof(s->session->username)); 02308 s->session->readperm = user->readperm; 02309 s->session->writeperm = user->writeperm; 02310 s->session->writetimeout = user->writetimeout; 02311 02312 filter_iter = ao2_iterator_init(user->whitefilters, 0); 02313 while ((regex_filter = ao2_iterator_next(&filter_iter))) { 02314 ao2_t_link(s->session->whitefilters, regex_filter, "add white user filter to session"); 02315 ao2_t_ref(regex_filter, -1, "remove iterator ref"); 02316 } 02317 ao2_iterator_destroy(&filter_iter); 02318 02319 filter_iter = ao2_iterator_init(user->blackfilters, 0); 02320 while ((regex_filter = ao2_iterator_next(&filter_iter))) { 02321 ao2_t_link(s->session->blackfilters, regex_filter, "add black user filter to session"); 02322 ao2_t_ref(regex_filter, -1, "remove iterator ref"); 02323 } 02324 ao2_iterator_destroy(&filter_iter); 02325 02326 s->session->sessionstart = time(NULL); 02327 s->session->sessionstart_tv = ast_tvnow(); 02328 set_eventmask(s, astman_get_header(m, "Events")); 02329 02330 report_auth_success(s); 02331 02332 AST_RWLIST_UNLOCK(&users); 02333 return 0; 02334 }
static const char* authority_to_str | ( | int | authority, | |
struct ast_str ** | res | |||
) | [static] |
Convert authority code to a list of options.
Definition at line 1128 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().
01129 { 01130 int i; 01131 char *sep = ""; 01132 01133 ast_str_reset(*res); 01134 for (i = 0; i < ARRAY_LEN(perms) - 1; i++) { 01135 if (authority & perms[i].num) { 01136 ast_str_append(res, 0, "%s%s", sep, perms[i].label); 01137 sep = ","; 01138 } 01139 } 01140 01141 if (ast_str_strlen(*res) == 0) /* replace empty string with something sensible */ 01142 ast_str_append(res, 0, "<none>"); 01143 01144 return ast_str_buffer(*res); 01145 }
static int blackfilter_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 4063 of file manager.c.
References CMP_MATCH, and CMP_STOP.
Referenced by match_filter().
04064 { 04065 regex_t *regex_filter = obj; 04066 const char *eventdata = arg; 04067 int *result = data; 04068 04069 if (regexec(regex_filter, eventdata, 0, NULL, 0)) { 04070 *result = 1; 04071 return (CMP_MATCH | CMP_STOP); 04072 } 04073 04074 return 0; 04075 }
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 1269 of file manager.c.
References ao2_alloc, ao2_container_alloc, ao2_link, ao2_ref, AST_PTHREADT_NULL, and session_destructor().
Referenced by session_do().
01270 { 01271 struct mansession_session *newsession; 01272 01273 if (!(newsession = ao2_alloc(sizeof(*newsession), session_destructor))) { 01274 return NULL; 01275 } 01276 01277 if (!(newsession->whitefilters = ao2_container_alloc(1, NULL, NULL))) { 01278 ao2_ref(newsession, -1); 01279 return NULL; 01280 } 01281 01282 if (!(newsession->blackfilters = ao2_container_alloc(1, NULL, NULL))) { 01283 ao2_ref(newsession, -1); /* session_destructor will cleanup the other filter */ 01284 return NULL; 01285 } 01286 01287 newsession->fd = -1; 01288 newsession->waiting_thread = AST_PTHREADT_NULL; 01289 newsession->writetimeout = 100; 01290 newsession->send_events = -1; 01291 newsession->sin = sin; 01292 01293 ao2_link(sessions, newsession); 01294 01295 return newsession; 01296 }
static int check_blacklist | ( | const char * | cmd | ) | [static] |
Definition at line 3428 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().
03429 { 03430 char *cmd_copy, *cur_cmd; 03431 char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, }; 03432 int i; 03433 03434 cmd_copy = ast_strdupa(cmd); 03435 for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) { 03436 cur_cmd = ast_strip(cur_cmd); 03437 if (ast_strlen_zero(cur_cmd)) { 03438 i--; 03439 continue; 03440 } 03441 03442 cmd_words[i] = cur_cmd; 03443 } 03444 03445 for (i = 0; i < ARRAY_LEN(command_blacklist); i++) { 03446 int j, match = 1; 03447 03448 for (j = 0; command_blacklist[i].words[j]; j++) { 03449 if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) { 03450 match = 0; 03451 break; 03452 } 03453 } 03454 03455 if (match) { 03456 return 1; 03457 } 03458 } 03459 03460 return 0; 03461 }
int check_manager_enabled | ( | void | ) |
Check if AMI is enabled.
Definition at line 1037 of file manager.c.
Referenced by handle_show_settings().
01038 { 01039 return manager_enabled; 01040 }
static int check_manager_session_inuse | ( | const char * | name | ) | [static] |
Definition at line 1312 of file manager.c.
References ao2_find, mansession_session::inuse, and unref_mansession().
Referenced by process_message().
01313 { 01314 struct mansession_session *session = ao2_find(sessions, (char *) name, 0); 01315 int inuse = 0; 01316 01317 if (session) { 01318 inuse = 1; 01319 unref_mansession(session); 01320 } 01321 return inuse; 01322 }
int check_webmanager_enabled | ( | void | ) |
Check if AMI/HTTP is enabled.
Definition at line 1042 of file manager.c.
Referenced by action_coresettings(), and handle_show_settings().
01043 { 01044 return (webmanager_enabled && manager_enabled); 01045 }
static int do_message | ( | struct mansession * | s | ) | [static] |
Definition at line 4590 of file manager.c.
References AST_MAX_MANHEADERS, ast_strdupa, ast_strlen_zero(), get_input(), message::hdrcount, message::headers, mansession_session::inbuf, process_events(), process_message(), and mansession::session.
Referenced by session_do().
04591 { 04592 struct message m = { 0 }; 04593 char header_buf[sizeof(s->session->inbuf)] = { '\0' }; 04594 int res; 04595 04596 for (;;) { 04597 /* Check if any events are pending and do them if needed */ 04598 if (process_events(s)) { 04599 return -1; 04600 } 04601 res = get_input(s, header_buf); 04602 if (res == 0) { 04603 continue; 04604 } else if (res > 0) { 04605 if (ast_strlen_zero(header_buf)) { 04606 return process_message(s, &m) ? -1 : 0; 04607 } else if (m.hdrcount < (AST_MAX_MANHEADERS - 1)) { 04608 m.headers[m.hdrcount++] = ast_strdupa(header_buf); 04609 } 04610 } else { 04611 return res; 04612 } 04613 } 04614 }
static void event_filter_destructor | ( | void * | obj | ) | [static] |
static void* fast_originate | ( | void * | data | ) | [static] |
Definition at line 3537 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().
03538 { 03539 struct fast_originate_helper *in = data; 03540 int res; 03541 int reason = 0; 03542 struct ast_channel *chan = NULL, *chans[1]; 03543 char requested_channel[AST_CHANNEL_NAME]; 03544 03545 if (!ast_strlen_zero(in->app)) { 03546 res = ast_pbx_outgoing_app(in->tech, in->format, in->data, in->timeout, in->app, in->appdata, &reason, 1, 03547 S_OR(in->cid_num, NULL), 03548 S_OR(in->cid_name, NULL), 03549 in->vars, in->account, &chan); 03550 } else { 03551 res = ast_pbx_outgoing_exten(in->tech, in->format, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, 03552 S_OR(in->cid_num, NULL), 03553 S_OR(in->cid_name, NULL), 03554 in->vars, in->account, &chan); 03555 } 03556 03557 if (!chan) { 03558 snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data); 03559 } 03560 /* Tell the manager what happened with the channel */ 03561 chans[0] = chan; 03562 ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans, 03563 "%s%s" 03564 "Response: %s\r\n" 03565 "Channel: %s\r\n" 03566 "Context: %s\r\n" 03567 "Exten: %s\r\n" 03568 "Reason: %d\r\n" 03569 "Uniqueid: %s\r\n" 03570 "CallerIDNum: %s\r\n" 03571 "CallerIDName: %s\r\n", 03572 in->idtext, ast_strlen_zero(in->idtext) ? "" : "\r\n", res ? "Failure" : "Success", 03573 chan ? chan->name : requested_channel, in->context, in->exten, reason, 03574 chan ? chan->uniqueid : "<null>", 03575 S_OR(in->cid_num, "<unknown>"), 03576 S_OR(in->cid_name, "<unknown>") 03577 ); 03578 03579 /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */ 03580 if (chan) { 03581 ast_channel_unlock(chan); 03582 } 03583 ast_free(in); 03584 return NULL; 03585 }
static void free_channelvars | ( | void | ) | [static] |
Definition at line 6558 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().
06559 { 06560 struct manager_channel_variable *var; 06561 AST_RWLIST_WRLOCK(&channelvars); 06562 while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) { 06563 ast_free(var); 06564 } 06565 AST_RWLIST_UNLOCK(&channelvars); 06566 }
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 4518 of file manager.c.
References mansession_session::inbuf, mansession_session::inlen, mansession::session, and ast_frame::src.
04519 { 04520 int res, x; 04521 int maxlen = sizeof(s->session->inbuf) - 1; 04522 char *src = s->session->inbuf; 04523 04524 /* 04525 * Look for \r\n within the buffer. If found, copy to the output 04526 * buffer and return, trimming the \r\n (not used afterwards). 04527 */ 04528 for (x = 0; x < s->session->inlen; x++) { 04529 int cr; /* set if we have \r */ 04530 if (src[x] == '\r' && x+1 < s->session->inlen && src[x + 1] == '\n') { 04531 cr = 2; /* Found. Update length to include \r\n */ 04532 } else if (src[x] == '\n') { 04533 cr = 1; /* also accept \n only */ 04534 } else { 04535 continue; 04536 } 04537 memmove(output, src, x); /*... but trim \r\n */ 04538 output[x] = '\0'; /* terminate the string */ 04539 x += cr; /* number of bytes used */ 04540 s->session->inlen -= x; /* remaining size */ 04541 memmove(src, src + x, s->session->inlen); /* remove used bytes */ 04542 return 1; 04543 } 04544 if (s->session->inlen >= maxlen) { 04545 /* no crlf found, and buffer full - sorry, too long for us */ 04546 ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", ast_inet_ntoa(s->session->sin.sin_addr), src); 04547 s->session->inlen = 0; 04548 } 04549 res = 0; 04550 while (res == 0) { 04551 ao2_lock(s->session); 04552 if (s->session->pending_event) { 04553 s->session->pending_event = 0; 04554 ao2_unlock(s->session); 04555 return 0; 04556 } 04557 s->session->waiting_thread = pthread_self(); 04558 ao2_unlock(s->session); 04559 04560 res = ast_wait_for_input(s->session->fd, -1); /* return 0 on timeout ? */ 04561 04562 ao2_lock(s->session); 04563 s->session->waiting_thread = AST_PTHREADT_NULL; 04564 ao2_unlock(s->session); 04565 } 04566 if (res < 0) { 04567 /* If we get a signal from some other thread (typically because 04568 * there are new events queued), return 0 to notify the caller. 04569 */ 04570 if (errno == EINTR || errno == EAGAIN) { 04571 return 0; 04572 } 04573 ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno)); 04574 return -1; 04575 } 04576 04577 ao2_lock(s->session); 04578 res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f); 04579 if (res < 1) { 04580 res = -1; /* error return */ 04581 } else { 04582 s->session->inlen += res; 04583 src[s->session->inlen] = '\0'; 04584 res = 0; 04585 } 04586 ao2_unlock(s->session); 04587 return res; 04588 }
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 1329 of file manager.c.
References AST_RWLIST_TRAVERSE, ast_manager_user::list, and user.
Referenced by authenticate(), handle_showmanager(), and manager_displayconnects().
01330 { 01331 struct ast_manager_user *user = NULL; 01332 01333 AST_RWLIST_TRAVERSE(&users, user, list) { 01334 if (!strcasecmp(user->username, name)) { 01335 break; 01336 } 01337 } 01338 01339 return user; 01340 }
static int get_perm | ( | const char * | instr | ) | [static] |
Definition at line 1171 of file manager.c.
References ARRAY_LEN, ast_instring(), permalias::num, and perms.
Referenced by strings_to_mask().
01172 { 01173 int x = 0, ret = 0; 01174 01175 if (!instr) { 01176 return 0; 01177 } 01178 01179 for (x = 0; x < ARRAY_LEN(perms); x++) { 01180 if (ast_instring(instr, perms[x].label, ',')) { 01181 ret |= perms[x].num; 01182 } 01183 } 01184 01185 return ret; 01186 }
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 1051 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().
01052 { 01053 struct eventqent *ret; 01054 01055 AST_RWLIST_WRLOCK(&all_events); 01056 ret = AST_RWLIST_LAST(&all_events); 01057 /* the list is never empty now, but may become so when 01058 * we optimize it in the future, so be prepared. 01059 */ 01060 if (ret) { 01061 ast_atomic_fetchadd_int(&ret->usecount, 1); 01062 } 01063 AST_RWLIST_UNLOCK(&all_events); 01064 return ret; 01065 }
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 1663 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.
01664 { 01665 switch (cmd) { 01666 case CLI_INIT: 01667 e->command = "manager reload"; 01668 e->usage = 01669 "Usage: manager reload\n" 01670 " Reloads the manager configuration.\n"; 01671 return NULL; 01672 case CLI_GENERATE: 01673 return NULL; 01674 } 01675 if (a->argc > 2) { 01676 return CLI_SHOWUSAGE; 01677 } 01678 reload_manager(); 01679 return CLI_SUCCESS; 01680 }
static char* handle_mandebug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1438 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.
01439 { 01440 switch (cmd) { 01441 case CLI_INIT: 01442 e->command = "manager set debug [on|off]"; 01443 e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n"; 01444 return NULL; 01445 case CLI_GENERATE: 01446 return NULL; 01447 } 01448 01449 if (a->argc == 3) { 01450 ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off"); 01451 } else if (a->argc == 4) { 01452 if (!strcasecmp(a->argv[3], "on")) { 01453 manager_debug = 1; 01454 } else if (!strcasecmp(a->argv[3], "off")) { 01455 manager_debug = 0; 01456 } else { 01457 return CLI_SHOWUSAGE; 01458 } 01459 } 01460 return CLI_SUCCESS; 01461 }
static char* handle_showmanager | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1463 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.
01464 { 01465 struct ast_manager_user *user = NULL; 01466 int l, which; 01467 char *ret = NULL; 01468 struct ast_str *rauthority = ast_str_alloca(128); 01469 struct ast_str *wauthority = ast_str_alloca(128); 01470 01471 switch (cmd) { 01472 case CLI_INIT: 01473 e->command = "manager show user"; 01474 e->usage = 01475 " Usage: manager show user <user>\n" 01476 " Display all information related to the manager user specified.\n"; 01477 return NULL; 01478 case CLI_GENERATE: 01479 l = strlen(a->word); 01480 which = 0; 01481 if (a->pos != 3) { 01482 return NULL; 01483 } 01484 AST_RWLIST_RDLOCK(&users); 01485 AST_RWLIST_TRAVERSE(&users, user, list) { 01486 if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) { 01487 ret = ast_strdup(user->username); 01488 break; 01489 } 01490 } 01491 AST_RWLIST_UNLOCK(&users); 01492 return ret; 01493 } 01494 01495 if (a->argc != 4) { 01496 return CLI_SHOWUSAGE; 01497 } 01498 01499 AST_RWLIST_RDLOCK(&users); 01500 01501 if (!(user = get_manager_by_name_locked(a->argv[3]))) { 01502 ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]); 01503 AST_RWLIST_UNLOCK(&users); 01504 return CLI_SUCCESS; 01505 } 01506 01507 ast_cli(a->fd, "\n"); 01508 ast_cli(a->fd, 01509 " username: %s\n" 01510 " secret: %s\n" 01511 " acl: %s\n" 01512 " read perm: %s\n" 01513 " write perm: %s\n" 01514 "displayconnects: %s\n", 01515 (user->username ? user->username : "(N/A)"), 01516 (user->secret ? "<Set>" : "(N/A)"), 01517 (user->ha ? "yes" : "no"), 01518 authority_to_str(user->readperm, &rauthority), 01519 authority_to_str(user->writeperm, &wauthority), 01520 (user->displayconnects ? "yes" : "no")); 01521 01522 AST_RWLIST_UNLOCK(&users); 01523 01524 return CLI_SUCCESS; 01525 }
static char* handle_showmanagers | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1527 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.
01528 { 01529 struct ast_manager_user *user = NULL; 01530 int count_amu = 0; 01531 switch (cmd) { 01532 case CLI_INIT: 01533 e->command = "manager show users"; 01534 e->usage = 01535 "Usage: manager show users\n" 01536 " Prints a listing of all managers that are currently configured on that\n" 01537 " system.\n"; 01538 return NULL; 01539 case CLI_GENERATE: 01540 return NULL; 01541 } 01542 if (a->argc != 3) { 01543 return CLI_SHOWUSAGE; 01544 } 01545 01546 AST_RWLIST_RDLOCK(&users); 01547 01548 /* If there are no users, print out something along those lines */ 01549 if (AST_RWLIST_EMPTY(&users)) { 01550 ast_cli(a->fd, "There are no manager users.\n"); 01551 AST_RWLIST_UNLOCK(&users); 01552 return CLI_SUCCESS; 01553 } 01554 01555 ast_cli(a->fd, "\nusername\n--------\n"); 01556 01557 AST_RWLIST_TRAVERSE(&users, user, list) { 01558 ast_cli(a->fd, "%s\n", user->username); 01559 count_amu++; 01560 } 01561 01562 AST_RWLIST_UNLOCK(&users); 01563 01564 ast_cli(a->fd,"-------------------\n" 01565 "%d manager users configured.\n", count_amu); 01566 return CLI_SUCCESS; 01567 }
static char* handle_showmancmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1360 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.
01361 { 01362 struct manager_action *cur; 01363 struct ast_str *authority; 01364 int num, l, which; 01365 char *ret = NULL; 01366 #ifdef AST_XML_DOCS 01367 char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64]; 01368 #endif 01369 01370 switch (cmd) { 01371 case CLI_INIT: 01372 e->command = "manager show command"; 01373 e->usage = 01374 "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n" 01375 " Shows the detailed description for a specific Asterisk manager interface command.\n"; 01376 return NULL; 01377 case CLI_GENERATE: 01378 l = strlen(a->word); 01379 which = 0; 01380 AST_RWLIST_RDLOCK(&actions); 01381 AST_RWLIST_TRAVERSE(&actions, cur, list) { 01382 if (!strncasecmp(a->word, cur->action, l) && ++which > a->n) { 01383 ret = ast_strdup(cur->action); 01384 break; /* make sure we exit even if ast_strdup() returns NULL */ 01385 } 01386 } 01387 AST_RWLIST_UNLOCK(&actions); 01388 return ret; 01389 } 01390 authority = ast_str_alloca(80); 01391 if (a->argc < 4) { 01392 return CLI_SHOWUSAGE; 01393 } 01394 01395 #ifdef AST_XML_DOCS 01396 /* setup the titles */ 01397 term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01398 term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40); 01399 term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01400 term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40); 01401 term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 01402 #endif 01403 01404 AST_RWLIST_RDLOCK(&actions); 01405 AST_RWLIST_TRAVERSE(&actions, cur, list) { 01406 for (num = 3; num < a->argc; num++) { 01407 if (!strcasecmp(cur->action, a->argv[num])) { 01408 #ifdef AST_XML_DOCS 01409 if (cur->docsrc == AST_XML_DOC) { 01410 ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n", 01411 syntax_title, 01412 ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1), 01413 synopsis_title, 01414 ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1), 01415 description_title, 01416 ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1), 01417 arguments_title, 01418 ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1), 01419 seealso_title, 01420 ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1)); 01421 } else { 01422 #endif 01423 ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n", 01424 cur->action, cur->synopsis, 01425 authority_to_str(cur->authority, &authority), 01426 S_OR(cur->description, "")); 01427 #ifdef AST_XML_DOCS 01428 } 01429 #endif 01430 } 01431 } 01432 } 01433 AST_RWLIST_UNLOCK(&actions); 01434 01435 return CLI_SUCCESS; 01436 }
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 1570 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.
01571 { 01572 struct manager_action *cur; 01573 struct ast_str *authority; 01574 #define HSMC_FORMAT " %-15.15s %-15.15s %-55.55s\n" 01575 switch (cmd) { 01576 case CLI_INIT: 01577 e->command = "manager show commands"; 01578 e->usage = 01579 "Usage: manager show commands\n" 01580 " Prints a listing of all the available Asterisk manager interface commands.\n"; 01581 return NULL; 01582 case CLI_GENERATE: 01583 return NULL; 01584 } 01585 authority = ast_str_alloca(80); 01586 ast_cli(a->fd, HSMC_FORMAT, "Action", "Privilege", "Synopsis"); 01587 ast_cli(a->fd, HSMC_FORMAT, "------", "---------", "--------"); 01588 01589 AST_RWLIST_RDLOCK(&actions); 01590 AST_RWLIST_TRAVERSE(&actions, cur, list) 01591 ast_cli(a->fd, HSMC_FORMAT, cur->action, authority_to_str(cur->authority, &authority), cur->synopsis); 01592 AST_RWLIST_UNLOCK(&actions); 01593 01594 return CLI_SUCCESS; 01595 }
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 1598 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.
01599 { 01600 struct mansession_session *session; 01601 time_t now = time(NULL); 01602 #define HSMCONN_FORMAT1 " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n" 01603 #define HSMCONN_FORMAT2 " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n" 01604 int count = 0; 01605 struct ao2_iterator i; 01606 01607 switch (cmd) { 01608 case CLI_INIT: 01609 e->command = "manager show connected"; 01610 e->usage = 01611 "Usage: manager show connected\n" 01612 " Prints a listing of the users that are currently connected to the\n" 01613 "Asterisk manager interface.\n"; 01614 return NULL; 01615 case CLI_GENERATE: 01616 return NULL; 01617 } 01618 01619 ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write"); 01620 01621 i = ao2_iterator_init(sessions, 0); 01622 while ((session = ao2_iterator_next(&i))) { 01623 ao2_lock(session); 01624 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); 01625 count++; 01626 ao2_unlock(session); 01627 unref_mansession(session); 01628 } 01629 ao2_iterator_destroy(&i); 01630 ast_cli(a->fd, "%d users connected.\n", count); 01631 01632 return CLI_SUCCESS; 01633 }
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 1637 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.
01638 { 01639 struct eventqent *s; 01640 switch (cmd) { 01641 case CLI_INIT: 01642 e->command = "manager show eventq"; 01643 e->usage = 01644 "Usage: manager show eventq\n" 01645 " Prints a listing of all events pending in the Asterisk manger\n" 01646 "event queue.\n"; 01647 return NULL; 01648 case CLI_GENERATE: 01649 return NULL; 01650 } 01651 AST_RWLIST_RDLOCK(&all_events); 01652 AST_RWLIST_TRAVERSE(&all_events, s, eq_next) { 01653 ast_cli(a->fd, "Usecount: %d\n", s->usecount); 01654 ast_cli(a->fd, "Category: %d\n", s->category); 01655 ast_cli(a->fd, "Event:\n%s", s->eventdata); 01656 } 01657 AST_RWLIST_UNLOCK(&all_events); 01658 01659 return CLI_SUCCESS; 01660 }
static enum error_type handle_updates | ( | struct mansession * | s, | |
const struct message * | m, | |||
struct ast_config * | cfg, | |||
const char * | dfn | |||
) | [static] |
Definition at line 2516 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().
02517 { 02518 int x; 02519 char hdr[40]; 02520 const char *action, *cat, *var, *value, *match, *line; 02521 struct ast_category *category; 02522 struct ast_variable *v; 02523 struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16); 02524 enum error_type result = 0; 02525 02526 for (x = 0; x < 100000; x++) { /* 100000 = the max number of allowed updates + 1 */ 02527 unsigned int object = 0; 02528 02529 snprintf(hdr, sizeof(hdr), "Action-%06d", x); 02530 action = astman_get_header(m, hdr); 02531 if (ast_strlen_zero(action)) /* breaks the for loop if no action header */ 02532 break; /* this could cause problems if actions come in misnumbered */ 02533 02534 snprintf(hdr, sizeof(hdr), "Cat-%06d", x); 02535 cat = astman_get_header(m, hdr); 02536 if (ast_strlen_zero(cat)) { /* every action needs a category */ 02537 result = UNSPECIFIED_CATEGORY; 02538 break; 02539 } 02540 02541 snprintf(hdr, sizeof(hdr), "Var-%06d", x); 02542 var = astman_get_header(m, hdr); 02543 02544 snprintf(hdr, sizeof(hdr), "Value-%06d", x); 02545 value = astman_get_header(m, hdr); 02546 02547 if (!ast_strlen_zero(value) && *value == '>') { 02548 object = 1; 02549 value++; 02550 } 02551 02552 snprintf(hdr, sizeof(hdr), "Match-%06d", x); 02553 match = astman_get_header(m, hdr); 02554 02555 snprintf(hdr, sizeof(hdr), "Line-%06d", x); 02556 line = astman_get_header(m, hdr); 02557 02558 if (!strcasecmp(action, "newcat")) { 02559 if (ast_category_get(cfg,cat)) { /* check to make sure the cat doesn't */ 02560 result = FAILURE_NEWCAT; /* already exist */ 02561 break; 02562 } 02563 if (!(category = ast_category_new(cat, dfn, -1))) { 02564 result = FAILURE_ALLOCATION; 02565 break; 02566 } 02567 if (ast_strlen_zero(match)) { 02568 ast_category_append(cfg, category); 02569 } else { 02570 ast_category_insert(cfg, category, match); 02571 } 02572 } else if (!strcasecmp(action, "renamecat")) { 02573 if (ast_strlen_zero(value)) { 02574 result = UNSPECIFIED_ARGUMENT; 02575 break; 02576 } 02577 if (!(category = ast_category_get(cfg, cat))) { 02578 result = UNKNOWN_CATEGORY; 02579 break; 02580 } 02581 ast_category_rename(category, value); 02582 } else if (!strcasecmp(action, "delcat")) { 02583 if (ast_category_delete(cfg, cat)) { 02584 result = FAILURE_DELCAT; 02585 break; 02586 } 02587 } else if (!strcasecmp(action, "emptycat")) { 02588 if (ast_category_empty(cfg, cat)) { 02589 result = FAILURE_EMPTYCAT; 02590 break; 02591 } 02592 } else if (!strcasecmp(action, "update")) { 02593 if (ast_strlen_zero(var)) { 02594 result = UNSPECIFIED_ARGUMENT; 02595 break; 02596 } 02597 if (!(category = ast_category_get(cfg,cat))) { 02598 result = UNKNOWN_CATEGORY; 02599 break; 02600 } 02601 if (ast_variable_update(category, var, value, match, object)) { 02602 result = FAILURE_UPDATE; 02603 break; 02604 } 02605 } else if (!strcasecmp(action, "delete")) { 02606 if ((ast_strlen_zero(var) && ast_strlen_zero(line))) { 02607 result = UNSPECIFIED_ARGUMENT; 02608 break; 02609 } 02610 if (!(category = ast_category_get(cfg, cat))) { 02611 result = UNKNOWN_CATEGORY; 02612 break; 02613 } 02614 if (ast_variable_delete(category, var, match, line)) { 02615 result = FAILURE_DELETE; 02616 break; 02617 } 02618 } else if (!strcasecmp(action, "append")) { 02619 if (ast_strlen_zero(var)) { 02620 result = UNSPECIFIED_ARGUMENT; 02621 break; 02622 } 02623 if (!(category = ast_category_get(cfg, cat))) { 02624 result = UNKNOWN_CATEGORY; 02625 break; 02626 } 02627 if (!(v = ast_variable_new(var, value, dfn))) { 02628 result = FAILURE_ALLOCATION; 02629 break; 02630 } 02631 if (object || (match && !strcasecmp(match, "object"))) { 02632 v->object = 1; 02633 } 02634 ast_variable_append(category, v); 02635 } else if (!strcasecmp(action, "insert")) { 02636 if (ast_strlen_zero(var) || ast_strlen_zero(line)) { 02637 result = UNSPECIFIED_ARGUMENT; 02638 break; 02639 } 02640 if (!(category = ast_category_get(cfg, cat))) { 02641 result = UNKNOWN_CATEGORY; 02642 break; 02643 } 02644 if (!(v = ast_variable_new(var, value, dfn))) { 02645 result = FAILURE_ALLOCATION; 02646 break; 02647 } 02648 ast_variable_insert(category, v, line); 02649 } 02650 else { 02651 ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action); 02652 result = UNKNOWN_ACTION; 02653 break; 02654 } 02655 } 02656 ast_free(str1); 02657 ast_free(str2); 02658 return result; 02659 }
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 2435 of file manager.c.
Referenced by action_getconfigjson().
02436 { 02437 for (; *in; in++) { 02438 if (*in == '\\' || *in == '\"') { 02439 *out++ = '\\'; 02440 } 02441 *out++ = *in; 02442 } 02443 *out = '\0'; 02444 }
static int manager_displayconnects | ( | struct mansession_session * | session | ) | [static] |
Get displayconnects config option.
session | manager session to get parameter from. |
Definition at line 1346 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(), and purge_sessions().
01347 { 01348 struct ast_manager_user *user = NULL; 01349 int ret = 0; 01350 01351 AST_RWLIST_RDLOCK(&users); 01352 if ((user = get_manager_by_name_locked (session->username))) { 01353 ret = user->displayconnects; 01354 } 01355 AST_RWLIST_UNLOCK(&users); 01356 01357 return ret; 01358 }
static int manager_modulecheck | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4325 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().
04326 { 04327 int res; 04328 const char *module = astman_get_header(m, "Module"); 04329 const char *id = astman_get_header(m, "ActionID"); 04330 char idText[256]; 04331 #if !defined(LOW_MEMORY) 04332 const char *version; 04333 #endif 04334 char filename[PATH_MAX]; 04335 char *cut; 04336 04337 ast_copy_string(filename, module, sizeof(filename)); 04338 if ((cut = strchr(filename, '.'))) { 04339 *cut = '\0'; 04340 } else { 04341 cut = filename + strlen(filename); 04342 } 04343 snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".so"); 04344 ast_log(LOG_DEBUG, "**** ModuleCheck .so file %s\n", filename); 04345 res = ast_module_check(filename); 04346 if (!res) { 04347 astman_send_error(s, m, "Module not loaded"); 04348 return 0; 04349 } 04350 snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".c"); 04351 ast_log(LOG_DEBUG, "**** ModuleCheck .c file %s\n", filename); 04352 #if !defined(LOW_MEMORY) 04353 version = ast_file_version_find(filename); 04354 #endif 04355 04356 if (!ast_strlen_zero(id)) { 04357 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 04358 } else { 04359 idText[0] = '\0'; 04360 } 04361 astman_append(s, "Response: Success\r\n%s", idText); 04362 #if !defined(LOW_MEMORY) 04363 astman_append(s, "Version: %s\r\n\r\n", version ? version : ""); 04364 #endif 04365 return 0; 04366 }
static int manager_moduleload | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4368 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().
04369 { 04370 int res; 04371 const char *module = astman_get_header(m, "Module"); 04372 const char *loadtype = astman_get_header(m, "LoadType"); 04373 04374 if (!loadtype || strlen(loadtype) == 0) { 04375 astman_send_error(s, m, "Incomplete ModuleLoad action."); 04376 } 04377 if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0) { 04378 astman_send_error(s, m, "Need module name"); 04379 } 04380 04381 if (!strcasecmp(loadtype, "load")) { 04382 res = ast_load_resource(module); 04383 if (res) { 04384 astman_send_error(s, m, "Could not load module."); 04385 } else { 04386 astman_send_ack(s, m, "Module loaded."); 04387 } 04388 } else if (!strcasecmp(loadtype, "unload")) { 04389 res = ast_unload_resource(module, AST_FORCE_SOFT); 04390 if (res) { 04391 astman_send_error(s, m, "Could not unload module."); 04392 } else { 04393 astman_send_ack(s, m, "Module unloaded."); 04394 } 04395 } else if (!strcasecmp(loadtype, "reload")) { 04396 if (module != NULL) { 04397 res = ast_module_reload(module); 04398 if (res == 0) { 04399 astman_send_error(s, m, "No such module."); 04400 } else if (res == 1) { 04401 astman_send_error(s, m, "Module does not support reload action."); 04402 } else { 04403 astman_send_ack(s, m, "Module reloaded."); 04404 } 04405 } else { 04406 ast_module_reload(NULL); /* Reload all modules */ 04407 astman_send_ack(s, m, "All modules reloaded"); 04408 } 04409 } else 04410 astman_send_error(s, m, "Incomplete ModuleLoad action."); 04411 return 0; 04412 }
static int manager_state_cb | ( | char * | context, | |
char * | exten, | |||
int | state, | |||
void * | data | |||
) | [static] |
Definition at line 4896 of file manager.c.
References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.
Referenced by __init_manager().
04897 { 04898 /* Notify managers of change */ 04899 char hint[512]; 04900 ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten); 04901 04902 manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state); 04903 return 0; 04904 }
static int mansession_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1298 of file manager.c.
References CMP_MATCH, str, and mansession_session::username.
01299 { 01300 struct mansession_session *s = obj; 01301 char *str = arg; 01302 return !strcasecmp(s->username, str) ? CMP_MATCH : 0; 01303 }
static struct sockaddr_in* mansession_encode_sin_local | ( | const struct mansession * | s, | |
struct sockaddr_in * | sin_local | |||
) | [static] |
Definition at line 2002 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().
02004 { 02005 ast_sockaddr_to_sin(&s->tcptls_session->parent->local_address, 02006 sin_local); 02007 02008 return sin_local; 02009 }
static enum ast_security_event_transport_type mansession_get_transport | ( | const struct mansession * | s | ) | [static] |
Definition at line 1996 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().
01997 { 01998 return s->tcptls_session->parent->tls_cfg ? AST_SECURITY_EVENT_TRANSPORT_TLS : 01999 AST_SECURITY_EVENT_TRANSPORT_TCP; 02000 }
static void mansession_lock | ( | struct mansession * | s | ) | [static] |
Lock the 'mansession' structure.
Definition at line 1968 of file manager.c.
References ast_mutex_lock, and mansession::lock.
Referenced by action_challenge(), and process_message().
01969 { 01970 ast_mutex_lock(&s->lock); 01971 }
static void mansession_unlock | ( | struct mansession * | s | ) | [static] |
Unlock the 'mansession' structure.
Definition at line 1974 of file manager.c.
References ast_mutex_unlock, and mansession::lock.
Referenced by action_challenge(), and process_message().
01975 { 01976 ast_mutex_unlock(&s->lock); 01977 }
static int match_filter | ( | struct mansession * | s, | |
char * | eventdata | |||
) | [static] |
Definition at line 4077 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().
04078 { 04079 int result = 0; 04080 04081 ast_debug(3, "Examining event:\n%s\n", eventdata); 04082 if (!ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) { 04083 return 1; /* no filtering means match all */ 04084 } else if (ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) { 04085 /* white filters only: implied black all filter processed first, then white filters */ 04086 ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04087 } else if (!ao2_container_count(s->session->whitefilters) && ao2_container_count(s->session->blackfilters)) { 04088 /* black filters only: implied white all filter processed first, then black filters */ 04089 ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04090 } else { 04091 /* white and black filters: implied black all filter processed first, then white filters, and lastly black filters */ 04092 ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04093 if (result) { 04094 result = 0; 04095 ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04096 } 04097 } 04098 04099 return result; 04100 }
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 4107 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().
04108 { 04109 int ret = 0; 04110 04111 ao2_lock(s->session); 04112 if (s->session->f != NULL) { 04113 struct eventqent *eqe = s->session->last_ev; 04114 04115 while ((eqe = advance_event(eqe))) { 04116 if (!ret && s->session->authenticated && 04117 (s->session->readperm & eqe->category) == eqe->category && 04118 (s->session->send_events & eqe->category) == eqe->category) { 04119 if (match_filter(s, eqe->eventdata)) { 04120 if (send_string(s, eqe->eventdata) < 0) 04121 ret = -1; /* don't send more */ 04122 } 04123 } 04124 s->session->last_ev = eqe; 04125 } 04126 } 04127 ao2_unlock(s->session); 04128 return ret; 04129 }
static int process_message | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4427 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().
04428 { 04429 char action[80] = ""; 04430 int ret = 0; 04431 struct manager_action *tmp; 04432 const char *user = astman_get_header(m, "Username"); 04433 int (*call_func)(struct mansession *s, const struct message *m) = NULL; 04434 04435 ast_copy_string(action, __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY), sizeof(action)); 04436 04437 if (ast_strlen_zero(action)) { 04438 report_req_bad_format(s, "NONE"); 04439 mansession_lock(s); 04440 astman_send_error(s, m, "Missing action in request"); 04441 mansession_unlock(s); 04442 return 0; 04443 } 04444 04445 if (!s->session->authenticated && strcasecmp(action, "Login") && strcasecmp(action, "Logoff") && strcasecmp(action, "Challenge")) { 04446 if (!s->session->authenticated) { 04447 report_req_not_allowed(s, action); 04448 } 04449 mansession_lock(s); 04450 astman_send_error(s, m, "Permission denied"); 04451 mansession_unlock(s); 04452 return 0; 04453 } 04454 04455 if (!allowmultiplelogin && !s->session->authenticated && user && 04456 (!strcasecmp(action, "Login") || !strcasecmp(action, "Challenge"))) { 04457 if (check_manager_session_inuse(user)) { 04458 report_session_limit(s); 04459 sleep(1); 04460 mansession_lock(s); 04461 astman_send_error(s, m, "Login Already In Use"); 04462 mansession_unlock(s); 04463 return -1; 04464 } 04465 } 04466 04467 AST_RWLIST_RDLOCK(&actions); 04468 AST_RWLIST_TRAVERSE(&actions, tmp, list) { 04469 if (strcasecmp(action, tmp->action)) { 04470 continue; 04471 } 04472 if (s->session->writeperm & tmp->authority || tmp->authority == 0) { 04473 call_func = tmp->func; 04474 } else { 04475 astman_send_error(s, m, "Permission denied"); 04476 report_req_not_allowed(s, action); 04477 } 04478 break; 04479 } 04480 AST_RWLIST_UNLOCK(&actions); 04481 04482 if (tmp && call_func) { 04483 /* call AMI function after actions list are unlocked */ 04484 ast_debug(1, "Running action '%s'\n", tmp->action); 04485 ret = call_func(s, m); 04486 } else { 04487 char buf[512]; 04488 if (!tmp) { 04489 report_req_bad_format(s, action); 04490 } 04491 snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action); 04492 mansession_lock(s); 04493 astman_send_error(s, m, buf); 04494 mansession_unlock(s); 04495 } 04496 if (ret) { 04497 return ret; 04498 } 04499 /* Once done with our message, deliver any pending events unless the 04500 requester doesn't want them as part of this response. 04501 */ 04502 if (ast_strlen_zero(astman_get_header(m, "SuppressEvents"))) { 04503 return process_events(s); 04504 } else { 04505 return ret; 04506 } 04507 }
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 1071 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().
01072 { 01073 struct eventqent *ev; 01074 struct timeval now = ast_tvnow(); 01075 01076 AST_RWLIST_WRLOCK(&all_events); 01077 while ( (ev = AST_RWLIST_FIRST(&all_events)) && 01078 ev->usecount == 0 && AST_RWLIST_NEXT(ev, eq_next)) { 01079 AST_RWLIST_REMOVE_HEAD(&all_events, eq_next); 01080 ast_free(ev); 01081 } 01082 01083 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&all_events, ev, eq_next) { 01084 /* Never release the last event */ 01085 if (!AST_RWLIST_NEXT(ev, eq_next)) { 01086 break; 01087 } 01088 01089 /* 2.5 times whatever the HTTP timeout is (maximum 2.5 hours) is the maximum time that we will definitely cache an event */ 01090 if (ev->usecount == 0 && ast_tvdiff_sec(now, ev->tv) > (httptimeout > 3600 ? 3600 : httptimeout) * 2.5) { 01091 AST_RWLIST_REMOVE_CURRENT(eq_next); 01092 ast_free(ev); 01093 } 01094 } 01095 AST_RWLIST_TRAVERSE_SAFE_END; 01096 AST_RWLIST_UNLOCK(&all_events); 01097 }
static void purge_sessions | ( | int | n_max | ) | [static] |
remove at most n_max stale session from the list.
Definition at line 4706 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().
04707 { 04708 struct mansession_session *session; 04709 time_t now = time(NULL); 04710 struct ao2_iterator i; 04711 04712 i = ao2_iterator_init(sessions, 0); 04713 while ((session = ao2_iterator_next(&i)) && n_max > 0) { 04714 ao2_lock(session); 04715 if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) { 04716 if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) { 04717 ast_verb(2, "HTTP Manager '%s' timed out from %s\n", 04718 session->username, ast_inet_ntoa(session->sin.sin_addr)); 04719 } 04720 ao2_unlock(session); 04721 session_destroy(session); 04722 n_max--; 04723 } else { 04724 ao2_unlock(session); 04725 unref_mansession(session); 04726 } 04727 } 04728 ao2_iterator_destroy(&i); 04729 }
static void report_auth_success | ( | const struct mansession * | s | ) | [static] |
Definition at line 2089 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().
02090 { 02091 struct sockaddr_in sin_local; 02092 char session_id[32]; 02093 struct ast_security_event_successful_auth successful_auth = { 02094 .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH, 02095 .common.version = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION, 02096 .common.service = "AMI", 02097 .common.account_id = s->session->username, 02098 .common.session_tv = &s->session->sessionstart_tv, 02099 .common.local_addr = { 02100 .sin = mansession_encode_sin_local(s, &sin_local), 02101 .transport = mansession_get_transport(s), 02102 }, 02103 .common.remote_addr = { 02104 .sin = &s->session->sin, 02105 .transport = mansession_get_transport(s), 02106 }, 02107 .common.session_id = session_id, 02108 }; 02109 02110 snprintf(session_id, sizeof(session_id), "%p", s->session); 02111 02112 ast_security_event_report(AST_SEC_EVT(&successful_auth)); 02113 }
static void report_failed_acl | ( | const struct mansession * | s, | |
const char * | username | |||
) | [static] |
Definition at line 2037 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().
02038 { 02039 struct sockaddr_in sin_local; 02040 char session_id[32]; 02041 struct ast_security_event_failed_acl failed_acl_event = { 02042 .common.event_type = AST_SECURITY_EVENT_FAILED_ACL, 02043 .common.version = AST_SECURITY_EVENT_FAILED_ACL_VERSION, 02044 .common.service = "AMI", 02045 .common.account_id = username, 02046 .common.session_tv = &s->session->sessionstart_tv, 02047 .common.local_addr = { 02048 .sin = mansession_encode_sin_local(s, &sin_local), 02049 .transport = mansession_get_transport(s), 02050 }, 02051 .common.remote_addr = { 02052 .sin = &s->session->sin, 02053 .transport = mansession_get_transport(s), 02054 }, 02055 .common.session_id = session_id, 02056 }; 02057 02058 snprintf(session_id, sizeof(session_id), "%p", s->session); 02059 02060 ast_security_event_report(AST_SEC_EVT(&failed_acl_event)); 02061 }
static void report_failed_challenge_response | ( | const struct mansession * | s, | |
const char * | response, | |||
const char * | expected_response | |||
) | [static] |
Definition at line 2175 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().
02177 { 02178 struct sockaddr_in sin_local; 02179 char session_id[32]; 02180 struct ast_security_event_chal_resp_failed chal_resp_failed = { 02181 .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED, 02182 .common.version = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION, 02183 .common.service = "AMI", 02184 .common.account_id = s->session->username, 02185 .common.session_tv = &s->session->sessionstart_tv, 02186 .common.local_addr = { 02187 .sin = mansession_encode_sin_local(s, &sin_local), 02188 .transport = mansession_get_transport(s), 02189 }, 02190 .common.remote_addr = { 02191 .sin = &s->session->sin, 02192 .transport = mansession_get_transport(s), 02193 }, 02194 .common.session_id = session_id, 02195 02196 .challenge = s->session->challenge, 02197 .response = response, 02198 .expected_response = expected_response, 02199 }; 02200 02201 snprintf(session_id, sizeof(session_id), "%p", s->session); 02202 02203 ast_security_event_report(AST_SEC_EVT(&chal_resp_failed)); 02204 }
static void report_inval_password | ( | const struct mansession * | s, | |
const char * | username | |||
) | [static] |
Definition at line 2063 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().
02064 { 02065 struct sockaddr_in sin_local; 02066 char session_id[32]; 02067 struct ast_security_event_inval_password inval_password = { 02068 .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD, 02069 .common.version = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION, 02070 .common.service = "AMI", 02071 .common.account_id = username, 02072 .common.session_tv = &s->session->sessionstart_tv, 02073 .common.local_addr = { 02074 .sin = mansession_encode_sin_local(s, &sin_local), 02075 .transport = mansession_get_transport(s), 02076 }, 02077 .common.remote_addr = { 02078 .sin = &s->session->sin, 02079 .transport = mansession_get_transport(s), 02080 }, 02081 .common.session_id = session_id, 02082 }; 02083 02084 snprintf(session_id, sizeof(session_id), "%p", s->session); 02085 02086 ast_security_event_report(AST_SEC_EVT(&inval_password)); 02087 }
static void report_invalid_user | ( | const struct mansession * | s, | |
const char * | username | |||
) | [static] |
Definition at line 2011 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().
02012 { 02013 struct sockaddr_in sin_local; 02014 char session_id[32]; 02015 struct ast_security_event_inval_acct_id inval_acct_id = { 02016 .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID, 02017 .common.version = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION, 02018 .common.service = "AMI", 02019 .common.account_id = username, 02020 .common.session_tv = &s->session->sessionstart_tv, 02021 .common.local_addr = { 02022 .sin = mansession_encode_sin_local(s, &sin_local), 02023 .transport = mansession_get_transport(s), 02024 }, 02025 .common.remote_addr = { 02026 .sin = &s->session->sin, 02027 .transport = mansession_get_transport(s), 02028 }, 02029 .common.session_id = session_id, 02030 }; 02031 02032 snprintf(session_id, sizeof(session_id), "%p", s); 02033 02034 ast_security_event_report(AST_SEC_EVT(&inval_acct_id)); 02035 }
static void report_req_bad_format | ( | const struct mansession * | s, | |
const char * | action | |||
) | [static] |
Definition at line 2145 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().
02146 { 02147 struct sockaddr_in sin_local; 02148 char session_id[32]; 02149 char request_type[64]; 02150 struct ast_security_event_req_bad_format req_bad_format = { 02151 .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT, 02152 .common.version = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION, 02153 .common.service = "AMI", 02154 .common.account_id = s->session->username, 02155 .common.session_tv = &s->session->sessionstart_tv, 02156 .common.local_addr = { 02157 .sin = mansession_encode_sin_local(s, &sin_local), 02158 .transport = mansession_get_transport(s), 02159 }, 02160 .common.remote_addr = { 02161 .sin = &s->session->sin, 02162 .transport = mansession_get_transport(s), 02163 }, 02164 .common.session_id = session_id, 02165 02166 .request_type = request_type, 02167 }; 02168 02169 snprintf(session_id, sizeof(session_id), "%p", s->session); 02170 snprintf(request_type, sizeof(request_type), "Action: %s", action); 02171 02172 ast_security_event_report(AST_SEC_EVT(&req_bad_format)); 02173 }
static void report_req_not_allowed | ( | const struct mansession * | s, | |
const char * | action | |||
) | [static] |
Definition at line 2115 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().
02116 { 02117 struct sockaddr_in sin_local; 02118 char session_id[32]; 02119 char request_type[64]; 02120 struct ast_security_event_req_not_allowed req_not_allowed = { 02121 .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED, 02122 .common.version = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION, 02123 .common.service = "AMI", 02124 .common.account_id = s->session->username, 02125 .common.session_tv = &s->session->sessionstart_tv, 02126 .common.local_addr = { 02127 .sin = mansession_encode_sin_local(s, &sin_local), 02128 .transport = mansession_get_transport(s), 02129 }, 02130 .common.remote_addr = { 02131 .sin = &s->session->sin, 02132 .transport = mansession_get_transport(s), 02133 }, 02134 .common.session_id = session_id, 02135 02136 .request_type = request_type, 02137 }; 02138 02139 snprintf(session_id, sizeof(session_id), "%p", s->session); 02140 snprintf(request_type, sizeof(request_type), "Action: %s", action); 02141 02142 ast_security_event_report(AST_SEC_EVT(&req_not_allowed)); 02143 }
static void report_session_limit | ( | const struct mansession * | s | ) | [static] |
Definition at line 2206 of file manager.c.
References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_SESSION_LIMIT, AST_SECURITY_EVENT_SESSION_LIMIT_VERSION, ast_security_event_session_limit::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().
02207 { 02208 struct sockaddr_in sin_local; 02209 char session_id[32]; 02210 struct ast_security_event_session_limit session_limit = { 02211 .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT, 02212 .common.version = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION, 02213 .common.service = "AMI", 02214 .common.account_id = s->session->username, 02215 .common.session_tv = &s->session->sessionstart_tv, 02216 .common.local_addr = { 02217 .sin = mansession_encode_sin_local(s, &sin_local), 02218 .transport = mansession_get_transport(s), 02219 }, 02220 .common.remote_addr = { 02221 .sin = &s->session->sin, 02222 .transport = mansession_get_transport(s), 02223 }, 02224 .common.session_id = session_id, 02225 }; 02226 02227 snprintf(session_id, sizeof(session_id), "%p", s->session); 02228 02229 ast_security_event_report(AST_SEC_EVT(&session_limit)); 02230 }
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 1846 of file manager.c.
References ast_careful_fwrite(), EVENT_FLAG_HOOKRESPONSE, mansession_session::f, mansession::f, f, mansession_session::fd, mansession::fd, manager_custom_hook::helper, mansession::hook, mansession::session, mansession::write_error, and mansession_session::writetimeout.
Referenced by astman_append(), and process_events().
01847 { 01848 int res; 01849 FILE *f = s->f ? s->f : s->session->f; 01850 int fd = s->f ? s->fd : s->session->fd; 01851 01852 /* It's a result from one of the hook's action invocation */ 01853 if (s->hook) { 01854 /* 01855 * to send responses, we're using the same function 01856 * as for receiving events. We call the event "HookResponse" 01857 */ 01858 s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string); 01859 return 0; 01860 } 01861 01862 if ((res = ast_careful_fwrite(f, fd, string, strlen(string), s->session->writetimeout))) { 01863 s->write_error = 1; 01864 } 01865 01866 return res; 01867 }
static void session_destroy | ( | struct mansession_session * | s | ) | [static] |
Definition at line 1305 of file manager.c.
References ao2_unlink, and unref_mansession().
Referenced by purge_sessions(), and spandsp_fax_destroy().
01306 { 01307 unref_mansession(s); 01308 ao2_unlink(sessions, s); 01309 }
static void session_destructor | ( | void * | obj | ) | [static] |
Definition at line 1238 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().
01239 { 01240 struct mansession_session *session = obj; 01241 struct eventqent *eqe = session->last_ev; 01242 struct ast_datastore *datastore; 01243 01244 /* Get rid of each of the data stores on the session */ 01245 while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) { 01246 /* Free the data store */ 01247 ast_datastore_free(datastore); 01248 } 01249 01250 if (session->f != NULL) { 01251 fclose(session->f); 01252 } 01253 if (eqe) { 01254 ast_atomic_fetchadd_int(&eqe->usecount, -1); 01255 } 01256 01257 if (session->whitefilters) { 01258 ao2_t_callback(session->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters"); 01259 ao2_t_ref(session->whitefilters, -1 , "decrement ref for white container, should be last one"); 01260 } 01261 01262 if (session->blackfilters) { 01263 ao2_t_callback(session->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters"); 01264 ao2_t_ref(session->blackfilters, -1 , "decrement ref for black container, should be last one"); 01265 } 01266 }
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 4624 of file manager.c.
References AMI_VERSION, ao2_lock, ao2_unlock, AST_LIST_HEAD_INIT_NOLOCK, ast_log(), ast_mutex_init, ast_sockaddr_to_sin, astman_append(), block_sockets, build_mansession(), mansession_session::datastores, do_message(), errno, ast_tcptls_session_instance::f, mansession::f, mansession_session::f, mansession::fd, mansession_session::fd, ast_tcptls_session_instance::fd, ast_frame::flags, grab_last(), mansession_session::last_ev, mansession::lock, LOG_WARNING, ast_tcptls_session_instance::remote_address, mansession::session, mansession_session::sin, mansession::tcptls_session, and mansession::write_error.
04625 { 04626 struct ast_tcptls_session_instance *ser = data; 04627 struct mansession_session *session; 04628 struct mansession s = { 04629 .tcptls_session = data, 04630 }; 04631 int flags; 04632 int res; 04633 struct sockaddr_in ser_remote_address_tmp; 04634 struct protoent *p; 04635 04636 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 04637 session = build_mansession(ser_remote_address_tmp); 04638 04639 if (session == NULL) { 04640 goto done; 04641 } 04642 04643 /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm. 04644 * This is necessary to prevent delays (caused by buffering) as we 04645 * write to the socket in bits and peices. */ 04646 p = getprotobyname("tcp"); 04647 if (p) { 04648 int arg = 1; 04649 if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) { 04650 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)); 04651 } 04652 } else { 04653 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"); 04654 } 04655 04656 flags = fcntl(ser->fd, F_GETFL); 04657 if (!block_sockets) { /* make sure socket is non-blocking */ 04658 flags |= O_NONBLOCK; 04659 } else { 04660 flags &= ~O_NONBLOCK; 04661 } 04662 fcntl(ser->fd, F_SETFL, flags); 04663 04664 ao2_lock(session); 04665 /* Hook to the tail of the event queue */ 04666 session->last_ev = grab_last(); 04667 04668 ast_mutex_init(&s.lock); 04669 04670 /* these fields duplicate those in the 'ser' structure */ 04671 session->fd = s.fd = ser->fd; 04672 session->f = s.f = ser->f; 04673 session->sin = ser_remote_address_tmp; 04674 s.session = session; 04675 04676 AST_LIST_HEAD_INIT_NOLOCK(&session->datastores); 04677 04678 ao2_unlock(session); 04679 astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */ 04680 for (;;) { 04681 if ((res = do_message(&s)) < 0 || s.write_error) { 04682 break; 04683 } 04684 } 04685 /* session is over, explain why and terminate */ 04686 if (session->authenticated) { 04687 if (manager_displayconnects(session)) { 04688 ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 04689 } 04690 } else { 04691 if (displayconnects) { 04692 ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr)); 04693 } 04694 } 04695 04696 session_destroy(session); 04697 04698 ast_mutex_destroy(&s.lock); 04699 done: 04700 ao2_ref(ser, -1); 04701 ser = NULL; 04702 return NULL; 04703 }
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 1983 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().
01984 { 01985 int maskint = strings_to_mask(eventmask); 01986 01987 ao2_lock(s->session); 01988 if (maskint >= 0) { 01989 s->session->send_events = maskint; 01990 } 01991 ao2_unlock(s->session); 01992 01993 return maskint; 01994 }
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 1192 of file manager.c.
References ARRAY_LEN, ast_false(), ast_strlen_zero(), ast_true(), get_perm(), and perms.
Referenced by set_eventmask().
01193 { 01194 const char *p; 01195 01196 if (ast_strlen_zero(string)) { 01197 return -1; 01198 } 01199 01200 for (p = string; *p; p++) { 01201 if (*p < '0' || *p > '9') { 01202 break; 01203 } 01204 } 01205 if (!*p) { /* all digits */ 01206 return atoi(string); 01207 } 01208 if (ast_false(string)) { 01209 return 0; 01210 } 01211 if (ast_true(string)) { /* all permissions */ 01212 int x, ret = 0; 01213 for (x = 0; x < ARRAY_LEN(perms); x++) { 01214 ret |= perms[x].num; 01215 } 01216 return ret; 01217 } 01218 return get_perm(string); 01219 }
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 1223 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().
01224 { 01225 int refcount = ao2_ref(s, -1); 01226 if (manager_debug) { 01227 ast_log(LOG_DEBUG, "Mansession: %p refcount now %d\n", s, refcount - 1); 01228 } 01229 return s; 01230 }
static int whitefilter_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 4049 of file manager.c.
References CMP_MATCH, and CMP_STOP.
Referenced by match_filter().
04050 { 04051 regex_t *regex_filter = obj; 04052 const char *eventdata = arg; 04053 int *result = data; 04054 04055 if (!regexec(regex_filter, eventdata, 0, NULL, 0)) { 04056 *result = 1; 04057 return (CMP_MATCH | CMP_STOP); 04058 } 04059 04060 return 0; 04061 }
int allowmultiplelogin = 1 [static] |
Definition at line 865 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 block_sockets [static] |
Definition at line 876 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_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 864 of file manager.c.
Referenced by __init_manager(), and handle_manager_show_settings().
char global_realm[MAXHOSTNAMELEN] [static] |
int httptimeout [static] |
Definition at line 867 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 878 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 869 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 866 of file manager.c.
Referenced by __ast_manager_event_multichan(), __init_manager(), and handle_manager_show_settings().
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 870 of file manager.c.
Referenced by __init_manager(), and handle_manager_show_settings().