callback to display queues status in manager More...
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 } |
enum | mansession_message_parsing { MESSAGE_OKAY, MESSAGE_LINE_TOO_LONG } |
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) |
Return a matching header value. | |
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 void | action_destroy (void *obj) |
static int | action_events (struct mansession *s, const struct message *m) |
static int | action_extensionstate (struct mansession *s, const struct message *m) |
static struct manager_action * | action_find (const char *name) |
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 new command with manager, including online help. This is the preferred way to register a manager command | |
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,...) |
static void | astman_append_json (struct mansession *s, const char *str) |
const char * | astman_get_header (const struct message *m, char *var) |
Return the first matching variable from an array. | |
struct 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. Note that the EVENT_FLAG_ALL authority will always be returned. | |
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 (void) |
Check if AMI is enabled. | |
static int | check_manager_session_inuse (const char *name) |
int | check_webmanager_enabled (void) |
Check if AMI/HTTP is enabled. | |
static void | destroy_fast_originate_helper (struct fast_originate_helper *doomed) |
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 | function_capable_string_allowed_with_auths (const char *evaluating, int writepermlist) |
Checks to see if a string which can be used to evaluate functions should be rejected. | |
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 void | handle_parse_error (struct mansession *s, struct message *m, char *error) |
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 struct ast_variable * | man_do_variable_value (struct ast_variable *head, const char *hdr_val) |
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 const char * | user_authority_to_str (int authority, struct ast_str **res) |
Convert authority code to a list of options for a user. This will only display those authority codes that have an explicit match on authority. | |
static int | whitefilter_cmp_fn (void *obj, void *arg, void *data, int flags) |
Variables | |
static int | allowmultiplelogin = 1 |
static struct ast_threadstorage | astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , } |
static int | authlimit |
static int | authtimeout |
static int | block_sockets |
static int | broken_events_action |
struct { | |
const char * words [AST_MAX_CMD_LEN] | |
} | command_blacklist [] |
static const int | DEFAULT_AUTHLIMIT = 50 |
static const int | DEFAULT_AUTHTIMEOUT = 30 |
static const int | DEFAULT_BLOCKSOCKETS = 0 |
static const int | DEFAULT_BROKENEVENTSACTION = 0 |
static const int | DEFAULT_DISPLAYCONNECTS = 1 |
static const int | DEFAULT_ENABLED = 0 |
static const int | DEFAULT_HTTPTIMEOUT = 60 |
static const int | DEFAULT_MANAGERDEBUG = 0 |
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 = 0 |
static int | manager_enabled = 0 |
static struct ast_threadstorage | manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , } |
static struct ast_threadstorage | manager_event_funcbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_funcbuf , .custom_init = NULL , } |
static struct permalias | perms [] |
static struct ao2_container * | sessions = NULL |
static int | timestampevents |
static int | unauth_sessions = 0 |
static struct ast_threadstorage | userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , } |
static int | webmanager_enabled = 0 |
callback to display queues status in manager
#define ASTMAN_APPEND_BUF_INITSIZE 256 |
initial allocated size for the astman_append_buf
Definition at line 2047 of file manager.c.
Referenced by astman_append().
#define DEFAULT_REALM "asterisk" |
Definition at line 910 of file manager.c.
Referenced by __init_manager(), and reload_config().
#define GET_HEADER_FIRST_MATCH 0 |
Definition at line 1800 of file manager.c.
Referenced by astman_get_header().
#define GET_HEADER_LAST_MATCH 1 |
Definition at line 1801 of file manager.c.
Referenced by __astman_get_header().
#define GET_HEADER_SKIP_EMPTY 2 |
Definition at line 1802 of file manager.c.
Referenced by __astman_get_header(), and process_message().
#define MANAGER_EVENT_BUF_INITSIZE 256 |
Definition at line 5235 of file manager.c.
Referenced by __ast_manager_event_multichan().
#define MAX_BLACKLIST_CMD_LEN 2 |
Descriptor for a manager session, either on the AMI socket or over HTTP.
Definition at line 927 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 2088 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 842 of file manager.c.
00842 { 00843 UNKNOWN_ACTION = 1, 00844 UNKNOWN_CATEGORY, 00845 UNSPECIFIED_CATEGORY, 00846 UNSPECIFIED_ARGUMENT, 00847 FAILURE_ALLOCATION, 00848 FAILURE_NEWCAT, 00849 FAILURE_DELCAT, 00850 FAILURE_EMPTYCAT, 00851 FAILURE_UPDATE, 00852 FAILURE_DELETE, 00853 FAILURE_APPEND 00854 };
Definition at line 1002 of file manager.c.
01002 { 01003 MESSAGE_OKAY, 01004 MESSAGE_LINE_TOO_LONG 01005 };
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 5237 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_event_buf, MANAGER_EVENT_BUF_INITSIZE, mansession_session::pending_event, eventqent::seq, sessions, unref_mansession(), and mansession_session::waiting_thread.
05239 { 05240 struct mansession_session *session; 05241 struct manager_custom_hook *hook; 05242 struct ast_str *auth = ast_str_alloca(80); 05243 const char *cat_str; 05244 va_list ap; 05245 struct timeval now; 05246 struct ast_str *buf; 05247 int i; 05248 05249 if (!(sessions && ao2_container_count(sessions)) && AST_RWLIST_EMPTY(&manager_hooks)) { 05250 return 0; 05251 } 05252 05253 if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) { 05254 return -1; 05255 } 05256 05257 cat_str = authority_to_str(category, &auth); 05258 ast_str_set(&buf, 0, 05259 "Event: %s\r\nPrivilege: %s\r\n", 05260 event, cat_str); 05261 05262 if (timestampevents) { 05263 now = ast_tvnow(); 05264 ast_str_append(&buf, 0, 05265 "Timestamp: %ld.%06lu\r\n", 05266 (long)now.tv_sec, (unsigned long) now.tv_usec); 05267 } 05268 if (manager_debug) { 05269 static int seq; 05270 ast_str_append(&buf, 0, 05271 "SequenceNumber: %d\r\n", 05272 ast_atomic_fetchadd_int(&seq, 1)); 05273 ast_str_append(&buf, 0, 05274 "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func); 05275 } 05276 05277 va_start(ap, fmt); 05278 ast_str_append_va(&buf, 0, fmt, ap); 05279 va_end(ap); 05280 for (i = 0; i < chancount; i++) { 05281 append_channel_vars(&buf, chans[i]); 05282 } 05283 05284 ast_str_append(&buf, 0, "\r\n"); 05285 05286 append_event(ast_str_buffer(buf), category); 05287 05288 /* Wake up any sleeping sessions */ 05289 if (sessions) { 05290 struct ao2_iterator i; 05291 i = ao2_iterator_init(sessions, 0); 05292 while ((session = ao2_iterator_next(&i))) { 05293 ao2_lock(session); 05294 if (session->waiting_thread != AST_PTHREADT_NULL) { 05295 pthread_kill(session->waiting_thread, SIGURG); 05296 } else { 05297 /* We have an event to process, but the mansession is 05298 * not waiting for it. We still need to indicate that there 05299 * is an event waiting so that get_input processes the pending 05300 * event instead of polling. 05301 */ 05302 session->pending_event = 1; 05303 } 05304 ao2_unlock(session); 05305 unref_mansession(session); 05306 } 05307 ao2_iterator_destroy(&i); 05308 } 05309 05310 if (!AST_RWLIST_EMPTY(&manager_hooks)) { 05311 AST_RWLIST_RDLOCK(&manager_hooks); 05312 AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) { 05313 hook->helper(category, event, ast_str_buffer(buf)); 05314 } 05315 AST_RWLIST_UNLOCK(&manager_hooks); 05316 } 05317 05318 return 0; 05319 }
static const char* __astman_get_header | ( | const struct message * | m, | |
char * | var, | |||
int | mode | |||
) | [static] |
Return a matching header value.
Generic function to return either the first or the last matching header from a list of variables, possibly skipping empty strings.
Definition at line 1817 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().
01818 { 01819 int x, l = strlen(var); 01820 const char *result = ""; 01821 01822 if (!m) { 01823 return result; 01824 } 01825 01826 for (x = 0; x < m->hdrcount; x++) { 01827 const char *h = m->headers[x]; 01828 if (!strncasecmp(var, h, l) && h[l] == ':') { 01829 const char *value = h + l + 1; 01830 value = ast_skip_blanks(value); /* ignore leading spaces in the value */ 01831 /* found a potential candidate */ 01832 if ((mode & GET_HEADER_SKIP_EMPTY) && ast_strlen_zero(value)) { 01833 continue; /* not interesting */ 01834 } 01835 if (mode & GET_HEADER_LAST_MATCH) { 01836 result = value; /* record the last match so far */ 01837 } else { 01838 return value; 01839 } 01840 } 01841 } 01842 01843 return result; 01844 }
static void __init_astman_append_buf | ( | void | ) | [static] |
thread local buffer for astman_append
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 3897 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().
03898 { 03899 const char *channel = astman_get_header(m, "Channel"); 03900 const char *pchannel = astman_get_header(m, "ChannelPrefix"); 03901 const char *msgtype = astman_get_header(m, "MsgType"); 03902 const char *chargetype = astman_get_header(m, "ChargeType"); 03903 const char *currencyname = astman_get_header(m, "CurrencyName"); 03904 const char *currencyamount = astman_get_header(m, "CurrencyAmount"); 03905 const char *mult = astman_get_header(m, "CurrencyMultiplier"); 03906 const char *totaltype = astman_get_header(m, "TotalType"); 03907 const char *aocbillingid = astman_get_header(m, "AOCBillingId"); 03908 const char *association_id= astman_get_header(m, "ChargingAssociationId"); 03909 const char *association_num = astman_get_header(m, "ChargingAssociationNumber"); 03910 const char *association_plan = astman_get_header(m, "ChargingAssociationPlan"); 03911 03912 enum ast_aoc_type _msgtype; 03913 enum ast_aoc_charge_type _chargetype; 03914 enum ast_aoc_currency_multiplier _mult = AST_AOC_MULT_ONE; 03915 enum ast_aoc_total_type _totaltype = AST_AOC_TOTAL; 03916 enum ast_aoc_billing_id _billingid = AST_AOC_BILLING_NA; 03917 unsigned int _currencyamount = 0; 03918 int _association_id = 0; 03919 unsigned int _association_plan = 0; 03920 struct ast_channel *chan = NULL; 03921 03922 struct ast_aoc_decoded *decoded = NULL; 03923 struct ast_aoc_encoded *encoded = NULL; 03924 size_t encoded_size = 0; 03925 03926 if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) { 03927 astman_send_error(s, m, "Channel and PartialChannel are not specified. Specify at least one of these."); 03928 goto aocmessage_cleanup; 03929 } 03930 03931 if (!(chan = ast_channel_get_by_name(channel)) && !ast_strlen_zero(pchannel)) { 03932 chan = ast_channel_get_by_name_prefix(pchannel, strlen(pchannel)); 03933 } 03934 03935 if (!chan) { 03936 astman_send_error(s, m, "No such channel"); 03937 goto aocmessage_cleanup; 03938 } 03939 03940 if (ast_strlen_zero(msgtype) || (strcasecmp(msgtype, "d") && strcasecmp(msgtype, "e"))) { 03941 astman_send_error(s, m, "Invalid MsgType"); 03942 goto aocmessage_cleanup; 03943 } 03944 03945 if (ast_strlen_zero(chargetype)) { 03946 astman_send_error(s, m, "ChargeType not specified"); 03947 goto aocmessage_cleanup; 03948 } 03949 03950 _msgtype = strcasecmp(msgtype, "d") ? AST_AOC_E : AST_AOC_D; 03951 03952 if (!strcasecmp(chargetype, "NA")) { 03953 _chargetype = AST_AOC_CHARGE_NA; 03954 } else if (!strcasecmp(chargetype, "Free")) { 03955 _chargetype = AST_AOC_CHARGE_FREE; 03956 } else if (!strcasecmp(chargetype, "Currency")) { 03957 _chargetype = AST_AOC_CHARGE_CURRENCY; 03958 } else if (!strcasecmp(chargetype, "Unit")) { 03959 _chargetype = AST_AOC_CHARGE_UNIT; 03960 } else { 03961 astman_send_error(s, m, "Invalid ChargeType"); 03962 goto aocmessage_cleanup; 03963 } 03964 03965 if (_chargetype == AST_AOC_CHARGE_CURRENCY) { 03966 03967 if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u", &_currencyamount) != 1)) { 03968 astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency"); 03969 goto aocmessage_cleanup; 03970 } 03971 03972 if (ast_strlen_zero(mult)) { 03973 astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency."); 03974 goto aocmessage_cleanup; 03975 } else if (!strcasecmp(mult, "onethousandth")) { 03976 _mult = AST_AOC_MULT_ONETHOUSANDTH; 03977 } else if (!strcasecmp(mult, "onehundredth")) { 03978 _mult = AST_AOC_MULT_ONEHUNDREDTH; 03979 } else if (!strcasecmp(mult, "onetenth")) { 03980 _mult = AST_AOC_MULT_ONETENTH; 03981 } else if (!strcasecmp(mult, "one")) { 03982 _mult = AST_AOC_MULT_ONE; 03983 } else if (!strcasecmp(mult, "ten")) { 03984 _mult = AST_AOC_MULT_TEN; 03985 } else if (!strcasecmp(mult, "hundred")) { 03986 _mult = AST_AOC_MULT_HUNDRED; 03987 } else if (!strcasecmp(mult, "thousand")) { 03988 _mult = AST_AOC_MULT_THOUSAND; 03989 } else { 03990 astman_send_error(s, m, "Invalid ChargeMultiplier"); 03991 goto aocmessage_cleanup; 03992 } 03993 } 03994 03995 /* create decoded object and start setting values */ 03996 if (!(decoded = ast_aoc_create(_msgtype, _chargetype, 0))) { 03997 astman_send_error(s, m, "Message Creation Failed"); 03998 goto aocmessage_cleanup; 03999 } 04000 04001 if (_msgtype == AST_AOC_D) { 04002 if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype, "subtotal")) { 04003 _totaltype = AST_AOC_SUBTOTAL; 04004 } 04005 04006 if (ast_strlen_zero(aocbillingid)) { 04007 /* ignore this is optional */ 04008 } else if (!strcasecmp(aocbillingid, "Normal")) { 04009 _billingid = AST_AOC_BILLING_NORMAL; 04010 } else if (!strcasecmp(aocbillingid, "ReverseCharge")) { 04011 _billingid = AST_AOC_BILLING_REVERSE_CHARGE; 04012 } else if (!strcasecmp(aocbillingid, "CreditCard")) { 04013 _billingid = AST_AOC_BILLING_CREDIT_CARD; 04014 } else { 04015 astman_send_error(s, m, "Invalid AOC-D AOCBillingId"); 04016 goto aocmessage_cleanup; 04017 } 04018 } else { 04019 if (ast_strlen_zero(aocbillingid)) { 04020 /* ignore this is optional */ 04021 } else if (!strcasecmp(aocbillingid, "Normal")) { 04022 _billingid = AST_AOC_BILLING_NORMAL; 04023 } else if (!strcasecmp(aocbillingid, "ReverseCharge")) { 04024 _billingid = AST_AOC_BILLING_REVERSE_CHARGE; 04025 } else if (!strcasecmp(aocbillingid, "CreditCard")) { 04026 _billingid = AST_AOC_BILLING_CREDIT_CARD; 04027 } else if (!strcasecmp(aocbillingid, "CallFwdUnconditional")) { 04028 _billingid = AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL; 04029 } else if (!strcasecmp(aocbillingid, "CallFwdBusy")) { 04030 _billingid = AST_AOC_BILLING_CALL_FWD_BUSY; 04031 } else if (!strcasecmp(aocbillingid, "CallFwdNoReply")) { 04032 _billingid = AST_AOC_BILLING_CALL_FWD_NO_REPLY; 04033 } else if (!strcasecmp(aocbillingid, "CallDeflection")) { 04034 _billingid = AST_AOC_BILLING_CALL_DEFLECTION; 04035 } else if (!strcasecmp(aocbillingid, "CallTransfer")) { 04036 _billingid = AST_AOC_BILLING_CALL_TRANSFER; 04037 } else { 04038 astman_send_error(s, m, "Invalid AOC-E AOCBillingId"); 04039 goto aocmessage_cleanup; 04040 } 04041 04042 if (!ast_strlen_zero(association_id) && (sscanf(association_id, "%30d", &_association_id) != 1)) { 04043 astman_send_error(s, m, "Invalid ChargingAssociationId"); 04044 goto aocmessage_cleanup; 04045 } 04046 if (!ast_strlen_zero(association_plan) && (sscanf(association_plan, "%30u", &_association_plan) != 1)) { 04047 astman_send_error(s, m, "Invalid ChargingAssociationPlan"); 04048 goto aocmessage_cleanup; 04049 } 04050 04051 if (_association_id) { 04052 ast_aoc_set_association_id(decoded, _association_id); 04053 } else if (!ast_strlen_zero(association_num)) { 04054 ast_aoc_set_association_number(decoded, association_num, _association_plan); 04055 } 04056 } 04057 04058 if (_chargetype == AST_AOC_CHARGE_CURRENCY) { 04059 ast_aoc_set_currency_info(decoded, _currencyamount, _mult, ast_strlen_zero(currencyname) ? NULL : currencyname); 04060 } else if (_chargetype == AST_AOC_CHARGE_UNIT) { 04061 struct ast_aoc_unit_entry entry; 04062 int i; 04063 04064 /* multiple unit entries are possible, lets get them all */ 04065 for (i = 0; i < 32; i++) { 04066 if (aocmessage_get_unit_entry(m, &entry, i)) { 04067 break; /* that's the end then */ 04068 } 04069 04070 ast_aoc_add_unit_entry(decoded, entry.valid_amount, entry.amount, entry.valid_type, entry.type); 04071 } 04072 04073 /* at least one unit entry is required */ 04074 if (!i) { 04075 astman_send_error(s, m, "Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit"); 04076 goto aocmessage_cleanup; 04077 } 04078 04079 } 04080 04081 ast_aoc_set_billing_id(decoded, _billingid); 04082 ast_aoc_set_total_type(decoded, _totaltype); 04083 04084 04085 if ((encoded = ast_aoc_encode(decoded, &encoded_size, NULL)) && !ast_indicate_data(chan, AST_CONTROL_AOC, encoded, encoded_size)) { 04086 astman_send_ack(s, m, "AOC Message successfully queued on channel"); 04087 } else { 04088 astman_send_error(s, m, "Error encoding AOC message, could not queue onto channel"); 04089 } 04090 04091 aocmessage_cleanup: 04092 04093 ast_aoc_destroy_decoded(decoded); 04094 ast_aoc_destroy_encoded(encoded); 04095 04096 if (chan) { 04097 chan = ast_channel_unref(chan); 04098 } 04099 return 0; 04100 }
static int action_atxfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3625 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, and pbx_builtin_setvar_helper().
Referenced by __init_manager().
03626 { 03627 const char *name = astman_get_header(m, "Channel"); 03628 const char *exten = astman_get_header(m, "Exten"); 03629 const char *context = astman_get_header(m, "Context"); 03630 struct ast_channel *chan = NULL; 03631 struct ast_call_feature *atxfer_feature = NULL; 03632 char *feature_code = NULL; 03633 03634 if (ast_strlen_zero(name)) { 03635 astman_send_error(s, m, "No channel specified"); 03636 return 0; 03637 } 03638 if (ast_strlen_zero(exten)) { 03639 astman_send_error(s, m, "No extension specified"); 03640 return 0; 03641 } 03642 03643 if (!(atxfer_feature = ast_find_call_feature("atxfer"))) { 03644 astman_send_error(s, m, "No attended transfer feature found"); 03645 return 0; 03646 } 03647 03648 if (!(chan = ast_channel_get_by_name(name))) { 03649 astman_send_error(s, m, "Channel specified does not exist"); 03650 return 0; 03651 } 03652 03653 if (!ast_strlen_zero(context)) { 03654 pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context); 03655 } 03656 03657 for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) { 03658 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code }; 03659 ast_queue_frame(chan, &f); 03660 } 03661 03662 for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) { 03663 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code }; 03664 ast_queue_frame(chan, &f); 03665 } 03666 03667 chan = ast_channel_unref(chan); 03668 03669 astman_send_ack(s, m, "Atxfer successfully queued"); 03670 03671 return 0; 03672 }
static int action_challenge | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3127 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().
03128 { 03129 const char *authtype = astman_get_header(m, "AuthType"); 03130 03131 if (!strcasecmp(authtype, "MD5")) { 03132 if (ast_strlen_zero(s->session->challenge)) { 03133 snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random()); 03134 } 03135 mansession_lock(s); 03136 astman_start_ack(s, m); 03137 astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge); 03138 mansession_unlock(s); 03139 } else { 03140 astman_send_error(s, m, "Must specify AuthType"); 03141 } 03142 return 0; 03143 }
static int action_command | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager command "command" - execute CLI command.
Definition at line 3710 of file manager.c.
References ast_cli_command, ast_free, ast_log(), AST_LOG_WARNING, ast_malloc, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), check_blacklist(), errno, LOG_WARNING, and term_strip().
Referenced by __init_manager().
03711 { 03712 const char *cmd = astman_get_header(m, "Command"); 03713 const char *id = astman_get_header(m, "ActionID"); 03714 char *buf = NULL, *final_buf = NULL; 03715 char template[] = "/tmp/ast-ami-XXXXXX"; /* template for temporary file */ 03716 int fd; 03717 off_t l; 03718 03719 if (ast_strlen_zero(cmd)) { 03720 astman_send_error(s, m, "No command provided"); 03721 return 0; 03722 } 03723 03724 if (check_blacklist(cmd)) { 03725 astman_send_error(s, m, "Command blacklisted"); 03726 return 0; 03727 } 03728 03729 if ((fd = mkstemp(template)) < 0) { 03730 ast_log(AST_LOG_WARNING, "Failed to create temporary file for command: %s\n", strerror(errno)); 03731 astman_send_error(s, m, "Command response construction error"); 03732 return 0; 03733 } 03734 03735 astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n"); 03736 if (!ast_strlen_zero(id)) { 03737 astman_append(s, "ActionID: %s\r\n", id); 03738 } 03739 /* FIXME: Wedge a ActionID response in here, waiting for later changes */ 03740 ast_cli_command(fd, cmd); /* XXX need to change this to use a FILE * */ 03741 /* Determine number of characters available */ 03742 if ((l = lseek(fd, 0, SEEK_END)) < 0) { 03743 ast_log(LOG_WARNING, "Failed to determine number of characters for command: %s\n", strerror(errno)); 03744 goto action_command_cleanup; 03745 } 03746 03747 /* This has a potential to overflow the stack. Hence, use the heap. */ 03748 buf = ast_malloc(l + 1); 03749 final_buf = ast_malloc(l + 1); 03750 03751 if (!buf || !final_buf) { 03752 ast_log(LOG_WARNING, "Failed to allocate memory for temporary buffer\n"); 03753 goto action_command_cleanup; 03754 } 03755 03756 if (lseek(fd, 0, SEEK_SET) < 0) { 03757 ast_log(LOG_WARNING, "Failed to set position on temporary file for command: %s\n", strerror(errno)); 03758 goto action_command_cleanup; 03759 } 03760 03761 if (read(fd, buf, l) < 0) { 03762 ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); 03763 goto action_command_cleanup; 03764 } 03765 03766 buf[l] = '\0'; 03767 term_strip(final_buf, buf, l); 03768 final_buf[l] = '\0'; 03769 astman_append(s, "%s", final_buf); 03770 03771 action_command_cleanup: 03772 03773 close(fd); 03774 unlink(template); 03775 astman_append(s, "--END COMMAND--\r\n\r\n"); 03776 03777 ast_free(buf); 03778 ast_free(final_buf); 03779 03780 return 0; 03781 }
static int action_coresettings | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Show PBX core settings information.
Definition at line 4446 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().
04447 { 04448 const char *actionid = astman_get_header(m, "ActionID"); 04449 char idText[150]; 04450 04451 if (!ast_strlen_zero(actionid)) { 04452 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04453 } else { 04454 idText[0] = '\0'; 04455 } 04456 04457 astman_append(s, "Response: Success\r\n" 04458 "%s" 04459 "AMIversion: %s\r\n" 04460 "AsteriskVersion: %s\r\n" 04461 "SystemName: %s\r\n" 04462 "CoreMaxCalls: %d\r\n" 04463 "CoreMaxLoadAvg: %f\r\n" 04464 "CoreRunUser: %s\r\n" 04465 "CoreRunGroup: %s\r\n" 04466 "CoreMaxFilehandles: %d\r\n" 04467 "CoreRealTimeEnabled: %s\r\n" 04468 "CoreCDRenabled: %s\r\n" 04469 "CoreHTTPenabled: %s\r\n" 04470 "\r\n", 04471 idText, 04472 AMI_VERSION, 04473 ast_get_version(), 04474 ast_config_AST_SYSTEM_NAME, 04475 option_maxcalls, 04476 option_maxload, 04477 ast_config_AST_RUN_USER, 04478 ast_config_AST_RUN_GROUP, 04479 option_maxfiles, 04480 AST_CLI_YESNO(ast_realtime_enabled()), 04481 AST_CLI_YESNO(check_cdr_enabled()), 04482 AST_CLI_YESNO(check_webmanager_enabled()) 04483 ); 04484 return 0; 04485 }
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 4555 of file manager.c.
References ast_channel::_state, 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::connected, ast_channel::context, ast_channel::data, ast_channel::exten, ast_party_connected_line::id, ast_party_caller::id, ast_party_id::name, ast_party_id::number, ast_channel::priority, S_COR, S_OR, ast_cdr::start, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.
Referenced by __init_manager().
04556 { 04557 const char *actionid = astman_get_header(m, "ActionID"); 04558 char idText[256]; 04559 struct ast_channel *c = NULL; 04560 int numchans = 0; 04561 int duration, durh, durm, durs; 04562 struct ast_channel_iterator *iter; 04563 04564 if (!ast_strlen_zero(actionid)) { 04565 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04566 } else { 04567 idText[0] = '\0'; 04568 } 04569 04570 if (!(iter = ast_channel_iterator_all_new())) { 04571 astman_send_error(s, m, "Memory Allocation Failure"); 04572 return 1; 04573 } 04574 04575 astman_send_listack(s, m, "Channels will follow", "start"); 04576 04577 for (; (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) { 04578 struct ast_channel *bc; 04579 char durbuf[10] = ""; 04580 04581 ast_channel_lock(c); 04582 04583 bc = ast_bridged_channel(c); 04584 if (c->cdr && !ast_tvzero(c->cdr->start)) { 04585 duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000); 04586 durh = duration / 3600; 04587 durm = (duration % 3600) / 60; 04588 durs = duration % 60; 04589 snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs); 04590 } 04591 04592 astman_append(s, 04593 "Event: CoreShowChannel\r\n" 04594 "%s" 04595 "Channel: %s\r\n" 04596 "UniqueID: %s\r\n" 04597 "Context: %s\r\n" 04598 "Extension: %s\r\n" 04599 "Priority: %d\r\n" 04600 "ChannelState: %d\r\n" 04601 "ChannelStateDesc: %s\r\n" 04602 "Application: %s\r\n" 04603 "ApplicationData: %s\r\n" 04604 "CallerIDnum: %s\r\n" 04605 "CallerIDname: %s\r\n" 04606 "ConnectedLineNum: %s\r\n" 04607 "ConnectedLineName: %s\r\n" 04608 "Duration: %s\r\n" 04609 "AccountCode: %s\r\n" 04610 "BridgedChannel: %s\r\n" 04611 "BridgedUniqueID: %s\r\n" 04612 "\r\n", idText, c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state, 04613 ast_state2str(c->_state), c->appl ? c->appl : "", c->data ? S_OR(c->data, "") : "", 04614 S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""), 04615 S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""), 04616 S_COR(c->connected.id.number.valid, c->connected.id.number.str, ""), 04617 S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""), 04618 durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : ""); 04619 04620 ast_channel_unlock(c); 04621 04622 numchans++; 04623 } 04624 04625 astman_append(s, 04626 "Event: CoreShowChannelsComplete\r\n" 04627 "EventList: Complete\r\n" 04628 "ListItems: %d\r\n" 04629 "%s" 04630 "\r\n", numchans, idText); 04631 04632 ast_channel_iterator_destroy(iter); 04633 04634 return 0; 04635 }
static int action_corestatus | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Show PBX core status information.
Definition at line 4488 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().
04489 { 04490 const char *actionid = astman_get_header(m, "ActionID"); 04491 char idText[150]; 04492 char startuptime[150], startupdate[150]; 04493 char reloadtime[150], reloaddate[150]; 04494 struct ast_tm tm; 04495 04496 if (!ast_strlen_zero(actionid)) { 04497 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04498 } else { 04499 idText[0] = '\0'; 04500 } 04501 04502 ast_localtime(&ast_startuptime, &tm, NULL); 04503 ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm); 04504 ast_strftime(startupdate, sizeof(startupdate), "%Y-%m-%d", &tm); 04505 ast_localtime(&ast_lastreloadtime, &tm, NULL); 04506 ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm); 04507 ast_strftime(reloaddate, sizeof(reloaddate), "%Y-%m-%d", &tm); 04508 04509 astman_append(s, "Response: Success\r\n" 04510 "%s" 04511 "CoreStartupDate: %s\r\n" 04512 "CoreStartupTime: %s\r\n" 04513 "CoreReloadDate: %s\r\n" 04514 "CoreReloadTime: %s\r\n" 04515 "CoreCurrentCalls: %d\r\n" 04516 "\r\n", 04517 idText, 04518 startupdate, 04519 startuptime, 04520 reloaddate, 04521 reloadtime, 04522 ast_active_channels() 04523 ); 04524 return 0; 04525 }
static int action_createconfig | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2903 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().
02904 { 02905 int fd; 02906 const char *fn = astman_get_header(m, "Filename"); 02907 struct ast_str *filepath = ast_str_alloca(PATH_MAX); 02908 ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR); 02909 ast_str_append(&filepath, 0, "%s", fn); 02910 02911 if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) { 02912 close(fd); 02913 astman_send_ack(s, m, "New configuration file created successfully"); 02914 } else { 02915 astman_send_error(s, m, strerror(errno)); 02916 } 02917 02918 return 0; 02919 }
static void action_destroy | ( | void * | obj | ) | [static] |
Definition at line 5426 of file manager.c.
References ast_string_field_free_memory.
Referenced by ast_manager_register2().
05427 { 05428 struct manager_action *doomed = obj; 05429 05430 if (doomed->synopsis) { 05431 /* The string fields were initialized. */ 05432 ast_string_field_free_memory(doomed); 05433 } 05434 }
static int action_events | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3046 of file manager.c.
References ARRAY_LEN, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), permalias::num, perms, and set_eventmask().
Referenced by __init_manager().
03047 { 03048 const char *mask = astman_get_header(m, "EventMask"); 03049 int res, x; 03050 const char *id = astman_get_header(m, "ActionID"); 03051 char id_text[256]; 03052 03053 if (!ast_strlen_zero(id)) { 03054 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id); 03055 } else { 03056 id_text[0] = '\0'; 03057 } 03058 03059 res = set_eventmask(s, mask); 03060 if (broken_events_action) { 03061 /* if this option is set we should not return a response on 03062 * error, or when all events are set */ 03063 03064 if (res > 0) { 03065 for (x = 0; x < ARRAY_LEN(perms); x++) { 03066 if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) { 03067 return 0; 03068 } 03069 } 03070 astman_append(s, "Response: Success\r\n%s" 03071 "Events: On\r\n\r\n", id_text); 03072 } else if (res == 0) 03073 astman_append(s, "Response: Success\r\n%s" 03074 "Events: Off\r\n\r\n", id_text); 03075 return 0; 03076 } 03077 03078 if (res > 0) 03079 astman_append(s, "Response: Success\r\n%s" 03080 "Events: On\r\n\r\n", id_text); 03081 else if (res == 0) 03082 astman_append(s, "Response: Success\r\n%s" 03083 "Events: Off\r\n\r\n", id_text); 03084 else 03085 astman_send_error(s, m, "Invalid event mask"); 03086 03087 return 0; 03088 }
static int action_extensionstate | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4284 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().
04285 { 04286 const char *exten = astman_get_header(m, "Exten"); 04287 const char *context = astman_get_header(m, "Context"); 04288 char hint[256] = ""; 04289 int status; 04290 if (ast_strlen_zero(exten)) { 04291 astman_send_error(s, m, "Extension not specified"); 04292 return 0; 04293 } 04294 if (ast_strlen_zero(context)) { 04295 context = "default"; 04296 } 04297 status = ast_extension_state(NULL, context, exten); 04298 ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten); 04299 astman_start_ack(s, m); 04300 astman_append(s, "Message: Extension Status\r\n" 04301 "Exten: %s\r\n" 04302 "Context: %s\r\n" 04303 "Hint: %s\r\n" 04304 "Status: %d\r\n\r\n", 04305 exten, context, hint, status); 04306 return 0; 04307 }
static struct manager_action* action_find | ( | const char * | name | ) | [static, read] |
Definition at line 1073 of file manager.c.
References manager_action::action, ao2_t_ref, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, and AST_RWLIST_UNLOCK.
Referenced by ast_hook_send_action(), and process_message().
01074 { 01075 struct manager_action *act; 01076 01077 AST_RWLIST_RDLOCK(&actions); 01078 AST_RWLIST_TRAVERSE(&actions, act, list) { 01079 if (!strcasecmp(name, act->action)) { 01080 ao2_t_ref(act, +1, "found action object"); 01081 break; 01082 } 01083 } 01084 AST_RWLIST_UNLOCK(&actions); 01085 01086 return act; 01087 }
static int action_getconfig | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2521 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(), eventqent::category, CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by __init_manager().
02522 { 02523 struct ast_config *cfg; 02524 const char *fn = astman_get_header(m, "Filename"); 02525 const char *category = astman_get_header(m, "Category"); 02526 int catcount = 0; 02527 int lineno = 0; 02528 char *cur_category = NULL; 02529 struct ast_variable *v; 02530 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02531 02532 if (ast_strlen_zero(fn)) { 02533 astman_send_error(s, m, "Filename not specified"); 02534 return 0; 02535 } 02536 cfg = ast_config_load2(fn, "manager", config_flags); 02537 if (cfg == CONFIG_STATUS_FILEMISSING) { 02538 astman_send_error(s, m, "Config file not found"); 02539 return 0; 02540 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02541 astman_send_error(s, m, "Config file has invalid format"); 02542 return 0; 02543 } 02544 02545 astman_start_ack(s, m); 02546 while ((cur_category = ast_category_browse(cfg, cur_category))) { 02547 if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) { 02548 lineno = 0; 02549 astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category); 02550 for (v = ast_variable_browse(cfg, cur_category); v; v = v->next) { 02551 astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value); 02552 } 02553 catcount++; 02554 } 02555 } 02556 if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */ 02557 astman_append(s, "No categories found\r\n"); 02558 } 02559 ast_config_destroy(cfg); 02560 astman_append(s, "\r\n"); 02561 02562 return 0; 02563 }
static int action_getconfigjson | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2631 of file manager.c.
References ast_category_browse(), ast_config_destroy(), ast_config_load2(), ast_strlen_zero(), ast_variable_browse(), astman_append(), astman_append_json(), astman_get_header(), astman_send_error(), astman_start_ack(), eventqent::category, CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEINVALID, ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by __init_manager().
02632 { 02633 struct ast_config *cfg; 02634 const char *fn = astman_get_header(m, "Filename"); 02635 char *category = NULL; 02636 struct ast_variable *v; 02637 int comma1 = 0; 02638 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02639 02640 if (ast_strlen_zero(fn)) { 02641 astman_send_error(s, m, "Filename not specified"); 02642 return 0; 02643 } 02644 02645 if (!(cfg = ast_config_load2(fn, "manager", config_flags))) { 02646 astman_send_error(s, m, "Config file not found"); 02647 return 0; 02648 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02649 astman_send_error(s, m, "Config file has invalid format"); 02650 return 0; 02651 } 02652 02653 astman_start_ack(s, m); 02654 astman_append(s, "JSON: {"); 02655 while ((category = ast_category_browse(cfg, category))) { 02656 int comma2 = 0; 02657 02658 astman_append(s, "%s\"", comma1 ? "," : ""); 02659 astman_append_json(s, category); 02660 astman_append(s, "\":["); 02661 comma1 = 1; 02662 for (v = ast_variable_browse(cfg, category); v; v = v->next) { 02663 astman_append(s, "%s\"", comma2 ? "," : ""); 02664 astman_append_json(s, v->name); 02665 astman_append(s, "\":\""); 02666 astman_append_json(s, v->value); 02667 astman_append(s, "\""); 02668 comma2 = 1; 02669 } 02670 astman_append(s, "]"); 02671 } 02672 astman_append(s, "}\r\n\r\n"); 02673 02674 ast_config_destroy(cfg); 02675 02676 return 0; 02677 }
static int action_getvar | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3221 of file manager.c.
References ast_channel_get_by_name(), 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(), function_capable_string_allowed_with_auths(), LOG_ERROR, pbx_retrieve_variable(), S_OR, mansession::session, and mansession_session::writeperm.
Referenced by __init_manager().
03222 { 03223 struct ast_channel *c = NULL; 03224 const char *name = astman_get_header(m, "Channel"); 03225 const char *varname = astman_get_header(m, "Variable"); 03226 char *varval; 03227 char workspace[1024]; 03228 03229 if (ast_strlen_zero(varname)) { 03230 astman_send_error(s, m, "No variable specified"); 03231 return 0; 03232 } 03233 03234 /* We don't want users with insufficient permissions using certain functions. */ 03235 if (!(function_capable_string_allowed_with_auths(varname, s->session->writeperm))) { 03236 astman_send_error(s, m, "GetVar Access Forbidden: Variable"); 03237 return 0; 03238 } 03239 03240 if (!ast_strlen_zero(name)) { 03241 if (!(c = ast_channel_get_by_name(name))) { 03242 astman_send_error(s, m, "No such channel"); 03243 return 0; 03244 } 03245 } 03246 03247 workspace[0] = '\0'; 03248 if (varname[strlen(varname) - 1] == ')') { 03249 if (!c) { 03250 c = ast_dummy_channel_alloc(); 03251 if (c) { 03252 ast_func_read(c, (char *) varname, workspace, sizeof(workspace)); 03253 } else 03254 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03255 } else { 03256 ast_func_read(c, (char *) varname, workspace, sizeof(workspace)); 03257 } 03258 varval = workspace; 03259 } else { 03260 pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL); 03261 } 03262 03263 if (c) { 03264 c = ast_channel_unref(c); 03265 } 03266 03267 astman_start_ack(s, m); 03268 astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, S_OR(varval, "")); 03269 03270 return 0; 03271 }
static int action_hangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3145 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(), ast_channel::hangupcause, and LOG_NOTICE.
Referenced by __init_manager().
03146 { 03147 struct ast_channel *c = NULL; 03148 int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */ 03149 const char *name = astman_get_header(m, "Channel"); 03150 const char *cause = astman_get_header(m, "Cause"); 03151 03152 if (ast_strlen_zero(name)) { 03153 astman_send_error(s, m, "No channel specified"); 03154 return 0; 03155 } 03156 03157 if (!ast_strlen_zero(cause)) { 03158 char *endptr; 03159 causecode = strtol(cause, &endptr, 10); 03160 if (causecode < 0 || causecode > 127 || *endptr != '\0') { 03161 ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause); 03162 /* keep going, better to hangup without cause than to not hang up at all */ 03163 causecode = 0; /* do not set channel's hangupcause */ 03164 } 03165 } 03166 03167 if (!(c = ast_channel_get_by_name(name))) { 03168 astman_send_error(s, m, "No such channel"); 03169 return 0; 03170 } 03171 03172 ast_channel_lock(c); 03173 if (causecode > 0) { 03174 ast_debug(1, "Setting hangupcause of channel %s to %d (is %d now)\n", 03175 c->name, causecode, c->hangupcause); 03176 c->hangupcause = causecode; 03177 } 03178 ast_softhangup_nolock(c, AST_SOFTHANGUP_EXPLICIT); 03179 ast_channel_unlock(c); 03180 03181 c = ast_channel_unref(c); 03182 03183 astman_send_ack(s, m, "Channel Hungup"); 03184 03185 return 0; 03186 }
static int action_listcategories | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2565 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(), eventqent::category, CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, and CONFIG_STATUS_FILEINVALID.
Referenced by __init_manager().
02566 { 02567 struct ast_config *cfg; 02568 const char *fn = astman_get_header(m, "Filename"); 02569 char *category = NULL; 02570 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02571 int catcount = 0; 02572 02573 if (ast_strlen_zero(fn)) { 02574 astman_send_error(s, m, "Filename not specified"); 02575 return 0; 02576 } 02577 if (!(cfg = ast_config_load2(fn, "manager", config_flags))) { 02578 astman_send_error(s, m, "Config file not found"); 02579 return 0; 02580 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02581 astman_send_error(s, m, "Config file has invalid format"); 02582 return 0; 02583 } 02584 astman_start_ack(s, m); 02585 while ((category = ast_category_browse(cfg, category))) { 02586 astman_append(s, "Category-%06d: %s\r\n", catcount, category); 02587 catcount++; 02588 } 02589 if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */ 02590 astman_append(s, "Error: no categories found\r\n"); 02591 } 02592 ast_config_destroy(cfg); 02593 astman_append(s, "\r\n"); 02594 02595 return 0; 02596 }
static int action_listcommands | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3027 of file manager.c.
References manager_action::action, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, astman_append(), astman_start_ack(), manager_action::authority, authority_to_str(), mansession::session, and mansession_session::writeperm.
Referenced by __init_manager().
03028 { 03029 struct manager_action *cur; 03030 struct ast_str *temp = ast_str_alloca(256); 03031 03032 astman_start_ack(s, m); 03033 AST_RWLIST_RDLOCK(&actions); 03034 AST_RWLIST_TRAVERSE(&actions, cur, list) { 03035 if ((s->session->writeperm & cur->authority) || cur->authority == 0) { 03036 astman_append(s, "%s: %s (Priv: %s)\r\n", 03037 cur->action, cur->synopsis, authority_to_str(cur->authority, &temp)); 03038 } 03039 } 03040 AST_RWLIST_UNLOCK(&actions); 03041 astman_append(s, "\r\n"); 03042 03043 return 0; 03044 }
static int action_login | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3096 of file manager.c.
References ast_atomic_fetchadd_int(), ast_inet_ntoa(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, ast_str_alloca, ast_test_flag, ast_verb, astman_append(), astman_send_ack(), astman_send_error(), authenticate(), mansession_session::authenticated, authority_to_str(), EVENT_FLAG_SYSTEM, manager_displayconnects(), mansession_session::managerid, mansession_session::send_events, mansession::session, mansession_session::sin, unauth_sessions, and mansession_session::username.
Referenced by __init_manager().
03097 { 03098 03099 /* still authenticated - don't process again */ 03100 if (s->session->authenticated) { 03101 astman_send_ack(s, m, "Already authenticated"); 03102 return 0; 03103 } 03104 03105 if (authenticate(s, m)) { 03106 sleep(1); 03107 astman_send_error(s, m, "Authentication failed"); 03108 return -1; 03109 } 03110 s->session->authenticated = 1; 03111 ast_atomic_fetchadd_int(&unauth_sessions, -1); 03112 if (manager_displayconnects(s->session)) { 03113 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)); 03114 } 03115 astman_send_ack(s, m, "Authentication accepted"); 03116 if ((s->session->send_events & EVENT_FLAG_SYSTEM) 03117 && ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 03118 struct ast_str *auth = ast_str_alloca(80); 03119 const char *cat_str = authority_to_str(EVENT_FLAG_SYSTEM, &auth); 03120 astman_append(s, "Event: FullyBooted\r\n" 03121 "Privilege: %s\r\n" 03122 "Status: Fully Booted\r\n\r\n", cat_str); 03123 } 03124 return 0; 03125 }
static int action_logoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3090 of file manager.c.
References astman_send_response().
Referenced by __init_manager().
03091 { 03092 astman_send_response(s, m, "Goodbye", "Thanks for all the fish."); 03093 return -1; 03094 }
static int action_mailboxcount | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4263 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().
04264 { 04265 const char *mailbox = astman_get_header(m, "Mailbox"); 04266 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;; 04267 04268 if (ast_strlen_zero(mailbox)) { 04269 astman_send_error(s, m, "Mailbox not specified"); 04270 return 0; 04271 } 04272 ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs); 04273 astman_start_ack(s, m); 04274 astman_append(s, "Message: Mailbox Message Count\r\n" 04275 "Mailbox: %s\r\n" 04276 "UrgMessages: %d\r\n" 04277 "NewMessages: %d\r\n" 04278 "OldMessages: %d\r\n" 04279 "\r\n", 04280 mailbox, urgentmsgs, newmsgs, oldmsgs); 04281 return 0; 04282 }
static int action_mailboxstatus | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4246 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().
04247 { 04248 const char *mailbox = astman_get_header(m, "Mailbox"); 04249 int ret; 04250 04251 if (ast_strlen_zero(mailbox)) { 04252 astman_send_error(s, m, "Mailbox not specified"); 04253 return 0; 04254 } 04255 ret = ast_app_has_voicemail(mailbox, NULL); 04256 astman_start_ack(s, m); 04257 astman_append(s, "Message: Mailbox Status\r\n" 04258 "Mailbox: %s\r\n" 04259 "Waiting: %d\r\n\r\n", mailbox, ret); 04260 return 0; 04261 }
static int action_originate | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4102 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_string_field_build, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_true(), ast_variables_destroy(), astman_get_header(), astman_get_variables(), astman_send_ack(), astman_send_error(), cid_name, cid_num, context, ast_frame::data, destroy_fast_originate_helper(), EVENT_FLAG_SYSTEM, exten, fast_originate(), fast_originate_helper::format, fast_originate_helper::priority, mansession::session, fast_originate_helper::timeout, fast_originate_helper::vars, and mansession_session::writeperm.
Referenced by __init_manager().
04103 { 04104 const char *name = astman_get_header(m, "Channel"); 04105 const char *exten = astman_get_header(m, "Exten"); 04106 const char *context = astman_get_header(m, "Context"); 04107 const char *priority = astman_get_header(m, "Priority"); 04108 const char *timeout = astman_get_header(m, "Timeout"); 04109 const char *callerid = astman_get_header(m, "CallerID"); 04110 const char *account = astman_get_header(m, "Account"); 04111 const char *app = astman_get_header(m, "Application"); 04112 const char *appdata = astman_get_header(m, "Data"); 04113 const char *async = astman_get_header(m, "Async"); 04114 const char *id = astman_get_header(m, "ActionID"); 04115 const char *codecs = astman_get_header(m, "Codecs"); 04116 struct ast_variable *vars; 04117 char *tech, *data; 04118 char *l = NULL, *n = NULL; 04119 int pi = 0; 04120 int res; 04121 int to = 30000; 04122 int reason = 0; 04123 char tmp[256]; 04124 char tmp2[256]; 04125 format_t format = AST_FORMAT_SLINEAR; 04126 04127 pthread_t th; 04128 if (ast_strlen_zero(name)) { 04129 astman_send_error(s, m, "Channel not specified"); 04130 return 0; 04131 } 04132 if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) { 04133 if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) { 04134 astman_send_error(s, m, "Invalid priority"); 04135 return 0; 04136 } 04137 } 04138 if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) { 04139 astman_send_error(s, m, "Invalid timeout"); 04140 return 0; 04141 } 04142 ast_copy_string(tmp, name, sizeof(tmp)); 04143 tech = tmp; 04144 data = strchr(tmp, '/'); 04145 if (!data) { 04146 astman_send_error(s, m, "Invalid channel"); 04147 return 0; 04148 } 04149 *data++ = '\0'; 04150 ast_copy_string(tmp2, callerid, sizeof(tmp2)); 04151 ast_callerid_parse(tmp2, &n, &l); 04152 if (n) { 04153 if (ast_strlen_zero(n)) { 04154 n = NULL; 04155 } 04156 } 04157 if (l) { 04158 ast_shrink_phone_number(l); 04159 if (ast_strlen_zero(l)) { 04160 l = NULL; 04161 } 04162 } 04163 if (!ast_strlen_zero(codecs)) { 04164 format = 0; 04165 ast_parse_allow_disallow(NULL, &format, codecs, 1); 04166 } 04167 if (!ast_strlen_zero(app) && s->session) { 04168 int bad_appdata = 0; 04169 /* To run the System application (or anything else that goes to 04170 * shell), you must have the additional System privilege */ 04171 if (!(s->session->writeperm & EVENT_FLAG_SYSTEM) 04172 && ( 04173 strcasestr(app, "system") || /* System(rm -rf /) 04174 TrySystem(rm -rf /) */ 04175 strcasestr(app, "exec") || /* Exec(System(rm -rf /)) 04176 TryExec(System(rm -rf /)) */ 04177 strcasestr(app, "agi") || /* AGI(/bin/rm,-rf /) 04178 EAGI(/bin/rm,-rf /) */ 04179 strcasestr(app, "mixmonitor") || /* MixMonitor(blah,,rm -rf) */ 04180 strcasestr(app, "externalivr") || /* ExternalIVR(rm -rf) */ 04181 (strstr(appdata, "SHELL") && (bad_appdata = 1)) || /* NoOp(${SHELL(rm -rf /)}) */ 04182 (strstr(appdata, "EVAL") && (bad_appdata = 1)) /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ 04183 )) { 04184 char error_buf[64]; 04185 snprintf(error_buf, sizeof(error_buf), "Originate Access Forbidden: %s", bad_appdata ? "Data" : "Application"); 04186 astman_send_error(s, m, error_buf); 04187 return 0; 04188 } 04189 } 04190 /* Allocate requested channel variables */ 04191 vars = astman_get_variables(m); 04192 04193 if (ast_true(async)) { 04194 struct fast_originate_helper *fast; 04195 04196 fast = ast_calloc(1, sizeof(*fast)); 04197 if (!fast || ast_string_field_init(fast, 252)) { 04198 ast_free(fast); 04199 ast_variables_destroy(vars); 04200 res = -1; 04201 } else { 04202 if (!ast_strlen_zero(id)) { 04203 ast_string_field_build(fast, idtext, "ActionID: %s\r\n", id); 04204 } 04205 ast_string_field_set(fast, tech, tech); 04206 ast_string_field_set(fast, data, data); 04207 ast_string_field_set(fast, app, app); 04208 ast_string_field_set(fast, appdata, appdata); 04209 ast_string_field_set(fast, cid_num, l); 04210 ast_string_field_set(fast, cid_name, n); 04211 ast_string_field_set(fast, context, context); 04212 ast_string_field_set(fast, exten, exten); 04213 ast_string_field_set(fast, account, account); 04214 fast->vars = vars; 04215 fast->format = format; 04216 fast->timeout = to; 04217 fast->priority = pi; 04218 if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) { 04219 destroy_fast_originate_helper(fast); 04220 res = -1; 04221 } else { 04222 res = 0; 04223 } 04224 } 04225 } else if (!ast_strlen_zero(app)) { 04226 res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL); 04227 /* Any vars memory was passed to ast_pbx_outgoing_app(). */ 04228 } else { 04229 if (exten && context && pi) { 04230 res = ast_pbx_outgoing_exten(tech, format, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL); 04231 /* Any vars memory was passed to ast_pbx_outgoing_exten(). */ 04232 } else { 04233 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'"); 04234 ast_variables_destroy(vars); 04235 return 0; 04236 } 04237 } 04238 if (!res) { 04239 astman_send_ack(s, m, "Originate successfully queued"); 04240 } else { 04241 astman_send_error(s, m, "Originate failed"); 04242 } 04243 return 0; 04244 }
static int action_ping | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2503 of file manager.c.
References ast_strlen_zero(), ast_tvnow(), astman_append(), and astman_get_header().
Referenced by __init_manager().
02504 { 02505 const char *actionid = astman_get_header(m, "ActionID"); 02506 struct timeval now = ast_tvnow(); 02507 02508 astman_append(s, "Response: Success\r\n"); 02509 if (!ast_strlen_zero(actionid)){ 02510 astman_append(s, "ActionID: %s\r\n", actionid); 02511 } 02512 astman_append( 02513 s, 02514 "Ping: Pong\r\n" 02515 "Timestamp: %ld.%06lu\r\n" 02516 "\r\n", 02517 (long) now.tv_sec, (unsigned long) now.tv_usec); 02518 return 0; 02519 }
static int action_redirect | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
action_redirect: The redirect manager command
Definition at line 3472 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_clear_flag, ast_findlabel_extension(), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT, AST_FLAG_BRIDGE_HANGUP_DONT, ast_set_flag, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), context, exten, ast_channel::pbx, and ast_channel::priority.
Referenced by __init_manager().
03473 { 03474 char buf[256]; 03475 const char *name = astman_get_header(m, "Channel"); 03476 const char *name2 = astman_get_header(m, "ExtraChannel"); 03477 const char *exten = astman_get_header(m, "Exten"); 03478 const char *exten2 = astman_get_header(m, "ExtraExten"); 03479 const char *context = astman_get_header(m, "Context"); 03480 const char *context2 = astman_get_header(m, "ExtraContext"); 03481 const char *priority = astman_get_header(m, "Priority"); 03482 const char *priority2 = astman_get_header(m, "ExtraPriority"); 03483 struct ast_channel *chan; 03484 struct ast_channel *chan2; 03485 int pi = 0; 03486 int pi2 = 0; 03487 int res; 03488 03489 if (ast_strlen_zero(name)) { 03490 astman_send_error(s, m, "Channel not specified"); 03491 return 0; 03492 } 03493 03494 if (ast_strlen_zero(context)) { 03495 astman_send_error(s, m, "Context not specified"); 03496 return 0; 03497 } 03498 if (ast_strlen_zero(exten)) { 03499 astman_send_error(s, m, "Exten not specified"); 03500 return 0; 03501 } 03502 if (ast_strlen_zero(priority)) { 03503 astman_send_error(s, m, "Priority not specified"); 03504 return 0; 03505 } 03506 if (sscanf(priority, "%30d", &pi) != 1) { 03507 pi = ast_findlabel_extension(NULL, context, exten, priority, NULL); 03508 } 03509 if (pi < 1) { 03510 astman_send_error(s, m, "Priority is invalid"); 03511 return 0; 03512 } 03513 03514 if (!ast_strlen_zero(name2) && !ast_strlen_zero(context2)) { 03515 /* We have an ExtraChannel and an ExtraContext */ 03516 if (ast_strlen_zero(exten2)) { 03517 astman_send_error(s, m, "ExtraExten not specified"); 03518 return 0; 03519 } 03520 if (ast_strlen_zero(priority2)) { 03521 astman_send_error(s, m, "ExtraPriority not specified"); 03522 return 0; 03523 } 03524 if (sscanf(priority2, "%30d", &pi2) != 1) { 03525 pi2 = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL); 03526 } 03527 if (pi2 < 1) { 03528 astman_send_error(s, m, "ExtraPriority is invalid"); 03529 return 0; 03530 } 03531 } 03532 03533 chan = ast_channel_get_by_name(name); 03534 if (!chan) { 03535 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name); 03536 astman_send_error(s, m, buf); 03537 return 0; 03538 } 03539 if (ast_check_hangup_locked(chan)) { 03540 astman_send_error(s, m, "Redirect failed, channel not up."); 03541 chan = ast_channel_unref(chan); 03542 return 0; 03543 } 03544 03545 if (ast_strlen_zero(name2)) { 03546 /* Single channel redirect in progress. */ 03547 if (chan->pbx) { 03548 ast_channel_lock(chan); 03549 /* don't let the after-bridge code run the h-exten */ 03550 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT); 03551 ast_channel_unlock(chan); 03552 } 03553 res = ast_async_goto(chan, context, exten, pi); 03554 if (!res) { 03555 astman_send_ack(s, m, "Redirect successful"); 03556 } else { 03557 astman_send_error(s, m, "Redirect failed"); 03558 } 03559 chan = ast_channel_unref(chan); 03560 return 0; 03561 } 03562 03563 chan2 = ast_channel_get_by_name(name2); 03564 if (!chan2) { 03565 snprintf(buf, sizeof(buf), "ExtraChannel does not exist: %s", name2); 03566 astman_send_error(s, m, buf); 03567 chan = ast_channel_unref(chan); 03568 return 0; 03569 } 03570 if (ast_check_hangup_locked(chan2)) { 03571 astman_send_error(s, m, "Redirect failed, extra channel not up."); 03572 chan2 = ast_channel_unref(chan2); 03573 chan = ast_channel_unref(chan); 03574 return 0; 03575 } 03576 03577 /* Dual channel redirect in progress. */ 03578 if (chan->pbx) { 03579 ast_channel_lock(chan); 03580 /* don't let the after-bridge code run the h-exten */ 03581 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT 03582 | AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); 03583 ast_channel_unlock(chan); 03584 } 03585 if (chan2->pbx) { 03586 ast_channel_lock(chan2); 03587 /* don't let the after-bridge code run the h-exten */ 03588 ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT 03589 | AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); 03590 ast_channel_unlock(chan2); 03591 } 03592 res = ast_async_goto(chan, context, exten, pi); 03593 if (!res) { 03594 if (!ast_strlen_zero(context2)) { 03595 res = ast_async_goto(chan2, context2, exten2, pi2); 03596 } else { 03597 res = ast_async_goto(chan2, context, exten, pi); 03598 } 03599 if (!res) { 03600 astman_send_ack(s, m, "Dual Redirect successful"); 03601 } else { 03602 astman_send_error(s, m, "Secondary redirect failed"); 03603 } 03604 } else { 03605 astman_send_error(s, m, "Redirect failed"); 03606 } 03607 03608 /* Release the bridge wait. */ 03609 if (chan->pbx) { 03610 ast_channel_lock(chan); 03611 ast_clear_flag(chan, AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); 03612 ast_channel_unlock(chan); 03613 } 03614 if (chan2->pbx) { 03615 ast_channel_lock(chan2); 03616 ast_clear_flag(chan2, AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); 03617 ast_channel_unlock(chan2); 03618 } 03619 03620 chan2 = ast_channel_unref(chan2); 03621 chan = ast_channel_unref(chan); 03622 return 0; 03623 }
static int action_reload | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Send a reload event.
Definition at line 4528 of file manager.c.
References ast_module_reload(), astman_get_header(), astman_send_ack(), astman_send_error(), and S_OR.
Referenced by __init_manager().
04529 { 04530 const char *module = astman_get_header(m, "Module"); 04531 int res = ast_module_reload(S_OR(module, NULL)); 04532 04533 switch (res) { 04534 case -1: 04535 astman_send_error(s, m, "A reload is in progress"); 04536 break; 04537 case 0: 04538 astman_send_error(s, m, "No such module"); 04539 break; 04540 case 1: 04541 astman_send_error(s, m, "Module does not support reload"); 04542 break; 04543 case 2: 04544 astman_send_ack(s, m, "Module Reloaded"); 04545 break; 04546 default: 04547 astman_send_error(s, m, "An unknown error occurred"); 04548 break; 04549 } 04550 return 0; 04551 }
static int action_sendtext | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3437 of file manager.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_sendtext(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), and astman_send_error().
Referenced by __init_manager().
03438 { 03439 struct ast_channel *c = NULL; 03440 const char *name = astman_get_header(m, "Channel"); 03441 const char *textmsg = astman_get_header(m, "Message"); 03442 int res = 0; 03443 03444 if (ast_strlen_zero(name)) { 03445 astman_send_error(s, m, "No channel specified"); 03446 return 0; 03447 } 03448 03449 if (ast_strlen_zero(textmsg)) { 03450 astman_send_error(s, m, "No Message specified"); 03451 return 0; 03452 } 03453 03454 if (!(c = ast_channel_get_by_name(name))) { 03455 astman_send_error(s, m, "No such channel"); 03456 return 0; 03457 } 03458 03459 res = ast_sendtext(c, textmsg); 03460 c = ast_channel_unref(c); 03461 03462 if (res >= 0) { 03463 astman_send_ack(s, m, "Success"); 03464 } else { 03465 astman_send_error(s, m, "Failure"); 03466 } 03467 03468 return res; 03469 }
static int action_setvar | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3188 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(), pbx_builtin_setvar_helper(), and S_OR.
Referenced by __init_manager().
03189 { 03190 struct ast_channel *c = NULL; 03191 const char *name = astman_get_header(m, "Channel"); 03192 const char *varname = astman_get_header(m, "Variable"); 03193 const char *varval = astman_get_header(m, "Value"); 03194 int res = 0; 03195 03196 if (ast_strlen_zero(varname)) { 03197 astman_send_error(s, m, "No variable specified"); 03198 return 0; 03199 } 03200 03201 if (!ast_strlen_zero(name)) { 03202 if (!(c = ast_channel_get_by_name(name))) { 03203 astman_send_error(s, m, "No such channel"); 03204 return 0; 03205 } 03206 } 03207 03208 res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, "")); 03209 03210 if (c) { 03211 c = ast_channel_unref(c); 03212 } 03213 if (res == 0) { 03214 astman_send_ack(s, m, "Variable Set"); 03215 } else { 03216 astman_send_error(s, m, "Variable not set"); 03217 } 03218 return 0; 03219 }
static int action_status | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager "status" command to show channels.
Definition at line 3275 of file manager.c.
References ast_channel::_bridge, ast_channel::_state, AST_APP_ARG, ast_channel_get_by_name(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, AST_DECLARE_APP_ARGS, ast_free, ast_func_read(), AST_STANDARD_APP_ARGS, ast_state2str(), ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_reset(), ast_strdupa, ast_strlen_zero(), ast_tvnow(), astman_append(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_channel::bridge, ast_channel::caller, ast_channel::cdr, channels, ast_channel::connected, ast_channel::context, ast_channel::exten, function_capable_string_allowed_with_auths(), ast_party_connected_line::id, ast_party_caller::id, ast_party_id::name, ast_party_id::number, ast_channel::pbx, pbx_retrieve_variable(), ast_channel::priority, S_COR, S_OR, mansession::session, ast_cdr::start, ast_party_name::str, ast_party_number::str, str, ast_party_name::valid, ast_party_number::valid, and mansession_session::writeperm.
Referenced by __init_manager().
03276 { 03277 const char *name = astman_get_header(m, "Channel"); 03278 const char *cvariables = astman_get_header(m, "Variables"); 03279 char *variables = ast_strdupa(S_OR(cvariables, "")); 03280 struct ast_channel *c; 03281 char bridge[256]; 03282 struct timeval now = ast_tvnow(); 03283 long elapsed_seconds = 0; 03284 int channels = 0; 03285 int all = ast_strlen_zero(name); /* set if we want all channels */ 03286 const char *id = astman_get_header(m, "ActionID"); 03287 char idText[256]; 03288 AST_DECLARE_APP_ARGS(vars, 03289 AST_APP_ARG(name)[100]; 03290 ); 03291 struct ast_str *str = ast_str_create(1000); 03292 struct ast_channel_iterator *iter = NULL; 03293 03294 if (!ast_strlen_zero(id)) { 03295 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 03296 } else { 03297 idText[0] = '\0'; 03298 } 03299 03300 if (!(function_capable_string_allowed_with_auths(variables, s->session->writeperm))) { 03301 astman_send_error(s, m, "Status Access Forbidden: Variables"); 03302 return 0; 03303 } 03304 03305 if (all) { 03306 if (!(iter = ast_channel_iterator_all_new())) { 03307 ast_free(str); 03308 astman_send_error(s, m, "Memory Allocation Failure"); 03309 return 1; 03310 } 03311 c = ast_channel_iterator_next(iter); 03312 } else { 03313 if (!(c = ast_channel_get_by_name(name))) { 03314 astman_send_error(s, m, "No such channel"); 03315 ast_free(str); 03316 return 0; 03317 } 03318 } 03319 03320 astman_send_ack(s, m, "Channel status will follow"); 03321 03322 if (!ast_strlen_zero(cvariables)) { 03323 AST_STANDARD_APP_ARGS(vars, variables); 03324 } 03325 03326 /* if we look by name, we break after the first iteration */ 03327 for (; c; c = ast_channel_iterator_next(iter)) { 03328 ast_channel_lock(c); 03329 03330 if (!ast_strlen_zero(cvariables)) { 03331 int i; 03332 ast_str_reset(str); 03333 for (i = 0; i < vars.argc; i++) { 03334 char valbuf[512], *ret = NULL; 03335 03336 if (vars.name[i][strlen(vars.name[i]) - 1] == ')') { 03337 if (ast_func_read(c, vars.name[i], valbuf, sizeof(valbuf)) < 0) { 03338 valbuf[0] = '\0'; 03339 } 03340 ret = valbuf; 03341 } else { 03342 pbx_retrieve_variable(c, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL); 03343 } 03344 03345 ast_str_append(&str, 0, "Variable: %s=%s\r\n", vars.name[i], ret); 03346 } 03347 } 03348 03349 channels++; 03350 if (c->_bridge) { 03351 snprintf(bridge, sizeof(bridge), "BridgedChannel: %s\r\nBridgedUniqueid: %s\r\n", c->_bridge->name, c->_bridge->uniqueid); 03352 } else { 03353 bridge[0] = '\0'; 03354 } 03355 if (c->pbx) { 03356 if (c->cdr) { 03357 elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec; 03358 } 03359 astman_append(s, 03360 "Event: Status\r\n" 03361 "Privilege: Call\r\n" 03362 "Channel: %s\r\n" 03363 "CallerIDNum: %s\r\n" 03364 "CallerIDName: %s\r\n" 03365 "ConnectedLineNum: %s\r\n" 03366 "ConnectedLineName: %s\r\n" 03367 "Accountcode: %s\r\n" 03368 "ChannelState: %d\r\n" 03369 "ChannelStateDesc: %s\r\n" 03370 "Context: %s\r\n" 03371 "Extension: %s\r\n" 03372 "Priority: %d\r\n" 03373 "Seconds: %ld\r\n" 03374 "%s" 03375 "Uniqueid: %s\r\n" 03376 "%s" 03377 "%s" 03378 "\r\n", 03379 c->name, 03380 S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"), 03381 S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"), 03382 S_COR(c->connected.id.number.valid, c->connected.id.number.str, "<unknown>"), 03383 S_COR(c->connected.id.name.valid, c->connected.id.name.str, "<unknown>"), 03384 c->accountcode, 03385 c->_state, 03386 ast_state2str(c->_state), c->context, 03387 c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, ast_str_buffer(str), idText); 03388 } else { 03389 astman_append(s, 03390 "Event: Status\r\n" 03391 "Privilege: Call\r\n" 03392 "Channel: %s\r\n" 03393 "CallerIDNum: %s\r\n" 03394 "CallerIDName: %s\r\n" 03395 "ConnectedLineNum: %s\r\n" 03396 "ConnectedLineName: %s\r\n" 03397 "Account: %s\r\n" 03398 "State: %s\r\n" 03399 "%s" 03400 "Uniqueid: %s\r\n" 03401 "%s" 03402 "%s" 03403 "\r\n", 03404 c->name, 03405 S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"), 03406 S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"), 03407 S_COR(c->connected.id.number.valid, c->connected.id.number.str, "<unknown>"), 03408 S_COR(c->connected.id.name.valid, c->connected.id.name.str, "<unknown>"), 03409 c->accountcode, 03410 ast_state2str(c->_state), bridge, c->uniqueid, 03411 ast_str_buffer(str), idText); 03412 } 03413 03414 ast_channel_unlock(c); 03415 c = ast_channel_unref(c); 03416 03417 if (!all) { 03418 break; 03419 } 03420 } 03421 03422 if (iter) { 03423 ast_channel_iterator_destroy(iter); 03424 } 03425 03426 astman_append(s, 03427 "Event: StatusComplete\r\n" 03428 "%s" 03429 "Items: %d\r\n" 03430 "\r\n", idText, channels); 03431 03432 ast_free(str); 03433 03434 return 0; 03435 }
static int action_timeout | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4309 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(), and astman_send_error().
Referenced by __init_manager().
04310 { 04311 struct ast_channel *c; 04312 const char *name = astman_get_header(m, "Channel"); 04313 double timeout = atof(astman_get_header(m, "Timeout")); 04314 struct timeval when = { timeout, 0 }; 04315 04316 if (ast_strlen_zero(name)) { 04317 astman_send_error(s, m, "No channel specified"); 04318 return 0; 04319 } 04320 04321 if (!timeout || timeout < 0) { 04322 astman_send_error(s, m, "No timeout specified"); 04323 return 0; 04324 } 04325 04326 if (!(c = ast_channel_get_by_name(name))) { 04327 astman_send_error(s, m, "No such channel"); 04328 return 0; 04329 } 04330 04331 when.tv_usec = (timeout - when.tv_sec) * 1000000.0; 04332 04333 ast_channel_lock(c); 04334 ast_channel_setwhentohangup_tv(c, when); 04335 ast_channel_unlock(c); 04336 c = ast_channel_unref(c); 04337 04338 astman_send_ack(s, m, "Timeout Set"); 04339 04340 return 0; 04341 }
static int action_updateconfig | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2825 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_STATUS_FILEINVALID, FAILURE_ALLOCATION, FAILURE_APPEND, 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().
02826 { 02827 struct ast_config *cfg; 02828 const char *sfn = astman_get_header(m, "SrcFilename"); 02829 const char *dfn = astman_get_header(m, "DstFilename"); 02830 int res; 02831 const char *rld = astman_get_header(m, "Reload"); 02832 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02833 enum error_type result; 02834 02835 if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) { 02836 astman_send_error(s, m, "Filename not specified"); 02837 return 0; 02838 } 02839 if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) { 02840 astman_send_error(s, m, "Config file not found"); 02841 return 0; 02842 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02843 astman_send_error(s, m, "Config file has invalid format"); 02844 return 0; 02845 } 02846 result = handle_updates(s, m, cfg, dfn); 02847 if (!result) { 02848 ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */ 02849 res = ast_config_text_file_save(dfn, cfg, "Manager"); 02850 ast_config_destroy(cfg); 02851 if (res) { 02852 astman_send_error(s, m, "Save of config failed"); 02853 return 0; 02854 } 02855 astman_send_ack(s, m, NULL); 02856 if (!ast_strlen_zero(rld)) { 02857 if (ast_true(rld)) { 02858 rld = NULL; 02859 } 02860 ast_module_reload(rld); 02861 } 02862 } else { 02863 ast_config_destroy(cfg); 02864 switch(result) { 02865 case UNKNOWN_ACTION: 02866 astman_send_error(s, m, "Unknown action command"); 02867 break; 02868 case UNKNOWN_CATEGORY: 02869 astman_send_error(s, m, "Given category does not exist"); 02870 break; 02871 case UNSPECIFIED_CATEGORY: 02872 astman_send_error(s, m, "Category not specified"); 02873 break; 02874 case UNSPECIFIED_ARGUMENT: 02875 astman_send_error(s, m, "Problem with category, value, or line (if required)"); 02876 break; 02877 case FAILURE_ALLOCATION: 02878 astman_send_error(s, m, "Memory allocation failure, this should not happen"); 02879 break; 02880 case FAILURE_NEWCAT: 02881 astman_send_error(s, m, "Create category did not complete successfully"); 02882 break; 02883 case FAILURE_DELCAT: 02884 astman_send_error(s, m, "Delete category did not complete successfully"); 02885 break; 02886 case FAILURE_EMPTYCAT: 02887 astman_send_error(s, m, "Empty category did not complete successfully"); 02888 break; 02889 case FAILURE_UPDATE: 02890 astman_send_error(s, m, "Update did not complete successfully"); 02891 break; 02892 case FAILURE_DELETE: 02893 astman_send_error(s, m, "Delete did not complete successfully"); 02894 break; 02895 case FAILURE_APPEND: 02896 astman_send_error(s, m, "Append did not complete successfully"); 02897 break; 02898 } 02899 } 02900 return 0; 02901 }
static int action_userevent | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4426 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().
04427 { 04428 const char *event = astman_get_header(m, "UserEvent"); 04429 struct ast_str *body = ast_str_thread_get(&userevent_buf, 16); 04430 int x; 04431 04432 ast_str_reset(body); 04433 04434 for (x = 0; x < m->hdrcount; x++) { 04435 if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) { 04436 ast_str_append(&body, 0, "%s\r\n", m->headers[x]); 04437 } 04438 } 04439 04440 astman_send_ack(s, m, "Event Sent"); 04441 manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, ast_str_buffer(body)); 04442 return 0; 04443 }
static int action_waitevent | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2921 of file manager.c.
References advance_event(), ao2_lock, ao2_unlock, ast_debug, AST_PTHREADT_NULL, AST_RWLIST_NEXT, ast_strlen_zero(), ast_wait_for_input(), astman_append(), astman_get_header(), astman_send_response(), eventqent::category, eventqent::eventdata, mansession_session::fd, mansession_session::last_ev, mansession_session::managerid, mansession_session::needdestroy, mansession_session::readperm, mansession_session::send_events, mansession::session, mansession_session::sessiontimeout, and mansession_session::waiting_thread.
Referenced by __init_manager().
02922 { 02923 const char *timeouts = astman_get_header(m, "Timeout"); 02924 int timeout = -1; 02925 int x; 02926 int needexit = 0; 02927 const char *id = astman_get_header(m, "ActionID"); 02928 char idText[256]; 02929 02930 if (!ast_strlen_zero(id)) { 02931 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 02932 } else { 02933 idText[0] = '\0'; 02934 } 02935 02936 if (!ast_strlen_zero(timeouts)) { 02937 sscanf(timeouts, "%30i", &timeout); 02938 if (timeout < -1) { 02939 timeout = -1; 02940 } 02941 /* XXX maybe put an upper bound, or prevent the use of 0 ? */ 02942 } 02943 02944 ao2_lock(s->session); 02945 if (s->session->waiting_thread != AST_PTHREADT_NULL) { 02946 pthread_kill(s->session->waiting_thread, SIGURG); 02947 } 02948 02949 if (s->session->managerid) { /* AMI-over-HTTP session */ 02950 /* 02951 * Make sure the timeout is within the expire time of the session, 02952 * as the client will likely abort the request if it does not see 02953 * data coming after some amount of time. 02954 */ 02955 time_t now = time(NULL); 02956 int max = s->session->sessiontimeout - now - 10; 02957 02958 if (max < 0) { /* We are already late. Strange but possible. */ 02959 max = 0; 02960 } 02961 if (timeout < 0 || timeout > max) { 02962 timeout = max; 02963 } 02964 if (!s->session->send_events) { /* make sure we record events */ 02965 s->session->send_events = -1; 02966 } 02967 } 02968 ao2_unlock(s->session); 02969 02970 /* XXX should this go inside the lock ? */ 02971 s->session->waiting_thread = pthread_self(); /* let new events wake up this thread */ 02972 ast_debug(1, "Starting waiting for an event!\n"); 02973 02974 for (x = 0; x < timeout || timeout < 0; x++) { 02975 ao2_lock(s->session); 02976 if (AST_RWLIST_NEXT(s->session->last_ev, eq_next)) { 02977 needexit = 1; 02978 } 02979 /* We can have multiple HTTP session point to the same mansession entry. 02980 * The way we deal with it is not very nice: newcomers kick out the previous 02981 * HTTP session. XXX this needs to be improved. 02982 */ 02983 if (s->session->waiting_thread != pthread_self()) { 02984 needexit = 1; 02985 } 02986 if (s->session->needdestroy) { 02987 needexit = 1; 02988 } 02989 ao2_unlock(s->session); 02990 if (needexit) { 02991 break; 02992 } 02993 if (s->session->managerid == 0) { /* AMI session */ 02994 if (ast_wait_for_input(s->session->fd, 1000)) { 02995 break; 02996 } 02997 } else { /* HTTP session */ 02998 sleep(1); 02999 } 03000 } 03001 ast_debug(1, "Finished waiting for an event!\n"); 03002 03003 ao2_lock(s->session); 03004 if (s->session->waiting_thread == pthread_self()) { 03005 struct eventqent *eqe = s->session->last_ev; 03006 astman_send_response(s, m, "Success", "Waiting for Event completed."); 03007 while ((eqe = advance_event(eqe))) { 03008 if (((s->session->readperm & eqe->category) == eqe->category) && 03009 ((s->session->send_events & eqe->category) == eqe->category)) { 03010 astman_append(s, "%s", eqe->eventdata); 03011 } 03012 s->session->last_ev = eqe; 03013 } 03014 astman_append(s, 03015 "Event: WaitEventComplete\r\n" 03016 "%s" 03017 "\r\n", idText); 03018 s->session->waiting_thread = AST_PTHREADT_NULL; 03019 } else { 03020 ast_debug(1, "Abandoning event request!\n"); 03021 } 03022 ao2_unlock(s->session); 03023 03024 return 0; 03025 }
Definition at line 1787 of file manager.c.
References ast_atomic_fetchadd_int(), AST_RWLIST_NEXT, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, eventqent::next, and eventqent::usecount.
Referenced by action_waitevent(), and process_events().
01788 { 01789 struct eventqent *next; 01790 01791 AST_RWLIST_RDLOCK(&all_events); 01792 if ((next = AST_RWLIST_NEXT(e, eq_next))) { 01793 ast_atomic_fetchadd_int(&next->usecount, 1); 01794 ast_atomic_fetchadd_int(&e->usecount, -1); 01795 } 01796 AST_RWLIST_UNLOCK(&all_events); 01797 return next; 01798 }
static int aocmessage_get_unit_entry | ( | const struct message * | m, | |
struct ast_aoc_unit_entry * | entry, | |||
unsigned int | entry_num | |||
) | [static] |
Definition at line 3872 of file manager.c.
References ast_aoc_unit_entry::amount, ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_strlen_zero(), astman_get_header(), str, ast_aoc_unit_entry::type, ast_aoc_unit_entry::valid_amount, and ast_aoc_unit_entry::valid_type.
Referenced by action_aocmessage().
03873 { 03874 const char *unitamount; 03875 const char *unittype; 03876 struct ast_str *str = ast_str_alloca(32); 03877 03878 memset(entry, 0, sizeof(*entry)); 03879 03880 ast_str_set(&str, 0, "UnitAmount(%u)", entry_num); 03881 unitamount = astman_get_header(m, ast_str_buffer(str)); 03882 03883 ast_str_set(&str, 0, "UnitType(%u)", entry_num); 03884 unittype = astman_get_header(m, ast_str_buffer(str)); 03885 03886 if (!ast_strlen_zero(unitamount) && (sscanf(unitamount, "%30u", &entry->amount) == 1)) { 03887 entry->valid_amount = 1; 03888 } 03889 03890 if (!ast_strlen_zero(unittype) && sscanf(unittype, "%30u", &entry->type) == 1) { 03891 entry->valid_type = 1; 03892 } 03893 03894 return 0; 03895 }
static void append_channel_vars | ( | struct ast_str ** | pbuf, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 5209 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_channel_variable::isfunc, manager_event_funcbuf, manager_channel_variable::name, pbx_builtin_getvar_helper(), and var.
Referenced by __ast_manager_event_multichan().
05210 { 05211 struct manager_channel_variable *var; 05212 05213 AST_RWLIST_RDLOCK(&channelvars); 05214 AST_LIST_TRAVERSE(&channelvars, var, entry) { 05215 const char *val; 05216 struct ast_str *res; 05217 05218 if (var->isfunc) { 05219 res = ast_str_thread_get(&manager_event_funcbuf, 16); 05220 if (res && ast_func_read2(chan, var->name, &res, 0) == 0) { 05221 val = ast_str_buffer(res); 05222 } else { 05223 val = NULL; 05224 } 05225 } else { 05226 val = pbx_builtin_getvar_helper(chan, var->name); 05227 } 05228 ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", chan->name, var->name, val ? val : ""); 05229 } 05230 AST_RWLIST_UNLOCK(&channelvars); 05231 }
static int append_event | ( | const char * | str, | |
int | category | |||
) | [static] |
Definition at line 5183 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(), eventqent::category, eventqent::eventdata, eventqent::seq, eventqent::tv, and eventqent::usecount.
Referenced by __ast_manager_event_multichan(), and __init_manager().
05184 { 05185 struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str)); 05186 static int seq; /* sequence number */ 05187 05188 if (!tmp) { 05189 return -1; 05190 } 05191 05192 /* need to init all fields, because ast_malloc() does not */ 05193 tmp->usecount = 0; 05194 tmp->category = category; 05195 tmp->seq = ast_atomic_fetchadd_int(&seq, 1); 05196 tmp->tv = ast_tvnow(); 05197 AST_RWLIST_NEXT(tmp, eq_next) = NULL; 05198 strcpy(tmp->eventdata, str); 05199 05200 AST_RWLIST_WRLOCK(&all_events); 05201 AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next); 05202 AST_RWLIST_UNLOCK(&all_events); 05203 05204 return 0; 05205 }
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 1934 of file manager.c.
References action_find(), manager_action::active_count, ao2_lock, ao2_t_ref, ao2_unlock, ARRAY_LEN, ast_free, ast_strdup, astman_get_header(), mansession::f, manager_action::func, message::hdrcount, message::headers, mansession::hook, manager_action::registered, and mansession::session.
01935 { 01936 const char *action; 01937 int ret = 0; 01938 struct manager_action *act_found; 01939 struct mansession s = {.session = NULL, }; 01940 struct message m = { 0 }; 01941 char *dup_str; 01942 char *src; 01943 int x = 0; 01944 int curlen; 01945 01946 if (hook == NULL) { 01947 return -1; 01948 } 01949 01950 /* Create our own copy of the AMI action msg string. */ 01951 src = dup_str = ast_strdup(msg); 01952 if (!dup_str) { 01953 return -1; 01954 } 01955 01956 /* convert msg string to message struct */ 01957 curlen = strlen(src); 01958 for (x = 0; x < curlen; x++) { 01959 int cr; /* set if we have \r */ 01960 if (src[x] == '\r' && x+1 < curlen && src[x+1] == '\n') 01961 cr = 2; /* Found. Update length to include \r\n */ 01962 else if (src[x] == '\n') 01963 cr = 1; /* also accept \n only */ 01964 else 01965 continue; 01966 /* don't keep empty lines */ 01967 if (x && m.hdrcount < ARRAY_LEN(m.headers)) { 01968 /* ... but trim \r\n and terminate the header string */ 01969 src[x] = '\0'; 01970 m.headers[m.hdrcount++] = src; 01971 } 01972 x += cr; 01973 curlen -= x; /* remaining size */ 01974 src += x; /* update pointer */ 01975 x = -1; /* reset loop */ 01976 } 01977 01978 action = astman_get_header(&m, "Action"); 01979 if (strcasecmp(action, "login")) { 01980 act_found = action_find(action); 01981 if (act_found) { 01982 /* 01983 * we have to simulate a session for this action request 01984 * to be able to pass it down for processing 01985 * This is necessary to meet the previous design of manager.c 01986 */ 01987 s.hook = hook; 01988 s.f = (void*)1; /* set this to something so our request will make it through all functions that test it*/ 01989 01990 ao2_lock(act_found); 01991 if (act_found->registered && act_found->func) { 01992 ++act_found->active_count; 01993 ao2_unlock(act_found); 01994 ret = act_found->func(&s, &m); 01995 ao2_lock(act_found); 01996 --act_found->active_count; 01997 } else { 01998 ret = -1; 01999 } 02000 ao2_unlock(act_found); 02001 ao2_t_ref(act_found, -1, "done with found action object"); 02002 } 02003 } 02004 ast_free(dup_str); 02005 return ret; 02006 }
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 1257 of file manager.c.
References eventqent::next.
Referenced by get_perm().
01258 { 01259 const char *val = bigstr, *next; 01260 01261 do { 01262 if ((next = strchr(val, delim))) { 01263 if (!strncmp(val, smallstr, (next - val))) { 01264 return 1; 01265 } else { 01266 continue; 01267 } 01268 } else { 01269 return !strcmp(smallstr, val); 01270 } 01271 } while (*(val = (next + 1))); 01272 01273 return 0; 01274 }
int ast_manager_register2 | ( | const char * | action, | |
int | auth, | |||
int(*)(struct mansession *s, const struct message *m) | func, | |||
const char * | synopsis, | |||
const char * | description | |||
) |
register a new command with manager, including online help. This is the preferred way to register a manager command
Register a manager command with the manager interface.
Definition at line 5438 of file manager.c.
References manager_action::action, action_destroy(), ao2_alloc, ao2_t_ref, ast_free, ast_manager_register_struct(), AST_STATIC_DOC, ast_string_field_init, 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().
05439 { 05440 struct manager_action *cur; 05441 05442 cur = ao2_alloc(sizeof(*cur), action_destroy); 05443 if (!cur) { 05444 return -1; 05445 } 05446 if (ast_string_field_init(cur, 128)) { 05447 ao2_t_ref(cur, -1, "action object creation failed"); 05448 return -1; 05449 } 05450 05451 cur->action = action; 05452 cur->authority = auth; 05453 cur->func = func; 05454 #ifdef AST_XML_DOCS 05455 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 05456 char *tmpxml; 05457 05458 tmpxml = ast_xmldoc_build_synopsis("manager", action, NULL); 05459 ast_string_field_set(cur, synopsis, tmpxml); 05460 ast_free(tmpxml); 05461 05462 tmpxml = ast_xmldoc_build_syntax("manager", action, NULL); 05463 ast_string_field_set(cur, syntax, tmpxml); 05464 ast_free(tmpxml); 05465 05466 tmpxml = ast_xmldoc_build_description("manager", action, NULL); 05467 ast_string_field_set(cur, description, tmpxml); 05468 ast_free(tmpxml); 05469 05470 tmpxml = ast_xmldoc_build_seealso("manager", action, NULL); 05471 ast_string_field_set(cur, seealso, tmpxml); 05472 ast_free(tmpxml); 05473 05474 tmpxml = ast_xmldoc_build_arguments("manager", action, NULL); 05475 ast_string_field_set(cur, arguments, tmpxml); 05476 ast_free(tmpxml); 05477 05478 cur->docsrc = AST_XML_DOC; 05479 } else 05480 #endif 05481 { 05482 ast_string_field_set(cur, synopsis, synopsis); 05483 ast_string_field_set(cur, description, description); 05484 #ifdef AST_XML_DOCS 05485 cur->docsrc = AST_STATIC_DOC; 05486 #endif 05487 } 05488 if (ast_manager_register_struct(cur)) { 05489 ao2_t_ref(cur, -1, "action object registration failed"); 05490 return -1; 05491 } 05492 05493 ao2_t_ref(cur, -1, "action object registration successful"); 05494 return 0; 05495 }
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 1090 of file manager.c.
References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and manager_action::list.
01091 { 01092 AST_RWLIST_WRLOCK(&manager_hooks); 01093 AST_RWLIST_INSERT_TAIL(&manager_hooks, hook, list); 01094 AST_RWLIST_UNLOCK(&manager_hooks); 01095 }
static int ast_manager_register_struct | ( | struct manager_action * | act | ) | [static] |
Definition at line 5383 of file manager.c.
References manager_action::action, ao2_t_ref, ast_log(), AST_RWLIST_INSERT_AFTER, AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, LOG_WARNING, and manager_action::registered.
Referenced by ast_manager_register2().
05384 { 05385 struct manager_action *cur, *prev = NULL; 05386 05387 AST_RWLIST_WRLOCK(&actions); 05388 AST_RWLIST_TRAVERSE(&actions, cur, list) { 05389 int ret; 05390 05391 ret = strcasecmp(cur->action, act->action); 05392 if (ret == 0) { 05393 ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action); 05394 AST_RWLIST_UNLOCK(&actions); 05395 return -1; 05396 } 05397 if (ret > 0) { /* Insert these alphabetically */ 05398 prev = cur; 05399 break; 05400 } 05401 } 05402 05403 ao2_t_ref(act, +1, "action object added to list"); 05404 act->registered = 1; 05405 if (prev) { 05406 AST_RWLIST_INSERT_AFTER(&actions, prev, act, list); 05407 } else { 05408 AST_RWLIST_INSERT_HEAD(&actions, act, list); 05409 } 05410 05411 ast_verb(2, "Manager registered action %s\n", act->action); 05412 05413 AST_RWLIST_UNLOCK(&actions); 05414 05415 return 0; 05416 }
int ast_manager_unregister | ( | char * | action | ) |
Unregister a registered manager command.
action | Name of registered Action: |
Definition at line 5324 of file manager.c.
References manager_action::action, manager_action::active_count, ao2_lock, ao2_t_ref, ao2_unlock, ast_debug, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, and manager_action::registered.
Referenced by __unload_module(), astdb_shutdown(), data_shutdown(), features_shutdown(), manager_shutdown(), unload_module(), and unload_pbx().
05325 { 05326 struct manager_action *cur; 05327 05328 AST_RWLIST_WRLOCK(&actions); 05329 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) { 05330 if (!strcasecmp(action, cur->action)) { 05331 AST_RWLIST_REMOVE_CURRENT(list); 05332 break; 05333 } 05334 } 05335 AST_RWLIST_TRAVERSE_SAFE_END; 05336 AST_RWLIST_UNLOCK(&actions); 05337 05338 if (cur) { 05339 time_t now; 05340 05341 /* 05342 * We have removed the action object from the container so we 05343 * are no longer in a hurry. 05344 */ 05345 ao2_lock(cur); 05346 cur->registered = 0; 05347 ao2_unlock(cur); 05348 05349 /* 05350 * Wait up to 5 seconds for any active invocations to complete 05351 * before returning. We have to wait instead of blocking 05352 * because we may be waiting for ourself to complete. 05353 */ 05354 now = time(NULL); 05355 while (cur->active_count) { 05356 if (5 <= time(NULL) - now) { 05357 ast_debug(1, 05358 "Unregister manager action %s timed out waiting for %d active instances to complete\n", 05359 action, cur->active_count); 05360 break; 05361 } 05362 05363 sched_yield(); 05364 } 05365 05366 ao2_t_ref(cur, -1, "action object removed from list"); 05367 ast_verb(2, "Manager unregistered action %s\n", action); 05368 } 05369 05370 return 0; 05371 }
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 1098 of file manager.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and manager_action::list.
01099 { 01100 AST_RWLIST_WRLOCK(&manager_hooks); 01101 AST_RWLIST_REMOVE(&manager_hooks, hook, list); 01102 AST_RWLIST_UNLOCK(&manager_hooks); 01103 }
void astman_append | ( | struct mansession * | s, | |
const char * | fmt, | |||
... | ||||
) |
utility functions for creating AMI replies
Definition at line 2052 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_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_ping(), action_status(), action_waitevent(), ast_cli_netstats(), astman_append_json(), 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_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(), and session_do().
02053 { 02054 va_list ap; 02055 struct ast_str *buf; 02056 02057 if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) { 02058 return; 02059 } 02060 02061 va_start(ap, fmt); 02062 ast_str_set_va(&buf, 0, fmt, ap); 02063 va_end(ap); 02064 02065 if (s->f != NULL || s->session->f != NULL) { 02066 send_string(s, ast_str_buffer(buf)); 02067 } else { 02068 ast_verbose("fd == -1 in astman_append, should not happen\n"); 02069 } 02070 }
static void astman_append_json | ( | struct mansession * | s, | |
const char * | str | |||
) | [static] |
Definition at line 2622 of file manager.c.
References ast_alloca, astman_append(), and json_escape().
Referenced by action_getconfigjson().
02623 { 02624 char *buf; 02625 02626 buf = ast_alloca(2 * strlen(str) + 1); 02627 json_escape(buf, str); 02628 astman_append(s, "%s", buf); 02629 }
const char* astman_get_header | ( | const struct message * | m, | |
char * | var | |||
) |
Return the first matching variable from an array.
Get header from mananger transaction.
Definition at line 1854 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_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(), start_monitor_action(), and stop_monitor_action().
01855 { 01856 return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH); 01857 }
struct ast_variable* astman_get_variables | ( | const struct message * | m | ) | [read] |
Get a linked list of the Variable: headers.
Definition at line 1912 of file manager.c.
References message::hdrcount, message::headers, and man_do_variable_value().
Referenced by action_originate(), and manager_sipnotify().
01913 { 01914 int varlen; 01915 int x; 01916 struct ast_variable *head = NULL; 01917 01918 static const char var_hdr[] = "Variable:"; 01919 01920 /* Process all "Variable:" headers. */ 01921 varlen = strlen(var_hdr); 01922 for (x = 0; x < m->hdrcount; x++) { 01923 if (strncasecmp(var_hdr, m->headers[x], varlen)) { 01924 continue; 01925 } 01926 head = man_do_variable_value(head, m->headers[x] + varlen); 01927 } 01928 01929 return head; 01930 }
void astman_send_ack | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | msg | |||
) |
Send ack in manager transaction.
Definition at line 2119 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(), manager_sipnotify(), meetmemute(), start_monitor_action(), and stop_monitor_action().
02120 { 02121 astman_send_response_full(s, m, "Success", msg, NULL); 02122 }
void astman_send_error | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | error | |||
) |
Send error in manager transaction.
Definition at line 2114 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_message(), do_pause_or_unpause(), handle_parse_error(), 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_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().
02115 { 02116 astman_send_response_full(s, m, "Error", error, NULL); 02117 }
void astman_send_listack | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | msg, | |||
char * | listflag | |||
) |
Send ack in manager list transaction.
Definition at line 2129 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().
02130 { 02131 astman_send_response_full(s, m, "Success", msg, listflag); 02132 }
void astman_send_response | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | resp, | |||
char * | msg | |||
) |
Send response in manager transaction.
Definition at line 2109 of file manager.c.
References astman_send_response_full().
Referenced by action_logoff(), and action_waitevent().
02110 { 02111 astman_send_response_full(s, m, resp, msg, NULL); 02112 }
static void astman_send_response_full | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | resp, | |||
char * | msg, | |||
char * | listflag | |||
) | [static] |
Definition at line 2089 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().
02090 { 02091 const char *id = astman_get_header(m, "ActionID"); 02092 02093 astman_append(s, "Response: %s\r\n", resp); 02094 if (!ast_strlen_zero(id)) { 02095 astman_append(s, "ActionID: %s\r\n", id); 02096 } 02097 if (listflag) { 02098 astman_append(s, "EventList: %s\r\n", listflag); /* Start, complete, cancelled */ 02099 } 02100 if (msg == MSG_MOREDATA) { 02101 return; 02102 } else if (msg) { 02103 astman_append(s, "Message: %s\r\n\r\n", msg); 02104 } else { 02105 astman_append(s, "\r\n"); 02106 } 02107 }
static void astman_start_ack | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2124 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().
02125 { 02126 astman_send_response_full(s, m, "Success", MSG_MOREDATA, NULL); 02127 }
static int authenticate | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2406 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, ast_manager_user::blackfilters, mansession_session::challenge, get_manager_by_name_locked(), ast_manager_user::ha, len(), LOG_NOTICE, MD5Final(), MD5Init(), MD5Update(), ast_manager_user::readperm, mansession_session::readperm, report_auth_success(), report_failed_acl(), report_failed_challenge_response(), report_inval_password(), report_invalid_user(), S_OR, ast_manager_user::secret, mansession::session, mansession_session::sessionstart, mansession_session::sessionstart_tv, set_eventmask(), mansession_session::sin, mansession_session::username, mansession_session::whitefilters, ast_manager_user::whitefilters, ast_manager_user::writeperm, mansession_session::writeperm, ast_manager_user::writetimeout, and mansession_session::writetimeout.
Referenced by action_login().
02407 { 02408 const char *username = astman_get_header(m, "Username"); 02409 const char *password = astman_get_header(m, "Secret"); 02410 int error = -1; 02411 struct ast_manager_user *user = NULL; 02412 regex_t *regex_filter; 02413 struct ao2_iterator filter_iter; 02414 struct ast_sockaddr addr; 02415 02416 if (ast_strlen_zero(username)) { /* missing username */ 02417 return -1; 02418 } 02419 02420 /* locate user in locked state */ 02421 AST_RWLIST_WRLOCK(&users); 02422 02423 ast_sockaddr_from_sin(&addr, &s->session->sin); 02424 02425 if (!(user = get_manager_by_name_locked(username))) { 02426 report_invalid_user(s, username); 02427 ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02428 } else if (user->ha && !ast_apply_ha(user->ha, &addr)) { 02429 report_failed_acl(s, username); 02430 ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02431 } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) { 02432 const char *key = astman_get_header(m, "Key"); 02433 if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) { 02434 int x; 02435 int len = 0; 02436 char md5key[256] = ""; 02437 struct MD5Context md5; 02438 unsigned char digest[16]; 02439 02440 MD5Init(&md5); 02441 MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge)); 02442 MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret)); 02443 MD5Final(digest, &md5); 02444 for (x = 0; x < 16; x++) 02445 len += sprintf(md5key + len, "%2.2x", digest[x]); 02446 if (!strcmp(md5key, key)) { 02447 error = 0; 02448 } else { 02449 report_failed_challenge_response(s, key, md5key); 02450 } 02451 } else { 02452 ast_debug(1, "MD5 authentication is not possible. challenge: '%s'\n", 02453 S_OR(s->session->challenge, "")); 02454 } 02455 } else if (user->secret) { 02456 if (!strcmp(password, user->secret)) { 02457 error = 0; 02458 } else { 02459 report_inval_password(s, username); 02460 } 02461 } 02462 02463 if (error) { 02464 ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02465 AST_RWLIST_UNLOCK(&users); 02466 return -1; 02467 } 02468 02469 /* auth complete */ 02470 02471 /* All of the user parameters are copied to the session so that in the event 02472 * of a reload and a configuration change, the session parameters are not 02473 * changed. */ 02474 ast_copy_string(s->session->username, username, sizeof(s->session->username)); 02475 s->session->readperm = user->readperm; 02476 s->session->writeperm = user->writeperm; 02477 s->session->writetimeout = user->writetimeout; 02478 02479 filter_iter = ao2_iterator_init(user->whitefilters, 0); 02480 while ((regex_filter = ao2_iterator_next(&filter_iter))) { 02481 ao2_t_link(s->session->whitefilters, regex_filter, "add white user filter to session"); 02482 ao2_t_ref(regex_filter, -1, "remove iterator ref"); 02483 } 02484 ao2_iterator_destroy(&filter_iter); 02485 02486 filter_iter = ao2_iterator_init(user->blackfilters, 0); 02487 while ((regex_filter = ao2_iterator_next(&filter_iter))) { 02488 ao2_t_link(s->session->blackfilters, regex_filter, "add black user filter to session"); 02489 ao2_t_ref(regex_filter, -1, "remove iterator ref"); 02490 } 02491 ao2_iterator_destroy(&filter_iter); 02492 02493 s->session->sessionstart = time(NULL); 02494 s->session->sessionstart_tv = ast_tvnow(); 02495 set_eventmask(s, astman_get_header(m, "Events")); 02496 02497 report_auth_success(s); 02498 02499 AST_RWLIST_UNLOCK(&users); 02500 return 0; 02501 }
static const char* authority_to_str | ( | int | authority, | |
struct ast_str ** | res | |||
) | [static] |
Convert authority code to a list of options. Note that the EVENT_FLAG_ALL authority will always be returned.
Definition at line 1233 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(), action_login(), handle_showmancmd(), and handle_showmancmds().
01234 { 01235 int i; 01236 char *sep = ""; 01237 01238 ast_str_reset(*res); 01239 for (i = 0; i < ARRAY_LEN(perms) - 1; i++) { 01240 if (authority & perms[i].num) { 01241 ast_str_append(res, 0, "%s%s", sep, perms[i].label); 01242 sep = ","; 01243 } 01244 } 01245 01246 if (ast_str_strlen(*res) == 0) /* replace empty string with something sensible */ 01247 ast_str_append(res, 0, "<none>"); 01248 01249 return ast_str_buffer(*res); 01250 }
static int blackfilter_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 4357 of file manager.c.
References CMP_MATCH, and CMP_STOP.
Referenced by match_filter().
static struct mansession_session* build_mansession | ( | struct sockaddr_in | sin | ) | [static, read] |
Allocate manager session structure and add it to the list of sessions.
Definition at line 1374 of file manager.c.
References ao2_alloc, ao2_container_alloc, ao2_link, ao2_ref, AST_PTHREADT_NULL, mansession_session::blackfilters, mansession_session::fd, mansession_session::send_events, session_destructor(), sessions, mansession_session::sin, mansession_session::waiting_thread, mansession_session::whitefilters, and mansession_session::writetimeout.
Referenced by auth_http_callback(), generic_http_callback(), and session_do().
01375 { 01376 struct mansession_session *newsession; 01377 01378 if (!(newsession = ao2_alloc(sizeof(*newsession), session_destructor))) { 01379 return NULL; 01380 } 01381 01382 if (!(newsession->whitefilters = ao2_container_alloc(1, NULL, NULL))) { 01383 ao2_ref(newsession, -1); 01384 return NULL; 01385 } 01386 01387 if (!(newsession->blackfilters = ao2_container_alloc(1, NULL, NULL))) { 01388 ao2_ref(newsession, -1); /* session_destructor will cleanup the other filter */ 01389 return NULL; 01390 } 01391 01392 newsession->fd = -1; 01393 newsession->waiting_thread = AST_PTHREADT_NULL; 01394 newsession->writetimeout = 100; 01395 newsession->send_events = -1; 01396 newsession->sin = sin; 01397 01398 ao2_link(sessions, newsession); 01399 01400 return newsession; 01401 }
static int check_blacklist | ( | const char * | cmd | ) | [static] |
Definition at line 3674 of file manager.c.
References ARRAY_LEN, ast_strdupa, ast_strip(), ast_strlen_zero(), command_blacklist, match(), MAX_BLACKLIST_CMD_LEN, and words.
Referenced by action_command().
03675 { 03676 char *cmd_copy, *cur_cmd; 03677 char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, }; 03678 int i; 03679 03680 cmd_copy = ast_strdupa(cmd); 03681 for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) { 03682 cur_cmd = ast_strip(cur_cmd); 03683 if (ast_strlen_zero(cur_cmd)) { 03684 i--; 03685 continue; 03686 } 03687 03688 cmd_words[i] = cur_cmd; 03689 } 03690 03691 for (i = 0; i < ARRAY_LEN(command_blacklist); i++) { 03692 int j, match = 1; 03693 03694 for (j = 0; command_blacklist[i].words[j]; j++) { 03695 if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) { 03696 match = 0; 03697 break; 03698 } 03699 } 03700 03701 if (match) { 03702 return 1; 03703 } 03704 } 03705 03706 return 0; 03707 }
int check_manager_enabled | ( | void | ) |
Check if AMI is enabled.
Definition at line 1105 of file manager.c.
Referenced by handle_show_settings().
01106 { 01107 return manager_enabled; 01108 }
static int check_manager_session_inuse | ( | const char * | name | ) | [static] |
Definition at line 1417 of file manager.c.
References ao2_find, mansession_session::inuse, sessions, and unref_mansession().
Referenced by process_message().
01418 { 01419 struct mansession_session *session = ao2_find(sessions, (char *) name, 0); 01420 int inuse = 0; 01421 01422 if (session) { 01423 inuse = 1; 01424 unref_mansession(session); 01425 } 01426 return inuse; 01427 }
int check_webmanager_enabled | ( | void | ) |
Check if AMI/HTTP is enabled.
Definition at line 1110 of file manager.c.
Referenced by action_coresettings(), and handle_show_settings().
01111 { 01112 return (webmanager_enabled && manager_enabled); 01113 }
static void destroy_fast_originate_helper | ( | struct fast_originate_helper * | doomed | ) | [static] |
Definition at line 3811 of file manager.c.
References ast_free, ast_string_field_free_memory, ast_variables_destroy(), and fast_originate_helper::vars.
Referenced by action_originate(), and fast_originate().
03812 { 03813 ast_variables_destroy(doomed->vars); 03814 ast_string_field_free_memory(doomed); 03815 ast_free(doomed); 03816 }
static int do_message | ( | struct mansession * | s | ) | [static] |
Definition at line 4963 of file manager.c.
References ARRAY_LEN, ast_free, ast_inet_ntoa(), ast_log(), ast_strdup, ast_strlen_zero(), ast_verb, astman_send_error(), mansession_session::authenticated, mansession_session::authstart, errno, get_input(), handle_parse_error(), message::hdrcount, message::headers, mansession_session::inbuf, LOG_ERROR, mansession_lock(), mansession_unlock(), MESSAGE_LINE_TOO_LONG, MESSAGE_OKAY, mansession::parsing, process_events(), process_message(), mansession::session, and mansession_session::sin.
Referenced by session_do().
04964 { 04965 struct message m = { 0 }; 04966 char header_buf[sizeof(s->session->inbuf)] = { '\0' }; 04967 int res; 04968 int idx; 04969 int hdr_loss; 04970 time_t now; 04971 04972 hdr_loss = 0; 04973 for (;;) { 04974 /* Check if any events are pending and do them if needed */ 04975 if (process_events(s)) { 04976 res = -1; 04977 break; 04978 } 04979 res = get_input(s, header_buf); 04980 if (res == 0) { 04981 /* No input line received. */ 04982 if (!s->session->authenticated) { 04983 if (time(&now) == -1) { 04984 ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); 04985 res = -1; 04986 break; 04987 } 04988 04989 if (now - s->session->authstart > authtimeout) { 04990 if (displayconnects) { 04991 ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout); 04992 } 04993 res = -1; 04994 break; 04995 } 04996 } 04997 continue; 04998 } else if (res > 0) { 04999 /* Input line received. */ 05000 if (ast_strlen_zero(header_buf)) { 05001 if (hdr_loss) { 05002 mansession_lock(s); 05003 astman_send_error(s, &m, "Too many lines in message or allocation failure"); 05004 mansession_unlock(s); 05005 res = 0; 05006 } else { 05007 switch (s->parsing) { 05008 case MESSAGE_OKAY: 05009 res = process_message(s, &m) ? -1 : 0; 05010 break; 05011 case MESSAGE_LINE_TOO_LONG: 05012 handle_parse_error(s, &m, "Failed to parse message: line too long"); 05013 res = 0; 05014 break; 05015 } 05016 } 05017 break; 05018 } else if (m.hdrcount < ARRAY_LEN(m.headers)) { 05019 m.headers[m.hdrcount] = ast_strdup(header_buf); 05020 if (!m.headers[m.hdrcount]) { 05021 /* Allocation failure. */ 05022 hdr_loss = 1; 05023 } else { 05024 ++m.hdrcount; 05025 } 05026 } else { 05027 /* Too many lines in message. */ 05028 hdr_loss = 1; 05029 } 05030 } else { 05031 /* Input error. */ 05032 break; 05033 } 05034 } 05035 05036 /* Free AMI request headers. */ 05037 for (idx = 0; idx < m.hdrcount; ++idx) { 05038 ast_free((void *) m.headers[idx]); 05039 } 05040 return res; 05041 }
static void event_filter_destructor | ( | void * | obj | ) | [static] |
Definition at line 1337 of file manager.c.
Referenced by __init_manager().
static void* fast_originate | ( | void * | data | ) | [static] |
Definition at line 3818 of file manager.c.
References fast_originate_helper::account, fast_originate_helper::app, fast_originate_helper::appdata, AST_CHANNEL_NAME, ast_channel_unlock, 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, destroy_fast_originate_helper(), EVENT_FLAG_CALL, fast_originate_helper::exten, fast_originate_helper::format, fast_originate_helper::idtext, fast_originate_helper::priority, S_OR, fast_originate_helper::tech, fast_originate_helper::timeout, and fast_originate_helper::vars.
Referenced by action_originate().
03819 { 03820 struct fast_originate_helper *in = data; 03821 int res; 03822 int reason = 0; 03823 struct ast_channel *chan = NULL, *chans[1]; 03824 char requested_channel[AST_CHANNEL_NAME]; 03825 03826 if (!ast_strlen_zero(in->app)) { 03827 res = ast_pbx_outgoing_app(in->tech, in->format, (char *) in->data, 03828 in->timeout, in->app, in->appdata, &reason, 1, 03829 S_OR(in->cid_num, NULL), 03830 S_OR(in->cid_name, NULL), 03831 in->vars, in->account, &chan); 03832 } else { 03833 res = ast_pbx_outgoing_exten(in->tech, in->format, (char *) in->data, 03834 in->timeout, in->context, in->exten, in->priority, &reason, 1, 03835 S_OR(in->cid_num, NULL), 03836 S_OR(in->cid_name, NULL), 03837 in->vars, in->account, &chan); 03838 } 03839 /* Any vars memory was passed to the ast_pbx_outgoing_xxx() calls. */ 03840 in->vars = NULL; 03841 03842 if (!chan) { 03843 snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data); 03844 } 03845 /* Tell the manager what happened with the channel */ 03846 chans[0] = chan; 03847 ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans, 03848 "%s" 03849 "Response: %s\r\n" 03850 "Channel: %s\r\n" 03851 "Context: %s\r\n" 03852 "Exten: %s\r\n" 03853 "Reason: %d\r\n" 03854 "Uniqueid: %s\r\n" 03855 "CallerIDNum: %s\r\n" 03856 "CallerIDName: %s\r\n", 03857 in->idtext, res ? "Failure" : "Success", 03858 chan ? chan->name : requested_channel, in->context, in->exten, reason, 03859 chan ? chan->uniqueid : "<null>", 03860 S_OR(in->cid_num, "<unknown>"), 03861 S_OR(in->cid_name, "<unknown>") 03862 ); 03863 03864 /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */ 03865 if (chan) { 03866 ast_channel_unlock(chan); 03867 } 03868 destroy_fast_originate_helper(in); 03869 return NULL; 03870 }
static void free_channelvars | ( | void | ) | [static] |
Definition at line 7222 of file manager.c.
References ast_free, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and var.
Referenced by __init_manager(), and load_channelvars().
07223 { 07224 struct manager_channel_variable *var; 07225 AST_RWLIST_WRLOCK(&channelvars); 07226 while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) { 07227 ast_free(var); 07228 } 07229 AST_RWLIST_UNLOCK(&channelvars); 07230 }
static int function_capable_string_allowed_with_auths | ( | const char * | evaluating, | |
int | writepermlist | |||
) | [static] |
Checks to see if a string which can be used to evaluate functions should be rejected.
Definition at line 1197 of file manager.c.
References EVENT_FLAG_SYSTEM.
Referenced by action_getvar(), and action_status().
01198 { 01199 if (!(writepermlist & EVENT_FLAG_SYSTEM) 01200 && ( 01201 strstr(evaluating, "SHELL") || /* NoOp(${SHELL(rm -rf /)}) */ 01202 strstr(evaluating, "EVAL") /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ 01203 )) { 01204 return 0; 01205 } 01206 return 1; 01207 }
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 4848 of file manager.c.
References ao2_lock, ao2_unlock, ast_inet_ntoa(), ast_log(), AST_PTHREADT_NULL, ast_wait_for_input(), mansession_session::authenticated, mansession_session::authstart, errno, mansession_session::f, mansession_session::fd, mansession_session::inbuf, mansession_session::inlen, LOG_ERROR, LOG_WARNING, MESSAGE_LINE_TOO_LONG, mansession::parsing, mansession_session::pending_event, mansession::session, mansession_session::sin, ast_frame::src, and mansession_session::waiting_thread.
Referenced by do_message().
04849 { 04850 int res, x; 04851 int maxlen = sizeof(s->session->inbuf) - 1; 04852 char *src = s->session->inbuf; 04853 int timeout = -1; 04854 time_t now; 04855 04856 /* 04857 * Look for \r\n within the buffer. If found, copy to the output 04858 * buffer and return, trimming the \r\n (not used afterwards). 04859 */ 04860 for (x = 0; x < s->session->inlen; x++) { 04861 int cr; /* set if we have \r */ 04862 if (src[x] == '\r' && x+1 < s->session->inlen && src[x + 1] == '\n') { 04863 cr = 2; /* Found. Update length to include \r\n */ 04864 } else if (src[x] == '\n') { 04865 cr = 1; /* also accept \n only */ 04866 } else { 04867 continue; 04868 } 04869 memmove(output, src, x); /*... but trim \r\n */ 04870 output[x] = '\0'; /* terminate the string */ 04871 x += cr; /* number of bytes used */ 04872 s->session->inlen -= x; /* remaining size */ 04873 memmove(src, src + x, s->session->inlen); /* remove used bytes */ 04874 return 1; 04875 } 04876 if (s->session->inlen >= maxlen) { 04877 /* no crlf found, and buffer full - sorry, too long for us */ 04878 ast_log(LOG_WARNING, "Discarding message from %s. Line too long: %.25s...\n", ast_inet_ntoa(s->session->sin.sin_addr), src); 04879 s->session->inlen = 0; 04880 s->parsing = MESSAGE_LINE_TOO_LONG; 04881 } 04882 res = 0; 04883 while (res == 0) { 04884 /* calculate a timeout if we are not authenticated */ 04885 if (!s->session->authenticated) { 04886 if(time(&now) == -1) { 04887 ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); 04888 return -1; 04889 } 04890 04891 timeout = (authtimeout - (now - s->session->authstart)) * 1000; 04892 if (timeout < 0) { 04893 /* we have timed out */ 04894 return 0; 04895 } 04896 } 04897 04898 ao2_lock(s->session); 04899 if (s->session->pending_event) { 04900 s->session->pending_event = 0; 04901 ao2_unlock(s->session); 04902 return 0; 04903 } 04904 s->session->waiting_thread = pthread_self(); 04905 ao2_unlock(s->session); 04906 04907 res = ast_wait_for_input(s->session->fd, timeout); 04908 04909 ao2_lock(s->session); 04910 s->session->waiting_thread = AST_PTHREADT_NULL; 04911 ao2_unlock(s->session); 04912 } 04913 if (res < 0) { 04914 /* If we get a signal from some other thread (typically because 04915 * there are new events queued), return 0 to notify the caller. 04916 */ 04917 if (errno == EINTR || errno == EAGAIN) { 04918 return 0; 04919 } 04920 ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno)); 04921 return -1; 04922 } 04923 04924 ao2_lock(s->session); 04925 res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f); 04926 if (res < 1) { 04927 res = -1; /* error return */ 04928 } else { 04929 s->session->inlen += res; 04930 src[s->session->inlen] = '\0'; 04931 res = 0; 04932 } 04933 ao2_unlock(s->session); 04934 return res; 04935 }
static struct ast_manager_user* get_manager_by_name_locked | ( | const char * | name | ) | [static, read] |
lookup an entry in the list of registered users. must be called with the list lock held.
Definition at line 1434 of file manager.c.
References AST_RWLIST_TRAVERSE, ast_manager_user::list, and ast_manager_user::username.
Referenced by __init_manager(), auth_http_callback(), authenticate(), handle_showmanager(), and manager_displayconnects().
01435 { 01436 struct ast_manager_user *user = NULL; 01437 01438 AST_RWLIST_TRAVERSE(&users, user, list) { 01439 if (!strcasecmp(user->username, name)) { 01440 break; 01441 } 01442 } 01443 01444 return user; 01445 }
static int get_perm | ( | const char * | instr | ) | [static] |
Definition at line 1276 of file manager.c.
References ARRAY_LEN, ast_instring(), permalias::num, and perms.
Referenced by __init_manager(), and strings_to_mask().
static struct eventqent* grab_last | ( | void | ) | [static, read] |
Grab a reference to the last event, update usecount as needed. Can handle a NULL pointer.
Definition at line 1119 of file manager.c.
References ast_atomic_fetchadd_int(), AST_RWLIST_LAST, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and eventqent::usecount.
Referenced by auth_http_callback(), generic_http_callback(), and session_do().
01120 { 01121 struct eventqent *ret; 01122 01123 AST_RWLIST_WRLOCK(&all_events); 01124 ret = AST_RWLIST_LAST(&all_events); 01125 /* the list is never empty now, but may become so when 01126 * we optimize it in the future, so be prepared. 01127 */ 01128 if (ret) { 01129 ast_atomic_fetchadd_int(&ret->usecount, 1); 01130 } 01131 AST_RWLIST_UNLOCK(&all_events); 01132 return ret; 01133 }
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 1768 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.
01769 { 01770 switch (cmd) { 01771 case CLI_INIT: 01772 e->command = "manager reload"; 01773 e->usage = 01774 "Usage: manager reload\n" 01775 " Reloads the manager configuration.\n"; 01776 return NULL; 01777 case CLI_GENERATE: 01778 return NULL; 01779 } 01780 if (a->argc > 2) { 01781 return CLI_SHOWUSAGE; 01782 } 01783 reload_manager(); 01784 return CLI_SUCCESS; 01785 }
static char* handle_mandebug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1542 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, and ast_cli_entry::usage.
01543 { 01544 switch (cmd) { 01545 case CLI_INIT: 01546 e->command = "manager set debug [on|off]"; 01547 e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n"; 01548 return NULL; 01549 case CLI_GENERATE: 01550 return NULL; 01551 } 01552 01553 if (a->argc == 3) { 01554 ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off"); 01555 } else if (a->argc == 4) { 01556 if (!strcasecmp(a->argv[3], "on")) { 01557 manager_debug = 1; 01558 } else if (!strcasecmp(a->argv[3], "off")) { 01559 manager_debug = 0; 01560 } else { 01561 return CLI_SHOWUSAGE; 01562 } 01563 } 01564 return CLI_SUCCESS; 01565 }
static void handle_parse_error | ( | struct mansession * | s, | |
struct message * | m, | |||
char * | error | |||
) | [static] |
Definition at line 4946 of file manager.c.
References astman_send_error(), mansession_lock(), mansession_unlock(), MESSAGE_OKAY, and mansession::parsing.
Referenced by do_message().
04947 { 04948 mansession_lock(s); 04949 astman_send_error(s, m, error); 04950 s->parsing = MESSAGE_OKAY; 04951 mansession_unlock(s); 04952 }
static char* handle_showmanager | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1567 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, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_manager_user::displayconnects, ast_cli_args::fd, get_manager_by_name_locked(), ast_manager_user::ha, ast_cli_args::n, ast_cli_args::pos, ast_manager_user::readperm, ast_manager_user::secret, ast_cli_entry::usage, user_authority_to_str(), ast_manager_user::username, ast_cli_args::word, and ast_manager_user::writeperm.
01568 { 01569 struct ast_manager_user *user = NULL; 01570 int l, which; 01571 char *ret = NULL; 01572 struct ast_str *rauthority = ast_str_alloca(128); 01573 struct ast_str *wauthority = ast_str_alloca(128); 01574 01575 switch (cmd) { 01576 case CLI_INIT: 01577 e->command = "manager show user"; 01578 e->usage = 01579 " Usage: manager show user <user>\n" 01580 " Display all information related to the manager user specified.\n"; 01581 return NULL; 01582 case CLI_GENERATE: 01583 l = strlen(a->word); 01584 which = 0; 01585 if (a->pos != 3) { 01586 return NULL; 01587 } 01588 AST_RWLIST_RDLOCK(&users); 01589 AST_RWLIST_TRAVERSE(&users, user, list) { 01590 if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) { 01591 ret = ast_strdup(user->username); 01592 break; 01593 } 01594 } 01595 AST_RWLIST_UNLOCK(&users); 01596 return ret; 01597 } 01598 01599 if (a->argc != 4) { 01600 return CLI_SHOWUSAGE; 01601 } 01602 01603 AST_RWLIST_RDLOCK(&users); 01604 01605 if (!(user = get_manager_by_name_locked(a->argv[3]))) { 01606 ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]); 01607 AST_RWLIST_UNLOCK(&users); 01608 return CLI_SUCCESS; 01609 } 01610 01611 ast_cli(a->fd, "\n"); 01612 ast_cli(a->fd, 01613 " username: %s\n" 01614 " secret: %s\n" 01615 " acl: %s\n" 01616 " read perm: %s\n" 01617 " write perm: %s\n" 01618 "displayconnects: %s\n", 01619 (user->username ? user->username : "(N/A)"), 01620 (user->secret ? "<Set>" : "(N/A)"), 01621 (user->ha ? "yes" : "no"), 01622 user_authority_to_str(user->readperm, &rauthority), 01623 user_authority_to_str(user->writeperm, &wauthority), 01624 (user->displayconnects ? "yes" : "no")); 01625 01626 AST_RWLIST_UNLOCK(&users); 01627 01628 return CLI_SUCCESS; 01629 }
static char* handle_showmanagers | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1631 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 ast_manager_user::username.
01632 { 01633 struct ast_manager_user *user = NULL; 01634 int count_amu = 0; 01635 switch (cmd) { 01636 case CLI_INIT: 01637 e->command = "manager show users"; 01638 e->usage = 01639 "Usage: manager show users\n" 01640 " Prints a listing of all managers that are currently configured on that\n" 01641 " system.\n"; 01642 return NULL; 01643 case CLI_GENERATE: 01644 return NULL; 01645 } 01646 if (a->argc != 3) { 01647 return CLI_SHOWUSAGE; 01648 } 01649 01650 AST_RWLIST_RDLOCK(&users); 01651 01652 /* If there are no users, print out something along those lines */ 01653 if (AST_RWLIST_EMPTY(&users)) { 01654 ast_cli(a->fd, "There are no manager users.\n"); 01655 AST_RWLIST_UNLOCK(&users); 01656 return CLI_SUCCESS; 01657 } 01658 01659 ast_cli(a->fd, "\nusername\n--------\n"); 01660 01661 AST_RWLIST_TRAVERSE(&users, user, list) { 01662 ast_cli(a->fd, "%s\n", user->username); 01663 count_amu++; 01664 } 01665 01666 AST_RWLIST_UNLOCK(&users); 01667 01668 ast_cli(a->fd,"-------------------\n" 01669 "%d manager users configured.\n", count_amu); 01670 return CLI_SUCCESS; 01671 }
static char* handle_showmancmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1465 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, CLI_SUCCESS, 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.
01466 { 01467 struct manager_action *cur; 01468 struct ast_str *authority; 01469 int num, l, which; 01470 char *ret = NULL; 01471 #ifdef AST_XML_DOCS 01472 char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64]; 01473 #endif 01474 01475 switch (cmd) { 01476 case CLI_INIT: 01477 e->command = "manager show command"; 01478 e->usage = 01479 "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n" 01480 " Shows the detailed description for a specific Asterisk manager interface command.\n"; 01481 return NULL; 01482 case CLI_GENERATE: 01483 l = strlen(a->word); 01484 which = 0; 01485 AST_RWLIST_RDLOCK(&actions); 01486 AST_RWLIST_TRAVERSE(&actions, cur, list) { 01487 if (!strncasecmp(a->word, cur->action, l) && ++which > a->n) { 01488 ret = ast_strdup(cur->action); 01489 break; /* make sure we exit even if ast_strdup() returns NULL */ 01490 } 01491 } 01492 AST_RWLIST_UNLOCK(&actions); 01493 return ret; 01494 } 01495 authority = ast_str_alloca(80); 01496 if (a->argc < 4) { 01497 return CLI_SHOWUSAGE; 01498 } 01499 01500 #ifdef AST_XML_DOCS 01501 /* setup the titles */ 01502 term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01503 term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40); 01504 term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01505 term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40); 01506 term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 01507 #endif 01508 01509 AST_RWLIST_RDLOCK(&actions); 01510 AST_RWLIST_TRAVERSE(&actions, cur, list) { 01511 for (num = 3; num < a->argc; num++) { 01512 if (!strcasecmp(cur->action, a->argv[num])) { 01513 #ifdef AST_XML_DOCS 01514 if (cur->docsrc == AST_XML_DOC) { 01515 ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n", 01516 syntax_title, 01517 ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1), 01518 synopsis_title, 01519 ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1), 01520 description_title, 01521 ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1), 01522 arguments_title, 01523 ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1), 01524 seealso_title, 01525 ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1)); 01526 } else 01527 #endif 01528 { 01529 ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n", 01530 cur->action, cur->synopsis, 01531 authority_to_str(cur->authority, &authority), 01532 S_OR(cur->description, "")); 01533 } 01534 } 01535 } 01536 } 01537 AST_RWLIST_UNLOCK(&actions); 01538 01539 return CLI_SUCCESS; 01540 }
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 1674 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.
01675 { 01676 struct manager_action *cur; 01677 struct ast_str *authority; 01678 #define HSMC_FORMAT " %-15.15s %-15.15s %-55.55s\n" 01679 switch (cmd) { 01680 case CLI_INIT: 01681 e->command = "manager show commands"; 01682 e->usage = 01683 "Usage: manager show commands\n" 01684 " Prints a listing of all the available Asterisk manager interface commands.\n"; 01685 return NULL; 01686 case CLI_GENERATE: 01687 return NULL; 01688 } 01689 authority = ast_str_alloca(80); 01690 ast_cli(a->fd, HSMC_FORMAT, "Action", "Privilege", "Synopsis"); 01691 ast_cli(a->fd, HSMC_FORMAT, "------", "---------", "--------"); 01692 01693 AST_RWLIST_RDLOCK(&actions); 01694 AST_RWLIST_TRAVERSE(&actions, cur, list) { 01695 ast_cli(a->fd, HSMC_FORMAT, cur->action, authority_to_str(cur->authority, &authority), cur->synopsis); 01696 } 01697 AST_RWLIST_UNLOCK(&actions); 01698 01699 return CLI_SUCCESS; 01700 }
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 1703 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, mansession_session::fd, ast_cli_args::fd, HSMCONN_FORMAT1, HSMCONN_FORMAT2, mansession_session::inuse, mansession_session::readperm, sessions, mansession_session::sessionstart, mansession_session::sin, unref_mansession(), ast_cli_entry::usage, mansession_session::username, and mansession_session::writeperm.
01704 { 01705 struct mansession_session *session; 01706 time_t now = time(NULL); 01707 #define HSMCONN_FORMAT1 " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n" 01708 #define HSMCONN_FORMAT2 " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n" 01709 int count = 0; 01710 struct ao2_iterator i; 01711 01712 switch (cmd) { 01713 case CLI_INIT: 01714 e->command = "manager show connected"; 01715 e->usage = 01716 "Usage: manager show connected\n" 01717 " Prints a listing of the users that are currently connected to the\n" 01718 "Asterisk manager interface.\n"; 01719 return NULL; 01720 case CLI_GENERATE: 01721 return NULL; 01722 } 01723 01724 ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write"); 01725 01726 i = ao2_iterator_init(sessions, 0); 01727 while ((session = ao2_iterator_next(&i))) { 01728 ao2_lock(session); 01729 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); 01730 count++; 01731 ao2_unlock(session); 01732 unref_mansession(session); 01733 } 01734 ao2_iterator_destroy(&i); 01735 ast_cli(a->fd, "%d users connected.\n", count); 01736 01737 return CLI_SUCCESS; 01738 }
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 1742 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::eventdata, ast_cli_args::fd, ast_cli_entry::usage, and eventqent::usecount.
01743 { 01744 struct eventqent *s; 01745 switch (cmd) { 01746 case CLI_INIT: 01747 e->command = "manager show eventq"; 01748 e->usage = 01749 "Usage: manager show eventq\n" 01750 " Prints a listing of all events pending in the Asterisk manger\n" 01751 "event queue.\n"; 01752 return NULL; 01753 case CLI_GENERATE: 01754 return NULL; 01755 } 01756 AST_RWLIST_RDLOCK(&all_events); 01757 AST_RWLIST_TRAVERSE(&all_events, s, eq_next) { 01758 ast_cli(a->fd, "Usecount: %d\n", s->usecount); 01759 ast_cli(a->fd, "Category: %d\n", s->category); 01760 ast_cli(a->fd, "Event:\n%s", s->eventdata); 01761 } 01762 AST_RWLIST_UNLOCK(&all_events); 01763 01764 return CLI_SUCCESS; 01765 }
static enum error_type handle_updates | ( | struct mansession * | s, | |
const struct message * | m, | |||
struct ast_config * | cfg, | |||
const char * | dfn | |||
) | [static] |
Definition at line 2680 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(), eventqent::category, 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().
02681 { 02682 int x; 02683 char hdr[40]; 02684 const char *action, *cat, *var, *value, *match, *line; 02685 struct ast_category *category; 02686 struct ast_variable *v; 02687 struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16); 02688 enum error_type result = 0; 02689 02690 for (x = 0; x < 100000; x++) { /* 100000 = the max number of allowed updates + 1 */ 02691 unsigned int object = 0; 02692 02693 snprintf(hdr, sizeof(hdr), "Action-%06d", x); 02694 action = astman_get_header(m, hdr); 02695 if (ast_strlen_zero(action)) /* breaks the for loop if no action header */ 02696 break; /* this could cause problems if actions come in misnumbered */ 02697 02698 snprintf(hdr, sizeof(hdr), "Cat-%06d", x); 02699 cat = astman_get_header(m, hdr); 02700 if (ast_strlen_zero(cat)) { /* every action needs a category */ 02701 result = UNSPECIFIED_CATEGORY; 02702 break; 02703 } 02704 02705 snprintf(hdr, sizeof(hdr), "Var-%06d", x); 02706 var = astman_get_header(m, hdr); 02707 02708 snprintf(hdr, sizeof(hdr), "Value-%06d", x); 02709 value = astman_get_header(m, hdr); 02710 02711 if (!ast_strlen_zero(value) && *value == '>') { 02712 object = 1; 02713 value++; 02714 } 02715 02716 snprintf(hdr, sizeof(hdr), "Match-%06d", x); 02717 match = astman_get_header(m, hdr); 02718 02719 snprintf(hdr, sizeof(hdr), "Line-%06d", x); 02720 line = astman_get_header(m, hdr); 02721 02722 if (!strcasecmp(action, "newcat")) { 02723 if (ast_category_get(cfg,cat)) { /* check to make sure the cat doesn't */ 02724 result = FAILURE_NEWCAT; /* already exist */ 02725 break; 02726 } 02727 if (!(category = ast_category_new(cat, dfn, -1))) { 02728 result = FAILURE_ALLOCATION; 02729 break; 02730 } 02731 if (ast_strlen_zero(match)) { 02732 ast_category_append(cfg, category); 02733 } else { 02734 ast_category_insert(cfg, category, match); 02735 } 02736 } else if (!strcasecmp(action, "renamecat")) { 02737 if (ast_strlen_zero(value)) { 02738 result = UNSPECIFIED_ARGUMENT; 02739 break; 02740 } 02741 if (!(category = ast_category_get(cfg, cat))) { 02742 result = UNKNOWN_CATEGORY; 02743 break; 02744 } 02745 ast_category_rename(category, value); 02746 } else if (!strcasecmp(action, "delcat")) { 02747 if (ast_category_delete(cfg, cat)) { 02748 result = FAILURE_DELCAT; 02749 break; 02750 } 02751 } else if (!strcasecmp(action, "emptycat")) { 02752 if (ast_category_empty(cfg, cat)) { 02753 result = FAILURE_EMPTYCAT; 02754 break; 02755 } 02756 } else if (!strcasecmp(action, "update")) { 02757 if (ast_strlen_zero(var)) { 02758 result = UNSPECIFIED_ARGUMENT; 02759 break; 02760 } 02761 if (!(category = ast_category_get(cfg,cat))) { 02762 result = UNKNOWN_CATEGORY; 02763 break; 02764 } 02765 if (ast_variable_update(category, var, value, match, object)) { 02766 result = FAILURE_UPDATE; 02767 break; 02768 } 02769 } else if (!strcasecmp(action, "delete")) { 02770 if ((ast_strlen_zero(var) && ast_strlen_zero(line))) { 02771 result = UNSPECIFIED_ARGUMENT; 02772 break; 02773 } 02774 if (!(category = ast_category_get(cfg, cat))) { 02775 result = UNKNOWN_CATEGORY; 02776 break; 02777 } 02778 if (ast_variable_delete(category, var, match, line)) { 02779 result = FAILURE_DELETE; 02780 break; 02781 } 02782 } else if (!strcasecmp(action, "append")) { 02783 if (ast_strlen_zero(var)) { 02784 result = UNSPECIFIED_ARGUMENT; 02785 break; 02786 } 02787 if (!(category = ast_category_get(cfg, cat))) { 02788 result = UNKNOWN_CATEGORY; 02789 break; 02790 } 02791 if (!(v = ast_variable_new(var, value, dfn))) { 02792 result = FAILURE_ALLOCATION; 02793 break; 02794 } 02795 if (object || (match && !strcasecmp(match, "object"))) { 02796 v->object = 1; 02797 } 02798 ast_variable_append(category, v); 02799 } else if (!strcasecmp(action, "insert")) { 02800 if (ast_strlen_zero(var) || ast_strlen_zero(line)) { 02801 result = UNSPECIFIED_ARGUMENT; 02802 break; 02803 } 02804 if (!(category = ast_category_get(cfg, cat))) { 02805 result = UNKNOWN_CATEGORY; 02806 break; 02807 } 02808 if (!(v = ast_variable_new(var, value, dfn))) { 02809 result = FAILURE_ALLOCATION; 02810 break; 02811 } 02812 ast_variable_insert(category, v, line); 02813 } 02814 else { 02815 ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action); 02816 result = UNKNOWN_ACTION; 02817 break; 02818 } 02819 } 02820 ast_free(str1); 02821 ast_free(str2); 02822 return result; 02823 }
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 2602 of file manager.c.
Referenced by astman_append_json().
static struct ast_variable* man_do_variable_value | ( | struct ast_variable * | head, | |
const char * | hdr_val | |||
) | [static, read] |
Definition at line 1868 of file manager.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_skip_blanks(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_variable_new(), ast_variable::next, parse(), and var.
Referenced by astman_get_variables().
01869 { 01870 char *parse; 01871 AST_DECLARE_APP_ARGS(args, 01872 AST_APP_ARG(vars)[64]; 01873 ); 01874 01875 hdr_val = ast_skip_blanks(hdr_val); /* ignore leading spaces in the value */ 01876 parse = ast_strdupa(hdr_val); 01877 01878 /* Break the header value string into name=val pair items. */ 01879 AST_STANDARD_APP_ARGS(args, parse); 01880 if (args.argc) { 01881 int y; 01882 01883 /* Process each name=val pair item. */ 01884 for (y = 0; y < args.argc; y++) { 01885 struct ast_variable *cur; 01886 char *var; 01887 char *val; 01888 01889 if (!args.vars[y]) { 01890 continue; 01891 } 01892 var = val = args.vars[y]; 01893 strsep(&val, "="); 01894 01895 /* XXX We may wish to trim whitespace from the strings. */ 01896 if (!val || ast_strlen_zero(var)) { 01897 continue; 01898 } 01899 01900 /* Create new variable list node and prepend it to the list. */ 01901 cur = ast_variable_new(var, val, ""); 01902 if (cur) { 01903 cur->next = head; 01904 head = cur; 01905 } 01906 } 01907 } 01908 01909 return head; 01910 }
static int manager_displayconnects | ( | struct mansession_session * | session | ) | [static] |
Get displayconnects config option.
session | manager session to get parameter from. |
Definition at line 1451 of file manager.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_manager_user::displayconnects, get_manager_by_name_locked(), and mansession_session::username.
Referenced by action_login(), generic_http_callback(), purge_sessions(), and session_do().
01452 { 01453 struct ast_manager_user *user = NULL; 01454 int ret = 0; 01455 01456 AST_RWLIST_RDLOCK(&users); 01457 if ((user = get_manager_by_name_locked (session->username))) { 01458 ret = user->displayconnects; 01459 } 01460 AST_RWLIST_UNLOCK(&users); 01461 01462 return ret; 01463 }
static int manager_modulecheck | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4638 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().
04639 { 04640 int res; 04641 const char *module = astman_get_header(m, "Module"); 04642 const char *id = astman_get_header(m, "ActionID"); 04643 char idText[256]; 04644 #if !defined(LOW_MEMORY) 04645 const char *version; 04646 #endif 04647 char filename[PATH_MAX]; 04648 char *cut; 04649 04650 ast_copy_string(filename, module, sizeof(filename)); 04651 if ((cut = strchr(filename, '.'))) { 04652 *cut = '\0'; 04653 } else { 04654 cut = filename + strlen(filename); 04655 } 04656 snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".so"); 04657 ast_log(LOG_DEBUG, "**** ModuleCheck .so file %s\n", filename); 04658 res = ast_module_check(filename); 04659 if (!res) { 04660 astman_send_error(s, m, "Module not loaded"); 04661 return 0; 04662 } 04663 snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".c"); 04664 ast_log(LOG_DEBUG, "**** ModuleCheck .c file %s\n", filename); 04665 #if !defined(LOW_MEMORY) 04666 version = ast_file_version_find(filename); 04667 #endif 04668 04669 if (!ast_strlen_zero(id)) { 04670 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 04671 } else { 04672 idText[0] = '\0'; 04673 } 04674 astman_append(s, "Response: Success\r\n%s", idText); 04675 #if !defined(LOW_MEMORY) 04676 astman_append(s, "Version: %s\r\n\r\n", version ? version : ""); 04677 #endif 04678 return 0; 04679 }
static int manager_moduleload | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4681 of file manager.c.
References AST_FORCE_SOFT, ast_load_resource(), ast_module_reload(), ast_strlen_zero(), ast_unload_resource(), astman_get_header(), astman_send_ack(), and astman_send_error().
Referenced by __init_manager().
04682 { 04683 int res; 04684 const char *module = astman_get_header(m, "Module"); 04685 const char *loadtype = astman_get_header(m, "LoadType"); 04686 04687 if (!loadtype || strlen(loadtype) == 0) { 04688 astman_send_error(s, m, "Incomplete ModuleLoad action."); 04689 } 04690 if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0) { 04691 astman_send_error(s, m, "Need module name"); 04692 } 04693 04694 if (!strcasecmp(loadtype, "load")) { 04695 res = ast_load_resource(module); 04696 if (res) { 04697 astman_send_error(s, m, "Could not load module."); 04698 } else { 04699 astman_send_ack(s, m, "Module loaded."); 04700 } 04701 } else if (!strcasecmp(loadtype, "unload")) { 04702 res = ast_unload_resource(module, AST_FORCE_SOFT); 04703 if (res) { 04704 astman_send_error(s, m, "Could not unload module."); 04705 } else { 04706 astman_send_ack(s, m, "Module unloaded."); 04707 } 04708 } else if (!strcasecmp(loadtype, "reload")) { 04709 if (!ast_strlen_zero(module)) { 04710 res = ast_module_reload(module); 04711 if (res == 0) { 04712 astman_send_error(s, m, "No such module."); 04713 } else if (res == 1) { 04714 astman_send_error(s, m, "Module does not support reload action."); 04715 } else { 04716 astman_send_ack(s, m, "Module reloaded."); 04717 } 04718 } else { 04719 ast_module_reload(NULL); /* Reload all modules */ 04720 astman_send_ack(s, m, "All modules reloaded"); 04721 } 04722 } else 04723 astman_send_error(s, m, "Incomplete ModuleLoad action."); 04724 return 0; 04725 }
static int manager_state_cb | ( | char * | context, | |
char * | exten, | |||
int | state, | |||
void * | data | |||
) | [static] |
Definition at line 5373 of file manager.c.
References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.
Referenced by __init_manager().
05374 { 05375 /* Notify managers of change */ 05376 char hint[512]; 05377 ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten); 05378 05379 manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state); 05380 return 0; 05381 }
static int mansession_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1403 of file manager.c.
References CMP_MATCH, str, and mansession_session::username.
Referenced by __init_manager().
01404 { 01405 struct mansession_session *s = obj; 01406 char *str = arg; 01407 return !strcasecmp(s->username, str) ? CMP_MATCH : 0; 01408 }
static struct sockaddr_in* mansession_encode_sin_local | ( | const struct mansession * | s, | |
struct sockaddr_in * | sin_local | |||
) | [static, read] |
Definition at line 2169 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().
02171 { 02172 ast_sockaddr_to_sin(&s->tcptls_session->parent->local_address, 02173 sin_local); 02174 02175 return sin_local; 02176 }
static enum ast_security_event_transport_type mansession_get_transport | ( | const struct mansession * | s | ) | [static] |
Definition at line 2163 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().
02164 { 02165 return s->tcptls_session->parent->tls_cfg ? AST_SECURITY_EVENT_TRANSPORT_TLS : 02166 AST_SECURITY_EVENT_TRANSPORT_TCP; 02167 }
static void mansession_lock | ( | struct mansession * | s | ) | [static] |
Lock the 'mansession' structure.
Definition at line 2135 of file manager.c.
References ast_mutex_lock, and mansession::lock.
Referenced by action_challenge(), do_message(), handle_parse_error(), and process_message().
02136 { 02137 ast_mutex_lock(&s->lock); 02138 }
static void mansession_unlock | ( | struct mansession * | s | ) | [static] |
Unlock the 'mansession' structure.
Definition at line 2141 of file manager.c.
References ast_mutex_unlock, and mansession::lock.
Referenced by action_challenge(), do_message(), handle_parse_error(), and process_message().
02142 { 02143 ast_mutex_unlock(&s->lock); 02144 }
static int match_filter | ( | struct mansession * | s, | |
char * | eventdata | |||
) | [static] |
Definition at line 4372 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().
04373 { 04374 int result = 0; 04375 04376 ast_debug(3, "Examining event:\n%s\n", eventdata); 04377 if (!ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) { 04378 return 1; /* no filtering means match all */ 04379 } else if (ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) { 04380 /* white filters only: implied black all filter processed first, then white filters */ 04381 ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04382 } else if (!ao2_container_count(s->session->whitefilters) && ao2_container_count(s->session->blackfilters)) { 04383 /* black filters only: implied white all filter processed first, then black filters */ 04384 ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04385 } else { 04386 /* white and black filters: implied black all filter processed first, then white filters, and lastly black filters */ 04387 ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04388 if (result) { 04389 result = 0; 04390 ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04391 } 04392 } 04393 04394 return result; 04395 }
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 4402 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().
04403 { 04404 int ret = 0; 04405 04406 ao2_lock(s->session); 04407 if (s->session->f != NULL) { 04408 struct eventqent *eqe = s->session->last_ev; 04409 04410 while ((eqe = advance_event(eqe))) { 04411 if (!ret && s->session->authenticated && 04412 (s->session->readperm & eqe->category) == eqe->category && 04413 (s->session->send_events & eqe->category) == eqe->category) { 04414 if (match_filter(s, eqe->eventdata)) { 04415 if (send_string(s, eqe->eventdata) < 0) 04416 ret = -1; /* don't send more */ 04417 } 04418 } 04419 s->session->last_ev = eqe; 04420 } 04421 } 04422 ao2_unlock(s->session); 04423 return ret; 04424 }
static int process_message | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4740 of file manager.c.
References __astman_get_header(), manager_action::action, action_find(), manager_action::active_count, ao2_lock, ao2_t_ref, ao2_unlock, ast_debug, 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(), manager_action::registered, report_req_bad_format(), report_req_not_allowed(), report_session_limit(), mansession::session, and mansession_session::writeperm.
Referenced by auth_http_callback(), do_message(), and generic_http_callback().
04741 { 04742 int ret = 0; 04743 struct manager_action *act_found; 04744 const char *user; 04745 const char *action; 04746 04747 action = __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY); 04748 if (ast_strlen_zero(action)) { 04749 report_req_bad_format(s, "NONE"); 04750 mansession_lock(s); 04751 astman_send_error(s, m, "Missing action in request"); 04752 mansession_unlock(s); 04753 return 0; 04754 } 04755 04756 if (!s->session->authenticated 04757 && strcasecmp(action, "Login") 04758 && strcasecmp(action, "Logoff") 04759 && strcasecmp(action, "Challenge")) { 04760 if (!s->session->authenticated) { 04761 report_req_not_allowed(s, action); 04762 } 04763 mansession_lock(s); 04764 astman_send_error(s, m, "Permission denied"); 04765 mansession_unlock(s); 04766 return 0; 04767 } 04768 04769 if (!allowmultiplelogin 04770 && !s->session->authenticated 04771 && (!strcasecmp(action, "Login") 04772 || !strcasecmp(action, "Challenge"))) { 04773 user = astman_get_header(m, "Username"); 04774 04775 if (!ast_strlen_zero(user) && check_manager_session_inuse(user)) { 04776 report_session_limit(s); 04777 sleep(1); 04778 mansession_lock(s); 04779 astman_send_error(s, m, "Login Already In Use"); 04780 mansession_unlock(s); 04781 return -1; 04782 } 04783 } 04784 04785 act_found = action_find(action); 04786 if (act_found) { 04787 /* Found the requested AMI action. */ 04788 int acted = 0; 04789 04790 if ((s->session->writeperm & act_found->authority) 04791 || act_found->authority == 0) { 04792 /* We have the authority to execute the action. */ 04793 ao2_lock(act_found); 04794 if (act_found->registered && act_found->func) { 04795 ast_debug(1, "Running action '%s'\n", act_found->action); 04796 ++act_found->active_count; 04797 ao2_unlock(act_found); 04798 ret = act_found->func(s, m); 04799 acted = 1; 04800 ao2_lock(act_found); 04801 --act_found->active_count; 04802 } 04803 ao2_unlock(act_found); 04804 } 04805 if (!acted) { 04806 /* 04807 * We did not execute the action because access was denied, it 04808 * was no longer registered, or no action was really registered. 04809 * Complain about it and leave. 04810 */ 04811 report_req_not_allowed(s, action); 04812 mansession_lock(s); 04813 astman_send_error(s, m, "Permission denied"); 04814 mansession_unlock(s); 04815 } 04816 ao2_t_ref(act_found, -1, "done with found action object"); 04817 } else { 04818 char buf[512]; 04819 04820 report_req_bad_format(s, action); 04821 snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action); 04822 mansession_lock(s); 04823 astman_send_error(s, m, buf); 04824 mansession_unlock(s); 04825 } 04826 if (ret) { 04827 return ret; 04828 } 04829 /* Once done with our message, deliver any pending events unless the 04830 requester doesn't want them as part of this response. 04831 */ 04832 if (ast_strlen_zero(astman_get_header(m, "SuppressEvents"))) { 04833 return process_events(s); 04834 } else { 04835 return ret; 04836 } 04837 }
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 1139 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::tv, and eventqent::usecount.
Referenced by purge_old_stuff().
01140 { 01141 struct eventqent *ev; 01142 struct timeval now = ast_tvnow(); 01143 01144 AST_RWLIST_WRLOCK(&all_events); 01145 while ( (ev = AST_RWLIST_FIRST(&all_events)) && 01146 ev->usecount == 0 && AST_RWLIST_NEXT(ev, eq_next)) { 01147 AST_RWLIST_REMOVE_HEAD(&all_events, eq_next); 01148 ast_free(ev); 01149 } 01150 01151 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&all_events, ev, eq_next) { 01152 /* Never release the last event */ 01153 if (!AST_RWLIST_NEXT(ev, eq_next)) { 01154 break; 01155 } 01156 01157 /* 2.5 times whatever the HTTP timeout is (maximum 2.5 hours) is the maximum time that we will definitely cache an event */ 01158 if (ev->usecount == 0 && ast_tvdiff_sec(now, ev->tv) > (httptimeout > 3600 ? 3600 : httptimeout) * 2.5) { 01159 AST_RWLIST_REMOVE_CURRENT(eq_next); 01160 ast_free(ev); 01161 } 01162 } 01163 AST_RWLIST_TRAVERSE_SAFE_END; 01164 AST_RWLIST_UNLOCK(&all_events); 01165 }
static void purge_sessions | ( | int | n_max | ) | [static] |
remove at most n_max stale session from the list.
Definition at line 5150 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(), sessions, mansession_session::sessiontimeout, mansession_session::sin, unref_mansession(), mansession_session::username, and VERBOSITY_ATLEAST.
Referenced by purge_old_stuff().
05151 { 05152 struct mansession_session *session; 05153 time_t now = time(NULL); 05154 struct ao2_iterator i; 05155 05156 if (!sessions) { 05157 return; 05158 } 05159 05160 i = ao2_iterator_init(sessions, 0); 05161 while ((session = ao2_iterator_next(&i)) && n_max > 0) { 05162 ao2_lock(session); 05163 if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) { 05164 if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) { 05165 ast_verb(2, "HTTP Manager '%s' timed out from %s\n", 05166 session->username, ast_inet_ntoa(session->sin.sin_addr)); 05167 } 05168 ao2_unlock(session); 05169 session_destroy(session); 05170 n_max--; 05171 } else { 05172 ao2_unlock(session); 05173 unref_mansession(session); 05174 } 05175 } 05176 ao2_iterator_destroy(&i); 05177 }
static void report_auth_success | ( | const struct mansession * | s | ) | [static] |
Definition at line 2256 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().
02257 { 02258 struct sockaddr_in sin_local; 02259 char session_id[32]; 02260 struct ast_security_event_successful_auth successful_auth = { 02261 .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH, 02262 .common.version = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION, 02263 .common.service = "AMI", 02264 .common.account_id = s->session->username, 02265 .common.session_tv = &s->session->sessionstart_tv, 02266 .common.local_addr = { 02267 .sin = mansession_encode_sin_local(s, &sin_local), 02268 .transport = mansession_get_transport(s), 02269 }, 02270 .common.remote_addr = { 02271 .sin = &s->session->sin, 02272 .transport = mansession_get_transport(s), 02273 }, 02274 .common.session_id = session_id, 02275 }; 02276 02277 snprintf(session_id, sizeof(session_id), "%p", s->session); 02278 02279 ast_security_event_report(AST_SEC_EVT(&successful_auth)); 02280 }
static void report_failed_acl | ( | const struct mansession * | s, | |
const char * | username | |||
) | [static] |
Definition at line 2204 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().
02205 { 02206 struct sockaddr_in sin_local; 02207 char session_id[32]; 02208 struct ast_security_event_failed_acl failed_acl_event = { 02209 .common.event_type = AST_SECURITY_EVENT_FAILED_ACL, 02210 .common.version = AST_SECURITY_EVENT_FAILED_ACL_VERSION, 02211 .common.service = "AMI", 02212 .common.account_id = username, 02213 .common.session_tv = &s->session->sessionstart_tv, 02214 .common.local_addr = { 02215 .sin = mansession_encode_sin_local(s, &sin_local), 02216 .transport = mansession_get_transport(s), 02217 }, 02218 .common.remote_addr = { 02219 .sin = &s->session->sin, 02220 .transport = mansession_get_transport(s), 02221 }, 02222 .common.session_id = session_id, 02223 }; 02224 02225 snprintf(session_id, sizeof(session_id), "%p", s->session); 02226 02227 ast_security_event_report(AST_SEC_EVT(&failed_acl_event)); 02228 }
static void report_failed_challenge_response | ( | const struct mansession * | s, | |
const char * | response, | |||
const char * | expected_response | |||
) | [static] |
Definition at line 2342 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().
02344 { 02345 struct sockaddr_in sin_local; 02346 char session_id[32]; 02347 struct ast_security_event_chal_resp_failed chal_resp_failed = { 02348 .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED, 02349 .common.version = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION, 02350 .common.service = "AMI", 02351 .common.account_id = s->session->username, 02352 .common.session_tv = &s->session->sessionstart_tv, 02353 .common.local_addr = { 02354 .sin = mansession_encode_sin_local(s, &sin_local), 02355 .transport = mansession_get_transport(s), 02356 }, 02357 .common.remote_addr = { 02358 .sin = &s->session->sin, 02359 .transport = mansession_get_transport(s), 02360 }, 02361 .common.session_id = session_id, 02362 02363 .challenge = s->session->challenge, 02364 .response = response, 02365 .expected_response = expected_response, 02366 }; 02367 02368 snprintf(session_id, sizeof(session_id), "%p", s->session); 02369 02370 ast_security_event_report(AST_SEC_EVT(&chal_resp_failed)); 02371 }
static void report_inval_password | ( | const struct mansession * | s, | |
const char * | username | |||
) | [static] |
Definition at line 2230 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().
02231 { 02232 struct sockaddr_in sin_local; 02233 char session_id[32]; 02234 struct ast_security_event_inval_password inval_password = { 02235 .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD, 02236 .common.version = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION, 02237 .common.service = "AMI", 02238 .common.account_id = username, 02239 .common.session_tv = &s->session->sessionstart_tv, 02240 .common.local_addr = { 02241 .sin = mansession_encode_sin_local(s, &sin_local), 02242 .transport = mansession_get_transport(s), 02243 }, 02244 .common.remote_addr = { 02245 .sin = &s->session->sin, 02246 .transport = mansession_get_transport(s), 02247 }, 02248 .common.session_id = session_id, 02249 }; 02250 02251 snprintf(session_id, sizeof(session_id), "%p", s->session); 02252 02253 ast_security_event_report(AST_SEC_EVT(&inval_password)); 02254 }
static void report_invalid_user | ( | const struct mansession * | s, | |
const char * | username | |||
) | [static] |
Definition at line 2178 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().
02179 { 02180 struct sockaddr_in sin_local; 02181 char session_id[32]; 02182 struct ast_security_event_inval_acct_id inval_acct_id = { 02183 .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID, 02184 .common.version = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION, 02185 .common.service = "AMI", 02186 .common.account_id = username, 02187 .common.session_tv = &s->session->sessionstart_tv, 02188 .common.local_addr = { 02189 .sin = mansession_encode_sin_local(s, &sin_local), 02190 .transport = mansession_get_transport(s), 02191 }, 02192 .common.remote_addr = { 02193 .sin = &s->session->sin, 02194 .transport = mansession_get_transport(s), 02195 }, 02196 .common.session_id = session_id, 02197 }; 02198 02199 snprintf(session_id, sizeof(session_id), "%p", s); 02200 02201 ast_security_event_report(AST_SEC_EVT(&inval_acct_id)); 02202 }
static void report_req_bad_format | ( | const struct mansession * | s, | |
const char * | action | |||
) | [static] |
Definition at line 2312 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().
02313 { 02314 struct sockaddr_in sin_local; 02315 char session_id[32]; 02316 char request_type[64]; 02317 struct ast_security_event_req_bad_format req_bad_format = { 02318 .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT, 02319 .common.version = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION, 02320 .common.service = "AMI", 02321 .common.account_id = s->session->username, 02322 .common.session_tv = &s->session->sessionstart_tv, 02323 .common.local_addr = { 02324 .sin = mansession_encode_sin_local(s, &sin_local), 02325 .transport = mansession_get_transport(s), 02326 }, 02327 .common.remote_addr = { 02328 .sin = &s->session->sin, 02329 .transport = mansession_get_transport(s), 02330 }, 02331 .common.session_id = session_id, 02332 02333 .request_type = request_type, 02334 }; 02335 02336 snprintf(session_id, sizeof(session_id), "%p", s->session); 02337 snprintf(request_type, sizeof(request_type), "Action: %s", action); 02338 02339 ast_security_event_report(AST_SEC_EVT(&req_bad_format)); 02340 }
static void report_req_not_allowed | ( | const struct mansession * | s, | |
const char * | action | |||
) | [static] |
Definition at line 2282 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().
02283 { 02284 struct sockaddr_in sin_local; 02285 char session_id[32]; 02286 char request_type[64]; 02287 struct ast_security_event_req_not_allowed req_not_allowed = { 02288 .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED, 02289 .common.version = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION, 02290 .common.service = "AMI", 02291 .common.account_id = s->session->username, 02292 .common.session_tv = &s->session->sessionstart_tv, 02293 .common.local_addr = { 02294 .sin = mansession_encode_sin_local(s, &sin_local), 02295 .transport = mansession_get_transport(s), 02296 }, 02297 .common.remote_addr = { 02298 .sin = &s->session->sin, 02299 .transport = mansession_get_transport(s), 02300 }, 02301 .common.session_id = session_id, 02302 02303 .request_type = request_type, 02304 }; 02305 02306 snprintf(session_id, sizeof(session_id), "%p", s->session); 02307 snprintf(request_type, sizeof(request_type), "Action: %s", action); 02308 02309 ast_security_event_report(AST_SEC_EVT(&req_not_allowed)); 02310 }
static void report_session_limit | ( | const struct mansession * | s | ) | [static] |
Definition at line 2373 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().
02374 { 02375 struct sockaddr_in sin_local; 02376 char session_id[32]; 02377 struct ast_security_event_session_limit session_limit = { 02378 .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT, 02379 .common.version = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION, 02380 .common.service = "AMI", 02381 .common.account_id = s->session->username, 02382 .common.session_tv = &s->session->sessionstart_tv, 02383 .common.local_addr = { 02384 .sin = mansession_encode_sin_local(s, &sin_local), 02385 .transport = mansession_get_transport(s), 02386 }, 02387 .common.remote_addr = { 02388 .sin = &s->session->sin, 02389 .transport = mansession_get_transport(s), 02390 }, 02391 .common.session_id = session_id, 02392 }; 02393 02394 snprintf(session_id, sizeof(session_id), "%p", s->session); 02395 02396 ast_security_event_report(AST_SEC_EVT(&session_limit)); 02397 }
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 2013 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().
02014 { 02015 int res; 02016 FILE *f = s->f ? s->f : s->session->f; 02017 int fd = s->f ? s->fd : s->session->fd; 02018 02019 /* It's a result from one of the hook's action invocation */ 02020 if (s->hook) { 02021 /* 02022 * to send responses, we're using the same function 02023 * as for receiving events. We call the event "HookResponse" 02024 */ 02025 s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string); 02026 return 0; 02027 } 02028 02029 if ((res = ast_careful_fwrite(f, fd, string, strlen(string), s->session->writetimeout))) { 02030 s->write_error = 1; 02031 } 02032 02033 return res; 02034 }
static void session_destroy | ( | struct mansession_session * | s | ) | [static] |
Definition at line 1410 of file manager.c.
References ao2_unlink, sessions, and unref_mansession().
Referenced by auth_http_callback(), generic_http_callback(), purge_sessions(), and session_do().
01411 { 01412 unref_mansession(s); 01413 ao2_unlink(sessions, s); 01414 }
static void session_destructor | ( | void * | obj | ) | [static] |
Definition at line 1343 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, mansession_session::f, mansession_session::last_ev, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, eventqent::usecount, and mansession_session::whitefilters.
Referenced by build_mansession().
01344 { 01345 struct mansession_session *session = obj; 01346 struct eventqent *eqe = session->last_ev; 01347 struct ast_datastore *datastore; 01348 01349 /* Get rid of each of the data stores on the session */ 01350 while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) { 01351 /* Free the data store */ 01352 ast_datastore_free(datastore); 01353 } 01354 01355 if (session->f != NULL) { 01356 fclose(session->f); 01357 } 01358 if (eqe) { 01359 ast_atomic_fetchadd_int(&eqe->usecount, -1); 01360 } 01361 01362 if (session->whitefilters) { 01363 ao2_t_callback(session->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters"); 01364 ao2_t_ref(session->whitefilters, -1 , "decrement ref for white container, should be last one"); 01365 } 01366 01367 if (session->blackfilters) { 01368 ao2_t_callback(session->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters"); 01369 ao2_t_ref(session->blackfilters, -1 , "decrement ref for black container, should be last one"); 01370 } 01371 }
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 5051 of file manager.c.
References AMI_VERSION, ao2_lock, ao2_ref, ao2_unlock, ast_atomic_fetchadd_int(), ast_inet_ntoa(), AST_LIST_HEAD_INIT_NOLOCK, ast_log(), ast_mutex_destroy, ast_mutex_init, ast_sockaddr_to_sin, ast_verb, astman_append(), mansession_session::authenticated, mansession_session::authstart, block_sockets, build_mansession(), mansession_session::datastores, do_message(), errno, mansession::f, mansession_session::f, ast_tcptls_session_instance::f, mansession::fd, mansession_session::fd, ast_tcptls_session_instance::fd, ast_frame::flags, grab_last(), mansession_session::last_ev, mansession::lock, LOG_ERROR, LOG_WARNING, manager_displayconnects(), ast_tcptls_session_instance::remote_address, mansession::session, session_destroy(), mansession_session::sin, unauth_sessions, mansession_session::username, and mansession::write_error.
05052 { 05053 struct ast_tcptls_session_instance *ser = data; 05054 struct mansession_session *session; 05055 struct mansession s = { 05056 .tcptls_session = data, 05057 }; 05058 int flags; 05059 int res; 05060 struct sockaddr_in ser_remote_address_tmp; 05061 struct protoent *p; 05062 05063 if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) { 05064 fclose(ser->f); 05065 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05066 goto done; 05067 } 05068 05069 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 05070 session = build_mansession(ser_remote_address_tmp); 05071 05072 if (session == NULL) { 05073 fclose(ser->f); 05074 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05075 goto done; 05076 } 05077 05078 /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm. 05079 * This is necessary to prevent delays (caused by buffering) as we 05080 * write to the socket in bits and peices. */ 05081 p = getprotobyname("tcp"); 05082 if (p) { 05083 int arg = 1; 05084 if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) { 05085 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)); 05086 } 05087 } else { 05088 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"); 05089 } 05090 05091 flags = fcntl(ser->fd, F_GETFL); 05092 if (!block_sockets) { /* make sure socket is non-blocking */ 05093 flags |= O_NONBLOCK; 05094 } else { 05095 flags &= ~O_NONBLOCK; 05096 } 05097 fcntl(ser->fd, F_SETFL, flags); 05098 05099 ao2_lock(session); 05100 /* Hook to the tail of the event queue */ 05101 session->last_ev = grab_last(); 05102 05103 ast_mutex_init(&s.lock); 05104 05105 /* these fields duplicate those in the 'ser' structure */ 05106 session->fd = s.fd = ser->fd; 05107 session->f = s.f = ser->f; 05108 session->sin = ser_remote_address_tmp; 05109 s.session = session; 05110 05111 AST_LIST_HEAD_INIT_NOLOCK(&session->datastores); 05112 05113 if(time(&session->authstart) == -1) { 05114 ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno)); 05115 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05116 ao2_unlock(session); 05117 session_destroy(session); 05118 goto done; 05119 } 05120 ao2_unlock(session); 05121 05122 astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */ 05123 for (;;) { 05124 if ((res = do_message(&s)) < 0 || s.write_error) { 05125 break; 05126 } 05127 } 05128 /* session is over, explain why and terminate */ 05129 if (session->authenticated) { 05130 if (manager_displayconnects(session)) { 05131 ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 05132 } 05133 } else { 05134 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05135 if (displayconnects) { 05136 ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr)); 05137 } 05138 } 05139 05140 session_destroy(session); 05141 05142 ast_mutex_destroy(&s.lock); 05143 done: 05144 ao2_ref(ser, -1); 05145 ser = NULL; 05146 return NULL; 05147 }
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 2150 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().
02151 { 02152 int maskint = strings_to_mask(eventmask); 02153 02154 ao2_lock(s->session); 02155 if (maskint >= 0) { 02156 s->session->send_events = maskint; 02157 } 02158 ao2_unlock(s->session); 02159 02160 return maskint; 02161 }
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 1297 of file manager.c.
References ARRAY_LEN, ast_false(), ast_strlen_zero(), ast_true(), get_perm(), permalias::num, and perms.
Referenced by set_eventmask().
01298 { 01299 const char *p; 01300 01301 if (ast_strlen_zero(string)) { 01302 return -1; 01303 } 01304 01305 for (p = string; *p; p++) { 01306 if (*p < '0' || *p > '9') { 01307 break; 01308 } 01309 } 01310 if (!*p) { /* all digits */ 01311 return atoi(string); 01312 } 01313 if (ast_false(string)) { 01314 return 0; 01315 } 01316 if (ast_true(string)) { /* all permissions */ 01317 int x, ret = 0; 01318 for (x = 0; x < ARRAY_LEN(perms); x++) { 01319 ret |= perms[x].num; 01320 } 01321 return ret; 01322 } 01323 return get_perm(string); 01324 }
static struct mansession_session* unref_mansession | ( | struct mansession_session * | s | ) | [static, read] |
Unreference manager session object. If no more references, then go ahead and delete it.
Definition at line 1328 of file manager.c.
References ao2_ref, ast_log(), and LOG_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().
01329 { 01330 int refcount = ao2_ref(s, -1); 01331 if (manager_debug) { 01332 ast_log(LOG_DEBUG, "Mansession: %p refcount now %d\n", s, refcount - 1); 01333 } 01334 return s; 01335 }
static const char* user_authority_to_str | ( | int | authority, | |
struct ast_str ** | res | |||
) | [static] |
Convert authority code to a list of options for a user. This will only display those authority codes that have an explicit match on authority.
Definition at line 1211 of file manager.c.
References ARRAY_LEN, ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_strlen(), permalias::num, and perms.
Referenced by handle_showmanager().
01212 { 01213 int i; 01214 char *sep = ""; 01215 01216 ast_str_reset(*res); 01217 for (i = 0; i < ARRAY_LEN(perms) - 1; i++) { 01218 if ((authority & perms[i].num) == perms[i].num) { 01219 ast_str_append(res, 0, "%s%s", sep, perms[i].label); 01220 sep = ","; 01221 } 01222 } 01223 01224 if (ast_str_strlen(*res) == 0) /* replace empty string with something sensible */ 01225 ast_str_append(res, 0, "<none>"); 01226 01227 return ast_str_buffer(*res); 01228 }
static int whitefilter_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 4343 of file manager.c.
References CMP_MATCH, and CMP_STOP.
Referenced by match_filter().
int allowmultiplelogin = 1 [static] |
struct ast_threadstorage astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , } [static] |
Definition at line 2043 of file manager.c.
Referenced by astman_append().
int authtimeout [static] |
int block_sockets [static] |
Definition at line 913 of file manager.c.
Referenced by __init_manager(), handle_manager_show_settings(), and session_do().
int broken_events_action [static] |
struct { ... } command_blacklist[] [static] |
Referenced by check_blacklist().
const int DEFAULT_AUTHLIMIT = 50 [static] |
Default setting for authlimit
Definition at line 895 of file manager.c.
Referenced by reload_config().
const int DEFAULT_AUTHTIMEOUT = 30 [static] |
Default setting for authtimeout
Definition at line 894 of file manager.c.
Referenced by reload_config().
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_MANAGERDEBUG = 0 [static] |
const int DEFAULT_TIMESTAMPEVENTS = 0 [static] |
const int DEFAULT_WEBENABLED = 0 [static] |
int displayconnects [static] |
char global_realm[MAXHOSTNAMELEN] [static] |
Default realm
Definition at line 911 of file manager.c.
Referenced by __init_manager(), and auth_http_callback().
int httptimeout [static] |
char* manager_channelvars [static] |
int manager_debug = 0 [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] |
Definition at line 5234 of file manager.c.
Referenced by __ast_manager_event_multichan().
struct ast_threadstorage manager_event_funcbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_funcbuf , .custom_init = NULL , } [static] |
Definition at line 5207 of file manager.c.
Referenced by append_channel_vars().
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(), strings_to_mask(), and user_authority_to_str().
struct ao2_container* sessions = NULL [static] |
Definition at line 1023 of file manager.c.
Referenced by __ast_manager_event_multichan(), __init_manager(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), build_mansession(), check_manager_session_inuse(), find_session(), find_session_by_nonce(), handle_showmanconn(), manager_shutdown(), purge_sessions(), and session_destroy().
int timestampevents [static] |
int unauth_sessions = 0 [static] |
Definition at line 914 of file manager.c.
Referenced by action_login(), and session_do().
struct ast_threadstorage userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , } [static] |
Definition at line 2044 of file manager.c.
Referenced by action_userevent().
int webmanager_enabled = 0 [static] |