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 2052 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 1805 of file manager.c.
Referenced by astman_get_header().
| #define GET_HEADER_LAST_MATCH 1 |
Definition at line 1806 of file manager.c.
Referenced by __astman_get_header().
| #define GET_HEADER_SKIP_EMPTY 2 |
Definition at line 1807 of file manager.c.
Referenced by __astman_get_header(), and process_message().
| #define MANAGER_EVENT_BUF_INITSIZE 256 |
Definition at line 5240 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 2093 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 5242 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.
05244 { 05245 struct mansession_session *session; 05246 struct manager_custom_hook *hook; 05247 struct ast_str *auth = ast_str_alloca(80); 05248 const char *cat_str; 05249 va_list ap; 05250 struct timeval now; 05251 struct ast_str *buf; 05252 int i; 05253 05254 if (!(sessions && ao2_container_count(sessions)) && AST_RWLIST_EMPTY(&manager_hooks)) { 05255 return 0; 05256 } 05257 05258 if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) { 05259 return -1; 05260 } 05261 05262 cat_str = authority_to_str(category, &auth); 05263 ast_str_set(&buf, 0, 05264 "Event: %s\r\nPrivilege: %s\r\n", 05265 event, cat_str); 05266 05267 if (timestampevents) { 05268 now = ast_tvnow(); 05269 ast_str_append(&buf, 0, 05270 "Timestamp: %ld.%06lu\r\n", 05271 (long)now.tv_sec, (unsigned long) now.tv_usec); 05272 } 05273 if (manager_debug) { 05274 static int seq; 05275 ast_str_append(&buf, 0, 05276 "SequenceNumber: %d\r\n", 05277 ast_atomic_fetchadd_int(&seq, 1)); 05278 ast_str_append(&buf, 0, 05279 "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func); 05280 } 05281 05282 va_start(ap, fmt); 05283 ast_str_append_va(&buf, 0, fmt, ap); 05284 va_end(ap); 05285 for (i = 0; i < chancount; i++) { 05286 append_channel_vars(&buf, chans[i]); 05287 } 05288 05289 ast_str_append(&buf, 0, "\r\n"); 05290 05291 append_event(ast_str_buffer(buf), category); 05292 05293 /* Wake up any sleeping sessions */ 05294 if (sessions) { 05295 struct ao2_iterator i; 05296 i = ao2_iterator_init(sessions, 0); 05297 while ((session = ao2_iterator_next(&i))) { 05298 ao2_lock(session); 05299 if (session->waiting_thread != AST_PTHREADT_NULL) { 05300 pthread_kill(session->waiting_thread, SIGURG); 05301 } else { 05302 /* We have an event to process, but the mansession is 05303 * not waiting for it. We still need to indicate that there 05304 * is an event waiting so that get_input processes the pending 05305 * event instead of polling. 05306 */ 05307 session->pending_event = 1; 05308 } 05309 ao2_unlock(session); 05310 unref_mansession(session); 05311 } 05312 ao2_iterator_destroy(&i); 05313 } 05314 05315 if (!AST_RWLIST_EMPTY(&manager_hooks)) { 05316 AST_RWLIST_RDLOCK(&manager_hooks); 05317 AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) { 05318 hook->helper(category, event, ast_str_buffer(buf)); 05319 } 05320 AST_RWLIST_UNLOCK(&manager_hooks); 05321 } 05322 05323 return 0; 05324 }
| 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 1822 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().
01823 { 01824 int x, l = strlen(var); 01825 const char *result = ""; 01826 01827 if (!m) { 01828 return result; 01829 } 01830 01831 for (x = 0; x < m->hdrcount; x++) { 01832 const char *h = m->headers[x]; 01833 if (!strncasecmp(var, h, l) && h[l] == ':') { 01834 const char *value = h + l + 1; 01835 value = ast_skip_blanks(value); /* ignore leading spaces in the value */ 01836 /* found a potential candidate */ 01837 if ((mode & GET_HEADER_SKIP_EMPTY) && ast_strlen_zero(value)) { 01838 continue; /* not interesting */ 01839 } 01840 if (mode & GET_HEADER_LAST_MATCH) { 01841 result = value; /* record the last match so far */ 01842 } else { 01843 return value; 01844 } 01845 } 01846 } 01847 01848 return result; 01849 }
| 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 3902 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().
03903 { 03904 const char *channel = astman_get_header(m, "Channel"); 03905 const char *pchannel = astman_get_header(m, "ChannelPrefix"); 03906 const char *msgtype = astman_get_header(m, "MsgType"); 03907 const char *chargetype = astman_get_header(m, "ChargeType"); 03908 const char *currencyname = astman_get_header(m, "CurrencyName"); 03909 const char *currencyamount = astman_get_header(m, "CurrencyAmount"); 03910 const char *mult = astman_get_header(m, "CurrencyMultiplier"); 03911 const char *totaltype = astman_get_header(m, "TotalType"); 03912 const char *aocbillingid = astman_get_header(m, "AOCBillingId"); 03913 const char *association_id= astman_get_header(m, "ChargingAssociationId"); 03914 const char *association_num = astman_get_header(m, "ChargingAssociationNumber"); 03915 const char *association_plan = astman_get_header(m, "ChargingAssociationPlan"); 03916 03917 enum ast_aoc_type _msgtype; 03918 enum ast_aoc_charge_type _chargetype; 03919 enum ast_aoc_currency_multiplier _mult = AST_AOC_MULT_ONE; 03920 enum ast_aoc_total_type _totaltype = AST_AOC_TOTAL; 03921 enum ast_aoc_billing_id _billingid = AST_AOC_BILLING_NA; 03922 unsigned int _currencyamount = 0; 03923 int _association_id = 0; 03924 unsigned int _association_plan = 0; 03925 struct ast_channel *chan = NULL; 03926 03927 struct ast_aoc_decoded *decoded = NULL; 03928 struct ast_aoc_encoded *encoded = NULL; 03929 size_t encoded_size = 0; 03930 03931 if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) { 03932 astman_send_error(s, m, "Channel and PartialChannel are not specified. Specify at least one of these."); 03933 goto aocmessage_cleanup; 03934 } 03935 03936 if (!(chan = ast_channel_get_by_name(channel)) && !ast_strlen_zero(pchannel)) { 03937 chan = ast_channel_get_by_name_prefix(pchannel, strlen(pchannel)); 03938 } 03939 03940 if (!chan) { 03941 astman_send_error(s, m, "No such channel"); 03942 goto aocmessage_cleanup; 03943 } 03944 03945 if (ast_strlen_zero(msgtype) || (strcasecmp(msgtype, "d") && strcasecmp(msgtype, "e"))) { 03946 astman_send_error(s, m, "Invalid MsgType"); 03947 goto aocmessage_cleanup; 03948 } 03949 03950 if (ast_strlen_zero(chargetype)) { 03951 astman_send_error(s, m, "ChargeType not specified"); 03952 goto aocmessage_cleanup; 03953 } 03954 03955 _msgtype = strcasecmp(msgtype, "d") ? AST_AOC_E : AST_AOC_D; 03956 03957 if (!strcasecmp(chargetype, "NA")) { 03958 _chargetype = AST_AOC_CHARGE_NA; 03959 } else if (!strcasecmp(chargetype, "Free")) { 03960 _chargetype = AST_AOC_CHARGE_FREE; 03961 } else if (!strcasecmp(chargetype, "Currency")) { 03962 _chargetype = AST_AOC_CHARGE_CURRENCY; 03963 } else if (!strcasecmp(chargetype, "Unit")) { 03964 _chargetype = AST_AOC_CHARGE_UNIT; 03965 } else { 03966 astman_send_error(s, m, "Invalid ChargeType"); 03967 goto aocmessage_cleanup; 03968 } 03969 03970 if (_chargetype == AST_AOC_CHARGE_CURRENCY) { 03971 03972 if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u", &_currencyamount) != 1)) { 03973 astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency"); 03974 goto aocmessage_cleanup; 03975 } 03976 03977 if (ast_strlen_zero(mult)) { 03978 astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency."); 03979 goto aocmessage_cleanup; 03980 } else if (!strcasecmp(mult, "onethousandth")) { 03981 _mult = AST_AOC_MULT_ONETHOUSANDTH; 03982 } else if (!strcasecmp(mult, "onehundredth")) { 03983 _mult = AST_AOC_MULT_ONEHUNDREDTH; 03984 } else if (!strcasecmp(mult, "onetenth")) { 03985 _mult = AST_AOC_MULT_ONETENTH; 03986 } else if (!strcasecmp(mult, "one")) { 03987 _mult = AST_AOC_MULT_ONE; 03988 } else if (!strcasecmp(mult, "ten")) { 03989 _mult = AST_AOC_MULT_TEN; 03990 } else if (!strcasecmp(mult, "hundred")) { 03991 _mult = AST_AOC_MULT_HUNDRED; 03992 } else if (!strcasecmp(mult, "thousand")) { 03993 _mult = AST_AOC_MULT_THOUSAND; 03994 } else { 03995 astman_send_error(s, m, "Invalid ChargeMultiplier"); 03996 goto aocmessage_cleanup; 03997 } 03998 } 03999 04000 /* create decoded object and start setting values */ 04001 if (!(decoded = ast_aoc_create(_msgtype, _chargetype, 0))) { 04002 astman_send_error(s, m, "Message Creation Failed"); 04003 goto aocmessage_cleanup; 04004 } 04005 04006 if (_msgtype == AST_AOC_D) { 04007 if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype, "subtotal")) { 04008 _totaltype = AST_AOC_SUBTOTAL; 04009 } 04010 04011 if (ast_strlen_zero(aocbillingid)) { 04012 /* ignore this is optional */ 04013 } else if (!strcasecmp(aocbillingid, "Normal")) { 04014 _billingid = AST_AOC_BILLING_NORMAL; 04015 } else if (!strcasecmp(aocbillingid, "ReverseCharge")) { 04016 _billingid = AST_AOC_BILLING_REVERSE_CHARGE; 04017 } else if (!strcasecmp(aocbillingid, "CreditCard")) { 04018 _billingid = AST_AOC_BILLING_CREDIT_CARD; 04019 } else { 04020 astman_send_error(s, m, "Invalid AOC-D AOCBillingId"); 04021 goto aocmessage_cleanup; 04022 } 04023 } else { 04024 if (ast_strlen_zero(aocbillingid)) { 04025 /* ignore this is optional */ 04026 } else if (!strcasecmp(aocbillingid, "Normal")) { 04027 _billingid = AST_AOC_BILLING_NORMAL; 04028 } else if (!strcasecmp(aocbillingid, "ReverseCharge")) { 04029 _billingid = AST_AOC_BILLING_REVERSE_CHARGE; 04030 } else if (!strcasecmp(aocbillingid, "CreditCard")) { 04031 _billingid = AST_AOC_BILLING_CREDIT_CARD; 04032 } else if (!strcasecmp(aocbillingid, "CallFwdUnconditional")) { 04033 _billingid = AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL; 04034 } else if (!strcasecmp(aocbillingid, "CallFwdBusy")) { 04035 _billingid = AST_AOC_BILLING_CALL_FWD_BUSY; 04036 } else if (!strcasecmp(aocbillingid, "CallFwdNoReply")) { 04037 _billingid = AST_AOC_BILLING_CALL_FWD_NO_REPLY; 04038 } else if (!strcasecmp(aocbillingid, "CallDeflection")) { 04039 _billingid = AST_AOC_BILLING_CALL_DEFLECTION; 04040 } else if (!strcasecmp(aocbillingid, "CallTransfer")) { 04041 _billingid = AST_AOC_BILLING_CALL_TRANSFER; 04042 } else { 04043 astman_send_error(s, m, "Invalid AOC-E AOCBillingId"); 04044 goto aocmessage_cleanup; 04045 } 04046 04047 if (!ast_strlen_zero(association_id) && (sscanf(association_id, "%30d", &_association_id) != 1)) { 04048 astman_send_error(s, m, "Invalid ChargingAssociationId"); 04049 goto aocmessage_cleanup; 04050 } 04051 if (!ast_strlen_zero(association_plan) && (sscanf(association_plan, "%30u", &_association_plan) != 1)) { 04052 astman_send_error(s, m, "Invalid ChargingAssociationPlan"); 04053 goto aocmessage_cleanup; 04054 } 04055 04056 if (_association_id) { 04057 ast_aoc_set_association_id(decoded, _association_id); 04058 } else if (!ast_strlen_zero(association_num)) { 04059 ast_aoc_set_association_number(decoded, association_num, _association_plan); 04060 } 04061 } 04062 04063 if (_chargetype == AST_AOC_CHARGE_CURRENCY) { 04064 ast_aoc_set_currency_info(decoded, _currencyamount, _mult, ast_strlen_zero(currencyname) ? NULL : currencyname); 04065 } else if (_chargetype == AST_AOC_CHARGE_UNIT) { 04066 struct ast_aoc_unit_entry entry; 04067 int i; 04068 04069 /* multiple unit entries are possible, lets get them all */ 04070 for (i = 0; i < 32; i++) { 04071 if (aocmessage_get_unit_entry(m, &entry, i)) { 04072 break; /* that's the end then */ 04073 } 04074 04075 ast_aoc_add_unit_entry(decoded, entry.valid_amount, entry.amount, entry.valid_type, entry.type); 04076 } 04077 04078 /* at least one unit entry is required */ 04079 if (!i) { 04080 astman_send_error(s, m, "Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit"); 04081 goto aocmessage_cleanup; 04082 } 04083 04084 } 04085 04086 ast_aoc_set_billing_id(decoded, _billingid); 04087 ast_aoc_set_total_type(decoded, _totaltype); 04088 04089 04090 if ((encoded = ast_aoc_encode(decoded, &encoded_size, NULL)) && !ast_indicate_data(chan, AST_CONTROL_AOC, encoded, encoded_size)) { 04091 astman_send_ack(s, m, "AOC Message successfully queued on channel"); 04092 } else { 04093 astman_send_error(s, m, "Error encoding AOC message, could not queue onto channel"); 04094 } 04095 04096 aocmessage_cleanup: 04097 04098 ast_aoc_destroy_decoded(decoded); 04099 ast_aoc_destroy_encoded(encoded); 04100 04101 if (chan) { 04102 chan = ast_channel_unref(chan); 04103 } 04104 return 0; 04105 }
| static int action_atxfer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3630 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().
03631 { 03632 const char *name = astman_get_header(m, "Channel"); 03633 const char *exten = astman_get_header(m, "Exten"); 03634 const char *context = astman_get_header(m, "Context"); 03635 struct ast_channel *chan = NULL; 03636 struct ast_call_feature *atxfer_feature = NULL; 03637 char *feature_code = NULL; 03638 03639 if (ast_strlen_zero(name)) { 03640 astman_send_error(s, m, "No channel specified"); 03641 return 0; 03642 } 03643 if (ast_strlen_zero(exten)) { 03644 astman_send_error(s, m, "No extension specified"); 03645 return 0; 03646 } 03647 03648 if (!(atxfer_feature = ast_find_call_feature("atxfer"))) { 03649 astman_send_error(s, m, "No attended transfer feature found"); 03650 return 0; 03651 } 03652 03653 if (!(chan = ast_channel_get_by_name(name))) { 03654 astman_send_error(s, m, "Channel specified does not exist"); 03655 return 0; 03656 } 03657 03658 if (!ast_strlen_zero(context)) { 03659 pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context); 03660 } 03661 03662 for (feature_code = atxfer_feature->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 for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) { 03668 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code }; 03669 ast_queue_frame(chan, &f); 03670 } 03671 03672 chan = ast_channel_unref(chan); 03673 03674 astman_send_ack(s, m, "Atxfer successfully queued"); 03675 03676 return 0; 03677 }
| static int action_challenge | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3132 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().
03133 { 03134 const char *authtype = astman_get_header(m, "AuthType"); 03135 03136 if (!strcasecmp(authtype, "MD5")) { 03137 if (ast_strlen_zero(s->session->challenge)) { 03138 snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random()); 03139 } 03140 mansession_lock(s); 03141 astman_start_ack(s, m); 03142 astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge); 03143 mansession_unlock(s); 03144 } else { 03145 astman_send_error(s, m, "Must specify AuthType"); 03146 } 03147 return 0; 03148 }
| static int action_command | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Manager command "command" - execute CLI command.
Definition at line 3715 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().
03716 { 03717 const char *cmd = astman_get_header(m, "Command"); 03718 const char *id = astman_get_header(m, "ActionID"); 03719 char *buf = NULL, *final_buf = NULL; 03720 char template[] = "/tmp/ast-ami-XXXXXX"; /* template for temporary file */ 03721 int fd; 03722 off_t l; 03723 03724 if (ast_strlen_zero(cmd)) { 03725 astman_send_error(s, m, "No command provided"); 03726 return 0; 03727 } 03728 03729 if (check_blacklist(cmd)) { 03730 astman_send_error(s, m, "Command blacklisted"); 03731 return 0; 03732 } 03733 03734 if ((fd = mkstemp(template)) < 0) { 03735 ast_log(AST_LOG_WARNING, "Failed to create temporary file for command: %s\n", strerror(errno)); 03736 astman_send_error(s, m, "Command response construction error"); 03737 return 0; 03738 } 03739 03740 astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n"); 03741 if (!ast_strlen_zero(id)) { 03742 astman_append(s, "ActionID: %s\r\n", id); 03743 } 03744 /* FIXME: Wedge a ActionID response in here, waiting for later changes */ 03745 ast_cli_command(fd, cmd); /* XXX need to change this to use a FILE * */ 03746 /* Determine number of characters available */ 03747 if ((l = lseek(fd, 0, SEEK_END)) < 0) { 03748 ast_log(LOG_WARNING, "Failed to determine number of characters for command: %s\n", strerror(errno)); 03749 goto action_command_cleanup; 03750 } 03751 03752 /* This has a potential to overflow the stack. Hence, use the heap. */ 03753 buf = ast_malloc(l + 1); 03754 final_buf = ast_malloc(l + 1); 03755 03756 if (!buf || !final_buf) { 03757 ast_log(LOG_WARNING, "Failed to allocate memory for temporary buffer\n"); 03758 goto action_command_cleanup; 03759 } 03760 03761 if (lseek(fd, 0, SEEK_SET) < 0) { 03762 ast_log(LOG_WARNING, "Failed to set position on temporary file for command: %s\n", strerror(errno)); 03763 goto action_command_cleanup; 03764 } 03765 03766 if (read(fd, buf, l) < 0) { 03767 ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); 03768 goto action_command_cleanup; 03769 } 03770 03771 buf[l] = '\0'; 03772 term_strip(final_buf, buf, l); 03773 final_buf[l] = '\0'; 03774 astman_append(s, "%s", final_buf); 03775 03776 action_command_cleanup: 03777 03778 close(fd); 03779 unlink(template); 03780 astman_append(s, "--END COMMAND--\r\n\r\n"); 03781 03782 ast_free(buf); 03783 ast_free(final_buf); 03784 03785 return 0; 03786 }
| static int action_coresettings | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show PBX core settings information.
Definition at line 4451 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().
04452 { 04453 const char *actionid = astman_get_header(m, "ActionID"); 04454 char idText[150]; 04455 04456 if (!ast_strlen_zero(actionid)) { 04457 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04458 } else { 04459 idText[0] = '\0'; 04460 } 04461 04462 astman_append(s, "Response: Success\r\n" 04463 "%s" 04464 "AMIversion: %s\r\n" 04465 "AsteriskVersion: %s\r\n" 04466 "SystemName: %s\r\n" 04467 "CoreMaxCalls: %d\r\n" 04468 "CoreMaxLoadAvg: %f\r\n" 04469 "CoreRunUser: %s\r\n" 04470 "CoreRunGroup: %s\r\n" 04471 "CoreMaxFilehandles: %d\r\n" 04472 "CoreRealTimeEnabled: %s\r\n" 04473 "CoreCDRenabled: %s\r\n" 04474 "CoreHTTPenabled: %s\r\n" 04475 "\r\n", 04476 idText, 04477 AMI_VERSION, 04478 ast_get_version(), 04479 ast_config_AST_SYSTEM_NAME, 04480 option_maxcalls, 04481 option_maxload, 04482 ast_config_AST_RUN_USER, 04483 ast_config_AST_RUN_GROUP, 04484 option_maxfiles, 04485 AST_CLI_YESNO(ast_realtime_enabled()), 04486 AST_CLI_YESNO(check_cdr_enabled()), 04487 AST_CLI_YESNO(check_webmanager_enabled()) 04488 ); 04489 return 0; 04490 }
| 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 4560 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().
04561 { 04562 const char *actionid = astman_get_header(m, "ActionID"); 04563 char idText[256]; 04564 struct ast_channel *c = NULL; 04565 int numchans = 0; 04566 int duration, durh, durm, durs; 04567 struct ast_channel_iterator *iter; 04568 04569 if (!ast_strlen_zero(actionid)) { 04570 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04571 } else { 04572 idText[0] = '\0'; 04573 } 04574 04575 if (!(iter = ast_channel_iterator_all_new())) { 04576 astman_send_error(s, m, "Memory Allocation Failure"); 04577 return 1; 04578 } 04579 04580 astman_send_listack(s, m, "Channels will follow", "start"); 04581 04582 for (; (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) { 04583 struct ast_channel *bc; 04584 char durbuf[10] = ""; 04585 04586 ast_channel_lock(c); 04587 04588 bc = ast_bridged_channel(c); 04589 if (c->cdr && !ast_tvzero(c->cdr->start)) { 04590 duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000); 04591 durh = duration / 3600; 04592 durm = (duration % 3600) / 60; 04593 durs = duration % 60; 04594 snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs); 04595 } 04596 04597 astman_append(s, 04598 "Event: CoreShowChannel\r\n" 04599 "%s" 04600 "Channel: %s\r\n" 04601 "UniqueID: %s\r\n" 04602 "Context: %s\r\n" 04603 "Extension: %s\r\n" 04604 "Priority: %d\r\n" 04605 "ChannelState: %d\r\n" 04606 "ChannelStateDesc: %s\r\n" 04607 "Application: %s\r\n" 04608 "ApplicationData: %s\r\n" 04609 "CallerIDnum: %s\r\n" 04610 "CallerIDname: %s\r\n" 04611 "ConnectedLineNum: %s\r\n" 04612 "ConnectedLineName: %s\r\n" 04613 "Duration: %s\r\n" 04614 "AccountCode: %s\r\n" 04615 "BridgedChannel: %s\r\n" 04616 "BridgedUniqueID: %s\r\n" 04617 "\r\n", idText, c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state, 04618 ast_state2str(c->_state), c->appl ? c->appl : "", c->data ? S_OR(c->data, "") : "", 04619 S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""), 04620 S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""), 04621 S_COR(c->connected.id.number.valid, c->connected.id.number.str, ""), 04622 S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""), 04623 durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : ""); 04624 04625 ast_channel_unlock(c); 04626 04627 numchans++; 04628 } 04629 04630 astman_append(s, 04631 "Event: CoreShowChannelsComplete\r\n" 04632 "EventList: Complete\r\n" 04633 "ListItems: %d\r\n" 04634 "%s" 04635 "\r\n", numchans, idText); 04636 04637 ast_channel_iterator_destroy(iter); 04638 04639 return 0; 04640 }
| static int action_corestatus | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show PBX core status information.
Definition at line 4493 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().
04494 { 04495 const char *actionid = astman_get_header(m, "ActionID"); 04496 char idText[150]; 04497 char startuptime[150], startupdate[150]; 04498 char reloadtime[150], reloaddate[150]; 04499 struct ast_tm tm; 04500 04501 if (!ast_strlen_zero(actionid)) { 04502 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04503 } else { 04504 idText[0] = '\0'; 04505 } 04506 04507 ast_localtime(&ast_startuptime, &tm, NULL); 04508 ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm); 04509 ast_strftime(startupdate, sizeof(startupdate), "%Y-%m-%d", &tm); 04510 ast_localtime(&ast_lastreloadtime, &tm, NULL); 04511 ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm); 04512 ast_strftime(reloaddate, sizeof(reloaddate), "%Y-%m-%d", &tm); 04513 04514 astman_append(s, "Response: Success\r\n" 04515 "%s" 04516 "CoreStartupDate: %s\r\n" 04517 "CoreStartupTime: %s\r\n" 04518 "CoreReloadDate: %s\r\n" 04519 "CoreReloadTime: %s\r\n" 04520 "CoreCurrentCalls: %d\r\n" 04521 "\r\n", 04522 idText, 04523 startupdate, 04524 startuptime, 04525 reloaddate, 04526 reloadtime, 04527 ast_active_channels() 04528 ); 04529 return 0; 04530 }
| static int action_createconfig | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2908 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().
02909 { 02910 int fd; 02911 const char *fn = astman_get_header(m, "Filename"); 02912 struct ast_str *filepath = ast_str_alloca(PATH_MAX); 02913 ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR); 02914 ast_str_append(&filepath, 0, "%s", fn); 02915 02916 if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) { 02917 close(fd); 02918 astman_send_ack(s, m, "New configuration file created successfully"); 02919 } else { 02920 astman_send_error(s, m, strerror(errno)); 02921 } 02922 02923 return 0; 02924 }
| static void action_destroy | ( | void * | obj | ) | [static] |
Definition at line 5431 of file manager.c.
References ast_string_field_free_memory.
Referenced by ast_manager_register2().
05432 { 05433 struct manager_action *doomed = obj; 05434 05435 if (doomed->synopsis) { 05436 /* The string fields were initialized. */ 05437 ast_string_field_free_memory(doomed); 05438 } 05439 }
| static int action_events | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3051 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().
03052 { 03053 const char *mask = astman_get_header(m, "EventMask"); 03054 int res, x; 03055 const char *id = astman_get_header(m, "ActionID"); 03056 char id_text[256]; 03057 03058 if (!ast_strlen_zero(id)) { 03059 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id); 03060 } else { 03061 id_text[0] = '\0'; 03062 } 03063 03064 res = set_eventmask(s, mask); 03065 if (broken_events_action) { 03066 /* if this option is set we should not return a response on 03067 * error, or when all events are set */ 03068 03069 if (res > 0) { 03070 for (x = 0; x < ARRAY_LEN(perms); x++) { 03071 if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) { 03072 return 0; 03073 } 03074 } 03075 astman_append(s, "Response: Success\r\n%s" 03076 "Events: On\r\n\r\n", id_text); 03077 } else if (res == 0) 03078 astman_append(s, "Response: Success\r\n%s" 03079 "Events: Off\r\n\r\n", id_text); 03080 return 0; 03081 } 03082 03083 if (res > 0) 03084 astman_append(s, "Response: Success\r\n%s" 03085 "Events: On\r\n\r\n", id_text); 03086 else if (res == 0) 03087 astman_append(s, "Response: Success\r\n%s" 03088 "Events: Off\r\n\r\n", id_text); 03089 else 03090 astman_send_error(s, m, "Invalid event mask"); 03091 03092 return 0; 03093 }
| static int action_extensionstate | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4289 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().
04290 { 04291 const char *exten = astman_get_header(m, "Exten"); 04292 const char *context = astman_get_header(m, "Context"); 04293 char hint[256] = ""; 04294 int status; 04295 if (ast_strlen_zero(exten)) { 04296 astman_send_error(s, m, "Extension not specified"); 04297 return 0; 04298 } 04299 if (ast_strlen_zero(context)) { 04300 context = "default"; 04301 } 04302 status = ast_extension_state(NULL, context, exten); 04303 ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten); 04304 astman_start_ack(s, m); 04305 astman_append(s, "Message: Extension Status\r\n" 04306 "Exten: %s\r\n" 04307 "Context: %s\r\n" 04308 "Hint: %s\r\n" 04309 "Status: %d\r\n\r\n", 04310 exten, context, hint, status); 04311 return 0; 04312 }
| 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 2526 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().
02527 { 02528 struct ast_config *cfg; 02529 const char *fn = astman_get_header(m, "Filename"); 02530 const char *category = astman_get_header(m, "Category"); 02531 int catcount = 0; 02532 int lineno = 0; 02533 char *cur_category = NULL; 02534 struct ast_variable *v; 02535 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02536 02537 if (ast_strlen_zero(fn)) { 02538 astman_send_error(s, m, "Filename not specified"); 02539 return 0; 02540 } 02541 cfg = ast_config_load2(fn, "manager", config_flags); 02542 if (cfg == CONFIG_STATUS_FILEMISSING) { 02543 astman_send_error(s, m, "Config file not found"); 02544 return 0; 02545 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02546 astman_send_error(s, m, "Config file has invalid format"); 02547 return 0; 02548 } 02549 02550 astman_start_ack(s, m); 02551 while ((cur_category = ast_category_browse(cfg, cur_category))) { 02552 if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) { 02553 lineno = 0; 02554 astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category); 02555 for (v = ast_variable_browse(cfg, cur_category); v; v = v->next) { 02556 astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value); 02557 } 02558 catcount++; 02559 } 02560 } 02561 if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */ 02562 astman_append(s, "No categories found\r\n"); 02563 } 02564 ast_config_destroy(cfg); 02565 astman_append(s, "\r\n"); 02566 02567 return 0; 02568 }
| static int action_getconfigjson | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2636 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().
02637 { 02638 struct ast_config *cfg; 02639 const char *fn = astman_get_header(m, "Filename"); 02640 char *category = NULL; 02641 struct ast_variable *v; 02642 int comma1 = 0; 02643 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02644 02645 if (ast_strlen_zero(fn)) { 02646 astman_send_error(s, m, "Filename not specified"); 02647 return 0; 02648 } 02649 02650 if (!(cfg = ast_config_load2(fn, "manager", config_flags))) { 02651 astman_send_error(s, m, "Config file not found"); 02652 return 0; 02653 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02654 astman_send_error(s, m, "Config file has invalid format"); 02655 return 0; 02656 } 02657 02658 astman_start_ack(s, m); 02659 astman_append(s, "JSON: {"); 02660 while ((category = ast_category_browse(cfg, category))) { 02661 int comma2 = 0; 02662 02663 astman_append(s, "%s\"", comma1 ? "," : ""); 02664 astman_append_json(s, category); 02665 astman_append(s, "\":["); 02666 comma1 = 1; 02667 for (v = ast_variable_browse(cfg, category); v; v = v->next) { 02668 astman_append(s, "%s\"", comma2 ? "," : ""); 02669 astman_append_json(s, v->name); 02670 astman_append(s, "\":\""); 02671 astman_append_json(s, v->value); 02672 astman_append(s, "\""); 02673 comma2 = 1; 02674 } 02675 astman_append(s, "]"); 02676 } 02677 astman_append(s, "}\r\n\r\n"); 02678 02679 ast_config_destroy(cfg); 02680 02681 return 0; 02682 }
| static int action_getvar | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3226 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().
03227 { 03228 struct ast_channel *c = NULL; 03229 const char *name = astman_get_header(m, "Channel"); 03230 const char *varname = astman_get_header(m, "Variable"); 03231 char *varval; 03232 char workspace[1024]; 03233 03234 if (ast_strlen_zero(varname)) { 03235 astman_send_error(s, m, "No variable specified"); 03236 return 0; 03237 } 03238 03239 /* We don't want users with insufficient permissions using certain functions. */ 03240 if (!(function_capable_string_allowed_with_auths(varname, s->session->writeperm))) { 03241 astman_send_error(s, m, "GetVar Access Forbidden: Variable"); 03242 return 0; 03243 } 03244 03245 if (!ast_strlen_zero(name)) { 03246 if (!(c = ast_channel_get_by_name(name))) { 03247 astman_send_error(s, m, "No such channel"); 03248 return 0; 03249 } 03250 } 03251 03252 workspace[0] = '\0'; 03253 if (varname[strlen(varname) - 1] == ')') { 03254 if (!c) { 03255 c = ast_dummy_channel_alloc(); 03256 if (c) { 03257 ast_func_read(c, (char *) varname, workspace, sizeof(workspace)); 03258 } else 03259 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03260 } else { 03261 ast_func_read(c, (char *) varname, workspace, sizeof(workspace)); 03262 } 03263 varval = workspace; 03264 } else { 03265 pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL); 03266 } 03267 03268 if (c) { 03269 c = ast_channel_unref(c); 03270 } 03271 03272 astman_start_ack(s, m); 03273 astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, S_OR(varval, "")); 03274 03275 return 0; 03276 }
| static int action_hangup | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3150 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().
03151 { 03152 struct ast_channel *c = NULL; 03153 int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */ 03154 const char *name = astman_get_header(m, "Channel"); 03155 const char *cause = astman_get_header(m, "Cause"); 03156 03157 if (ast_strlen_zero(name)) { 03158 astman_send_error(s, m, "No channel specified"); 03159 return 0; 03160 } 03161 03162 if (!ast_strlen_zero(cause)) { 03163 char *endptr; 03164 causecode = strtol(cause, &endptr, 10); 03165 if (causecode < 0 || causecode > 127 || *endptr != '\0') { 03166 ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause); 03167 /* keep going, better to hangup without cause than to not hang up at all */ 03168 causecode = 0; /* do not set channel's hangupcause */ 03169 } 03170 } 03171 03172 if (!(c = ast_channel_get_by_name(name))) { 03173 astman_send_error(s, m, "No such channel"); 03174 return 0; 03175 } 03176 03177 ast_channel_lock(c); 03178 if (causecode > 0) { 03179 ast_debug(1, "Setting hangupcause of channel %s to %d (is %d now)\n", 03180 c->name, causecode, c->hangupcause); 03181 c->hangupcause = causecode; 03182 } 03183 ast_softhangup_nolock(c, AST_SOFTHANGUP_EXPLICIT); 03184 ast_channel_unlock(c); 03185 03186 c = ast_channel_unref(c); 03187 03188 astman_send_ack(s, m, "Channel Hungup"); 03189 03190 return 0; 03191 }
| static int action_listcategories | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2570 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().
02571 { 02572 struct ast_config *cfg; 02573 const char *fn = astman_get_header(m, "Filename"); 02574 char *category = NULL; 02575 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02576 int catcount = 0; 02577 02578 if (ast_strlen_zero(fn)) { 02579 astman_send_error(s, m, "Filename not specified"); 02580 return 0; 02581 } 02582 if (!(cfg = ast_config_load2(fn, "manager", config_flags))) { 02583 astman_send_error(s, m, "Config file not found"); 02584 return 0; 02585 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02586 astman_send_error(s, m, "Config file has invalid format"); 02587 return 0; 02588 } 02589 astman_start_ack(s, m); 02590 while ((category = ast_category_browse(cfg, category))) { 02591 astman_append(s, "Category-%06d: %s\r\n", catcount, category); 02592 catcount++; 02593 } 02594 if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */ 02595 astman_append(s, "Error: no categories found\r\n"); 02596 } 02597 ast_config_destroy(cfg); 02598 astman_append(s, "\r\n"); 02599 02600 return 0; 02601 }
| static int action_listcommands | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3032 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().
03033 { 03034 struct manager_action *cur; 03035 struct ast_str *temp = ast_str_alloca(256); 03036 03037 astman_start_ack(s, m); 03038 AST_RWLIST_RDLOCK(&actions); 03039 AST_RWLIST_TRAVERSE(&actions, cur, list) { 03040 if ((s->session->writeperm & cur->authority) || cur->authority == 0) { 03041 astman_append(s, "%s: %s (Priv: %s)\r\n", 03042 cur->action, cur->synopsis, authority_to_str(cur->authority, &temp)); 03043 } 03044 } 03045 AST_RWLIST_UNLOCK(&actions); 03046 astman_append(s, "\r\n"); 03047 03048 return 0; 03049 }
| static int action_login | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3101 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().
03102 { 03103 03104 /* still authenticated - don't process again */ 03105 if (s->session->authenticated) { 03106 astman_send_ack(s, m, "Already authenticated"); 03107 return 0; 03108 } 03109 03110 if (authenticate(s, m)) { 03111 sleep(1); 03112 astman_send_error(s, m, "Authentication failed"); 03113 return -1; 03114 } 03115 s->session->authenticated = 1; 03116 ast_atomic_fetchadd_int(&unauth_sessions, -1); 03117 if (manager_displayconnects(s->session)) { 03118 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)); 03119 } 03120 astman_send_ack(s, m, "Authentication accepted"); 03121 if ((s->session->send_events & EVENT_FLAG_SYSTEM) 03122 && ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 03123 struct ast_str *auth = ast_str_alloca(80); 03124 const char *cat_str = authority_to_str(EVENT_FLAG_SYSTEM, &auth); 03125 astman_append(s, "Event: FullyBooted\r\n" 03126 "Privilege: %s\r\n" 03127 "Status: Fully Booted\r\n\r\n", cat_str); 03128 } 03129 return 0; 03130 }
| static int action_logoff | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3095 of file manager.c.
References astman_send_response().
Referenced by __init_manager().
03096 { 03097 astman_send_response(s, m, "Goodbye", "Thanks for all the fish."); 03098 return -1; 03099 }
| static int action_mailboxcount | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4268 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().
04269 { 04270 const char *mailbox = astman_get_header(m, "Mailbox"); 04271 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;; 04272 04273 if (ast_strlen_zero(mailbox)) { 04274 astman_send_error(s, m, "Mailbox not specified"); 04275 return 0; 04276 } 04277 ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs); 04278 astman_start_ack(s, m); 04279 astman_append(s, "Message: Mailbox Message Count\r\n" 04280 "Mailbox: %s\r\n" 04281 "UrgMessages: %d\r\n" 04282 "NewMessages: %d\r\n" 04283 "OldMessages: %d\r\n" 04284 "\r\n", 04285 mailbox, urgentmsgs, newmsgs, oldmsgs); 04286 return 0; 04287 }
| static int action_mailboxstatus | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4251 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().
04252 { 04253 const char *mailbox = astman_get_header(m, "Mailbox"); 04254 int ret; 04255 04256 if (ast_strlen_zero(mailbox)) { 04257 astman_send_error(s, m, "Mailbox not specified"); 04258 return 0; 04259 } 04260 ret = ast_app_has_voicemail(mailbox, NULL); 04261 astman_start_ack(s, m); 04262 astman_append(s, "Message: Mailbox Status\r\n" 04263 "Mailbox: %s\r\n" 04264 "Waiting: %d\r\n\r\n", mailbox, ret); 04265 return 0; 04266 }
| static int action_originate | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4107 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().
04108 { 04109 const char *name = astman_get_header(m, "Channel"); 04110 const char *exten = astman_get_header(m, "Exten"); 04111 const char *context = astman_get_header(m, "Context"); 04112 const char *priority = astman_get_header(m, "Priority"); 04113 const char *timeout = astman_get_header(m, "Timeout"); 04114 const char *callerid = astman_get_header(m, "CallerID"); 04115 const char *account = astman_get_header(m, "Account"); 04116 const char *app = astman_get_header(m, "Application"); 04117 const char *appdata = astman_get_header(m, "Data"); 04118 const char *async = astman_get_header(m, "Async"); 04119 const char *id = astman_get_header(m, "ActionID"); 04120 const char *codecs = astman_get_header(m, "Codecs"); 04121 struct ast_variable *vars; 04122 char *tech, *data; 04123 char *l = NULL, *n = NULL; 04124 int pi = 0; 04125 int res; 04126 int to = 30000; 04127 int reason = 0; 04128 char tmp[256]; 04129 char tmp2[256]; 04130 format_t format = AST_FORMAT_SLINEAR; 04131 04132 pthread_t th; 04133 if (ast_strlen_zero(name)) { 04134 astman_send_error(s, m, "Channel not specified"); 04135 return 0; 04136 } 04137 if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) { 04138 if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) { 04139 astman_send_error(s, m, "Invalid priority"); 04140 return 0; 04141 } 04142 } 04143 if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) { 04144 astman_send_error(s, m, "Invalid timeout"); 04145 return 0; 04146 } 04147 ast_copy_string(tmp, name, sizeof(tmp)); 04148 tech = tmp; 04149 data = strchr(tmp, '/'); 04150 if (!data) { 04151 astman_send_error(s, m, "Invalid channel"); 04152 return 0; 04153 } 04154 *data++ = '\0'; 04155 ast_copy_string(tmp2, callerid, sizeof(tmp2)); 04156 ast_callerid_parse(tmp2, &n, &l); 04157 if (n) { 04158 if (ast_strlen_zero(n)) { 04159 n = NULL; 04160 } 04161 } 04162 if (l) { 04163 ast_shrink_phone_number(l); 04164 if (ast_strlen_zero(l)) { 04165 l = NULL; 04166 } 04167 } 04168 if (!ast_strlen_zero(codecs)) { 04169 format = 0; 04170 ast_parse_allow_disallow(NULL, &format, codecs, 1); 04171 } 04172 if (!ast_strlen_zero(app) && s->session) { 04173 int bad_appdata = 0; 04174 /* To run the System application (or anything else that goes to 04175 * shell), you must have the additional System privilege */ 04176 if (!(s->session->writeperm & EVENT_FLAG_SYSTEM) 04177 && ( 04178 strcasestr(app, "system") || /* System(rm -rf /) 04179 TrySystem(rm -rf /) */ 04180 strcasestr(app, "exec") || /* Exec(System(rm -rf /)) 04181 TryExec(System(rm -rf /)) */ 04182 strcasestr(app, "agi") || /* AGI(/bin/rm,-rf /) 04183 EAGI(/bin/rm,-rf /) */ 04184 strcasestr(app, "mixmonitor") || /* MixMonitor(blah,,rm -rf) */ 04185 strcasestr(app, "externalivr") || /* ExternalIVR(rm -rf) */ 04186 (strstr(appdata, "SHELL") && (bad_appdata = 1)) || /* NoOp(${SHELL(rm -rf /)}) */ 04187 (strstr(appdata, "EVAL") && (bad_appdata = 1)) /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ 04188 )) { 04189 char error_buf[64]; 04190 snprintf(error_buf, sizeof(error_buf), "Originate Access Forbidden: %s", bad_appdata ? "Data" : "Application"); 04191 astman_send_error(s, m, error_buf); 04192 return 0; 04193 } 04194 } 04195 /* Allocate requested channel variables */ 04196 vars = astman_get_variables(m); 04197 04198 if (ast_true(async)) { 04199 struct fast_originate_helper *fast; 04200 04201 fast = ast_calloc(1, sizeof(*fast)); 04202 if (!fast || ast_string_field_init(fast, 252)) { 04203 ast_free(fast); 04204 ast_variables_destroy(vars); 04205 res = -1; 04206 } else { 04207 if (!ast_strlen_zero(id)) { 04208 ast_string_field_build(fast, idtext, "ActionID: %s\r\n", id); 04209 } 04210 ast_string_field_set(fast, tech, tech); 04211 ast_string_field_set(fast, data, data); 04212 ast_string_field_set(fast, app, app); 04213 ast_string_field_set(fast, appdata, appdata); 04214 ast_string_field_set(fast, cid_num, l); 04215 ast_string_field_set(fast, cid_name, n); 04216 ast_string_field_set(fast, context, context); 04217 ast_string_field_set(fast, exten, exten); 04218 ast_string_field_set(fast, account, account); 04219 fast->vars = vars; 04220 fast->format = format; 04221 fast->timeout = to; 04222 fast->priority = pi; 04223 if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) { 04224 destroy_fast_originate_helper(fast); 04225 res = -1; 04226 } else { 04227 res = 0; 04228 } 04229 } 04230 } else if (!ast_strlen_zero(app)) { 04231 res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL); 04232 /* Any vars memory was passed to ast_pbx_outgoing_app(). */ 04233 } else { 04234 if (exten && context && pi) { 04235 res = ast_pbx_outgoing_exten(tech, format, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL); 04236 /* Any vars memory was passed to ast_pbx_outgoing_exten(). */ 04237 } else { 04238 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'"); 04239 ast_variables_destroy(vars); 04240 return 0; 04241 } 04242 } 04243 if (!res) { 04244 astman_send_ack(s, m, "Originate successfully queued"); 04245 } else { 04246 astman_send_error(s, m, "Originate failed"); 04247 } 04248 return 0; 04249 }
| static int action_ping | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2508 of file manager.c.
References ast_strlen_zero(), ast_tvnow(), astman_append(), and astman_get_header().
Referenced by __init_manager().
02509 { 02510 const char *actionid = astman_get_header(m, "ActionID"); 02511 struct timeval now = ast_tvnow(); 02512 02513 astman_append(s, "Response: Success\r\n"); 02514 if (!ast_strlen_zero(actionid)){ 02515 astman_append(s, "ActionID: %s\r\n", actionid); 02516 } 02517 astman_append( 02518 s, 02519 "Ping: Pong\r\n" 02520 "Timestamp: %ld.%06lu\r\n" 02521 "\r\n", 02522 (long) now.tv_sec, (unsigned long) now.tv_usec); 02523 return 0; 02524 }
| static int action_redirect | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
action_redirect: The redirect manager command
Definition at line 3477 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().
03478 { 03479 char buf[256]; 03480 const char *name = astman_get_header(m, "Channel"); 03481 const char *name2 = astman_get_header(m, "ExtraChannel"); 03482 const char *exten = astman_get_header(m, "Exten"); 03483 const char *exten2 = astman_get_header(m, "ExtraExten"); 03484 const char *context = astman_get_header(m, "Context"); 03485 const char *context2 = astman_get_header(m, "ExtraContext"); 03486 const char *priority = astman_get_header(m, "Priority"); 03487 const char *priority2 = astman_get_header(m, "ExtraPriority"); 03488 struct ast_channel *chan; 03489 struct ast_channel *chan2; 03490 int pi = 0; 03491 int pi2 = 0; 03492 int res; 03493 03494 if (ast_strlen_zero(name)) { 03495 astman_send_error(s, m, "Channel not specified"); 03496 return 0; 03497 } 03498 03499 if (ast_strlen_zero(context)) { 03500 astman_send_error(s, m, "Context not specified"); 03501 return 0; 03502 } 03503 if (ast_strlen_zero(exten)) { 03504 astman_send_error(s, m, "Exten not specified"); 03505 return 0; 03506 } 03507 if (ast_strlen_zero(priority)) { 03508 astman_send_error(s, m, "Priority not specified"); 03509 return 0; 03510 } 03511 if (sscanf(priority, "%30d", &pi) != 1) { 03512 pi = ast_findlabel_extension(NULL, context, exten, priority, NULL); 03513 } 03514 if (pi < 1) { 03515 astman_send_error(s, m, "Priority is invalid"); 03516 return 0; 03517 } 03518 03519 if (!ast_strlen_zero(name2) && !ast_strlen_zero(context2)) { 03520 /* We have an ExtraChannel and an ExtraContext */ 03521 if (ast_strlen_zero(exten2)) { 03522 astman_send_error(s, m, "ExtraExten not specified"); 03523 return 0; 03524 } 03525 if (ast_strlen_zero(priority2)) { 03526 astman_send_error(s, m, "ExtraPriority not specified"); 03527 return 0; 03528 } 03529 if (sscanf(priority2, "%30d", &pi2) != 1) { 03530 pi2 = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL); 03531 } 03532 if (pi2 < 1) { 03533 astman_send_error(s, m, "ExtraPriority is invalid"); 03534 return 0; 03535 } 03536 } 03537 03538 chan = ast_channel_get_by_name(name); 03539 if (!chan) { 03540 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name); 03541 astman_send_error(s, m, buf); 03542 return 0; 03543 } 03544 if (ast_check_hangup_locked(chan)) { 03545 astman_send_error(s, m, "Redirect failed, channel not up."); 03546 chan = ast_channel_unref(chan); 03547 return 0; 03548 } 03549 03550 if (ast_strlen_zero(name2)) { 03551 /* Single channel redirect in progress. */ 03552 if (chan->pbx) { 03553 ast_channel_lock(chan); 03554 /* don't let the after-bridge code run the h-exten */ 03555 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT); 03556 ast_channel_unlock(chan); 03557 } 03558 res = ast_async_goto(chan, context, exten, pi); 03559 if (!res) { 03560 astman_send_ack(s, m, "Redirect successful"); 03561 } else { 03562 astman_send_error(s, m, "Redirect failed"); 03563 } 03564 chan = ast_channel_unref(chan); 03565 return 0; 03566 } 03567 03568 chan2 = ast_channel_get_by_name(name2); 03569 if (!chan2) { 03570 snprintf(buf, sizeof(buf), "ExtraChannel does not exist: %s", name2); 03571 astman_send_error(s, m, buf); 03572 chan = ast_channel_unref(chan); 03573 return 0; 03574 } 03575 if (ast_check_hangup_locked(chan2)) { 03576 astman_send_error(s, m, "Redirect failed, extra channel not up."); 03577 chan2 = ast_channel_unref(chan2); 03578 chan = ast_channel_unref(chan); 03579 return 0; 03580 } 03581 03582 /* Dual channel redirect in progress. */ 03583 if (chan->pbx) { 03584 ast_channel_lock(chan); 03585 /* don't let the after-bridge code run the h-exten */ 03586 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT 03587 | AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); 03588 ast_channel_unlock(chan); 03589 } 03590 if (chan2->pbx) { 03591 ast_channel_lock(chan2); 03592 /* don't let the after-bridge code run the h-exten */ 03593 ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT 03594 | AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); 03595 ast_channel_unlock(chan2); 03596 } 03597 res = ast_async_goto(chan, context, exten, pi); 03598 if (!res) { 03599 if (!ast_strlen_zero(context2)) { 03600 res = ast_async_goto(chan2, context2, exten2, pi2); 03601 } else { 03602 res = ast_async_goto(chan2, context, exten, pi); 03603 } 03604 if (!res) { 03605 astman_send_ack(s, m, "Dual Redirect successful"); 03606 } else { 03607 astman_send_error(s, m, "Secondary redirect failed"); 03608 } 03609 } else { 03610 astman_send_error(s, m, "Redirect failed"); 03611 } 03612 03613 /* Release the bridge wait. */ 03614 if (chan->pbx) { 03615 ast_channel_lock(chan); 03616 ast_clear_flag(chan, AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); 03617 ast_channel_unlock(chan); 03618 } 03619 if (chan2->pbx) { 03620 ast_channel_lock(chan2); 03621 ast_clear_flag(chan2, AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); 03622 ast_channel_unlock(chan2); 03623 } 03624 03625 chan2 = ast_channel_unref(chan2); 03626 chan = ast_channel_unref(chan); 03627 return 0; 03628 }
| static int action_reload | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Send a reload event.
Definition at line 4533 of file manager.c.
References ast_module_reload(), astman_get_header(), astman_send_ack(), astman_send_error(), and S_OR.
Referenced by __init_manager().
04534 { 04535 const char *module = astman_get_header(m, "Module"); 04536 int res = ast_module_reload(S_OR(module, NULL)); 04537 04538 switch (res) { 04539 case -1: 04540 astman_send_error(s, m, "A reload is in progress"); 04541 break; 04542 case 0: 04543 astman_send_error(s, m, "No such module"); 04544 break; 04545 case 1: 04546 astman_send_error(s, m, "Module does not support reload"); 04547 break; 04548 case 2: 04549 astman_send_ack(s, m, "Module Reloaded"); 04550 break; 04551 default: 04552 astman_send_error(s, m, "An unknown error occurred"); 04553 break; 04554 } 04555 return 0; 04556 }
| static int action_sendtext | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3442 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().
03443 { 03444 struct ast_channel *c = NULL; 03445 const char *name = astman_get_header(m, "Channel"); 03446 const char *textmsg = astman_get_header(m, "Message"); 03447 int res = 0; 03448 03449 if (ast_strlen_zero(name)) { 03450 astman_send_error(s, m, "No channel specified"); 03451 return 0; 03452 } 03453 03454 if (ast_strlen_zero(textmsg)) { 03455 astman_send_error(s, m, "No Message specified"); 03456 return 0; 03457 } 03458 03459 if (!(c = ast_channel_get_by_name(name))) { 03460 astman_send_error(s, m, "No such channel"); 03461 return 0; 03462 } 03463 03464 res = ast_sendtext(c, textmsg); 03465 c = ast_channel_unref(c); 03466 03467 if (res >= 0) { 03468 astman_send_ack(s, m, "Success"); 03469 } else { 03470 astman_send_error(s, m, "Failure"); 03471 } 03472 03473 return 0; 03474 }
| static int action_setvar | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3193 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().
03194 { 03195 struct ast_channel *c = NULL; 03196 const char *name = astman_get_header(m, "Channel"); 03197 const char *varname = astman_get_header(m, "Variable"); 03198 const char *varval = astman_get_header(m, "Value"); 03199 int res = 0; 03200 03201 if (ast_strlen_zero(varname)) { 03202 astman_send_error(s, m, "No variable specified"); 03203 return 0; 03204 } 03205 03206 if (!ast_strlen_zero(name)) { 03207 if (!(c = ast_channel_get_by_name(name))) { 03208 astman_send_error(s, m, "No such channel"); 03209 return 0; 03210 } 03211 } 03212 03213 res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, "")); 03214 03215 if (c) { 03216 c = ast_channel_unref(c); 03217 } 03218 if (res == 0) { 03219 astman_send_ack(s, m, "Variable Set"); 03220 } else { 03221 astman_send_error(s, m, "Variable not set"); 03222 } 03223 return 0; 03224 }
| static int action_status | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Manager "status" command to show channels.
Definition at line 3280 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().
03281 { 03282 const char *name = astman_get_header(m, "Channel"); 03283 const char *cvariables = astman_get_header(m, "Variables"); 03284 char *variables = ast_strdupa(S_OR(cvariables, "")); 03285 struct ast_channel *c; 03286 char bridge[256]; 03287 struct timeval now = ast_tvnow(); 03288 long elapsed_seconds = 0; 03289 int channels = 0; 03290 int all = ast_strlen_zero(name); /* set if we want all channels */ 03291 const char *id = astman_get_header(m, "ActionID"); 03292 char idText[256]; 03293 AST_DECLARE_APP_ARGS(vars, 03294 AST_APP_ARG(name)[100]; 03295 ); 03296 struct ast_str *str = ast_str_create(1000); 03297 struct ast_channel_iterator *iter = NULL; 03298 03299 if (!ast_strlen_zero(id)) { 03300 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 03301 } else { 03302 idText[0] = '\0'; 03303 } 03304 03305 if (!(function_capable_string_allowed_with_auths(variables, s->session->writeperm))) { 03306 astman_send_error(s, m, "Status Access Forbidden: Variables"); 03307 return 0; 03308 } 03309 03310 if (all) { 03311 if (!(iter = ast_channel_iterator_all_new())) { 03312 ast_free(str); 03313 astman_send_error(s, m, "Memory Allocation Failure"); 03314 return 1; 03315 } 03316 c = ast_channel_iterator_next(iter); 03317 } else { 03318 if (!(c = ast_channel_get_by_name(name))) { 03319 astman_send_error(s, m, "No such channel"); 03320 ast_free(str); 03321 return 0; 03322 } 03323 } 03324 03325 astman_send_ack(s, m, "Channel status will follow"); 03326 03327 if (!ast_strlen_zero(cvariables)) { 03328 AST_STANDARD_APP_ARGS(vars, variables); 03329 } 03330 03331 /* if we look by name, we break after the first iteration */ 03332 for (; c; c = ast_channel_iterator_next(iter)) { 03333 ast_channel_lock(c); 03334 03335 if (!ast_strlen_zero(cvariables)) { 03336 int i; 03337 ast_str_reset(str); 03338 for (i = 0; i < vars.argc; i++) { 03339 char valbuf[512], *ret = NULL; 03340 03341 if (vars.name[i][strlen(vars.name[i]) - 1] == ')') { 03342 if (ast_func_read(c, vars.name[i], valbuf, sizeof(valbuf)) < 0) { 03343 valbuf[0] = '\0'; 03344 } 03345 ret = valbuf; 03346 } else { 03347 pbx_retrieve_variable(c, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL); 03348 } 03349 03350 ast_str_append(&str, 0, "Variable: %s=%s\r\n", vars.name[i], ret); 03351 } 03352 } 03353 03354 channels++; 03355 if (c->_bridge) { 03356 snprintf(bridge, sizeof(bridge), "BridgedChannel: %s\r\nBridgedUniqueid: %s\r\n", c->_bridge->name, c->_bridge->uniqueid); 03357 } else { 03358 bridge[0] = '\0'; 03359 } 03360 if (c->pbx) { 03361 if (c->cdr) { 03362 elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec; 03363 } 03364 astman_append(s, 03365 "Event: Status\r\n" 03366 "Privilege: Call\r\n" 03367 "Channel: %s\r\n" 03368 "CallerIDNum: %s\r\n" 03369 "CallerIDName: %s\r\n" 03370 "ConnectedLineNum: %s\r\n" 03371 "ConnectedLineName: %s\r\n" 03372 "Accountcode: %s\r\n" 03373 "ChannelState: %d\r\n" 03374 "ChannelStateDesc: %s\r\n" 03375 "Context: %s\r\n" 03376 "Extension: %s\r\n" 03377 "Priority: %d\r\n" 03378 "Seconds: %ld\r\n" 03379 "%s" 03380 "Uniqueid: %s\r\n" 03381 "%s" 03382 "%s" 03383 "\r\n", 03384 c->name, 03385 S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"), 03386 S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"), 03387 S_COR(c->connected.id.number.valid, c->connected.id.number.str, "<unknown>"), 03388 S_COR(c->connected.id.name.valid, c->connected.id.name.str, "<unknown>"), 03389 c->accountcode, 03390 c->_state, 03391 ast_state2str(c->_state), c->context, 03392 c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, ast_str_buffer(str), idText); 03393 } else { 03394 astman_append(s, 03395 "Event: Status\r\n" 03396 "Privilege: Call\r\n" 03397 "Channel: %s\r\n" 03398 "CallerIDNum: %s\r\n" 03399 "CallerIDName: %s\r\n" 03400 "ConnectedLineNum: %s\r\n" 03401 "ConnectedLineName: %s\r\n" 03402 "Account: %s\r\n" 03403 "State: %s\r\n" 03404 "%s" 03405 "Uniqueid: %s\r\n" 03406 "%s" 03407 "%s" 03408 "\r\n", 03409 c->name, 03410 S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"), 03411 S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"), 03412 S_COR(c->connected.id.number.valid, c->connected.id.number.str, "<unknown>"), 03413 S_COR(c->connected.id.name.valid, c->connected.id.name.str, "<unknown>"), 03414 c->accountcode, 03415 ast_state2str(c->_state), bridge, c->uniqueid, 03416 ast_str_buffer(str), idText); 03417 } 03418 03419 ast_channel_unlock(c); 03420 c = ast_channel_unref(c); 03421 03422 if (!all) { 03423 break; 03424 } 03425 } 03426 03427 if (iter) { 03428 ast_channel_iterator_destroy(iter); 03429 } 03430 03431 astman_append(s, 03432 "Event: StatusComplete\r\n" 03433 "%s" 03434 "Items: %d\r\n" 03435 "\r\n", idText, channels); 03436 03437 ast_free(str); 03438 03439 return 0; 03440 }
| static int action_timeout | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4314 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().
04315 { 04316 struct ast_channel *c; 04317 const char *name = astman_get_header(m, "Channel"); 04318 double timeout = atof(astman_get_header(m, "Timeout")); 04319 struct timeval when = { timeout, 0 }; 04320 04321 if (ast_strlen_zero(name)) { 04322 astman_send_error(s, m, "No channel specified"); 04323 return 0; 04324 } 04325 04326 if (!timeout || timeout < 0) { 04327 astman_send_error(s, m, "No timeout specified"); 04328 return 0; 04329 } 04330 04331 if (!(c = ast_channel_get_by_name(name))) { 04332 astman_send_error(s, m, "No such channel"); 04333 return 0; 04334 } 04335 04336 when.tv_usec = (timeout - when.tv_sec) * 1000000.0; 04337 04338 ast_channel_lock(c); 04339 ast_channel_setwhentohangup_tv(c, when); 04340 ast_channel_unlock(c); 04341 c = ast_channel_unref(c); 04342 04343 astman_send_ack(s, m, "Timeout Set"); 04344 04345 return 0; 04346 }
| static int action_updateconfig | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2830 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().
02831 { 02832 struct ast_config *cfg; 02833 const char *sfn = astman_get_header(m, "SrcFilename"); 02834 const char *dfn = astman_get_header(m, "DstFilename"); 02835 int res; 02836 const char *rld = astman_get_header(m, "Reload"); 02837 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02838 enum error_type result; 02839 02840 if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) { 02841 astman_send_error(s, m, "Filename not specified"); 02842 return 0; 02843 } 02844 if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) { 02845 astman_send_error(s, m, "Config file not found"); 02846 return 0; 02847 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02848 astman_send_error(s, m, "Config file has invalid format"); 02849 return 0; 02850 } 02851 result = handle_updates(s, m, cfg, dfn); 02852 if (!result) { 02853 ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */ 02854 res = ast_config_text_file_save(dfn, cfg, "Manager"); 02855 ast_config_destroy(cfg); 02856 if (res) { 02857 astman_send_error(s, m, "Save of config failed"); 02858 return 0; 02859 } 02860 astman_send_ack(s, m, NULL); 02861 if (!ast_strlen_zero(rld)) { 02862 if (ast_true(rld)) { 02863 rld = NULL; 02864 } 02865 ast_module_reload(rld); 02866 } 02867 } else { 02868 ast_config_destroy(cfg); 02869 switch(result) { 02870 case UNKNOWN_ACTION: 02871 astman_send_error(s, m, "Unknown action command"); 02872 break; 02873 case UNKNOWN_CATEGORY: 02874 astman_send_error(s, m, "Given category does not exist"); 02875 break; 02876 case UNSPECIFIED_CATEGORY: 02877 astman_send_error(s, m, "Category not specified"); 02878 break; 02879 case UNSPECIFIED_ARGUMENT: 02880 astman_send_error(s, m, "Problem with category, value, or line (if required)"); 02881 break; 02882 case FAILURE_ALLOCATION: 02883 astman_send_error(s, m, "Memory allocation failure, this should not happen"); 02884 break; 02885 case FAILURE_NEWCAT: 02886 astman_send_error(s, m, "Create category did not complete successfully"); 02887 break; 02888 case FAILURE_DELCAT: 02889 astman_send_error(s, m, "Delete category did not complete successfully"); 02890 break; 02891 case FAILURE_EMPTYCAT: 02892 astman_send_error(s, m, "Empty category did not complete successfully"); 02893 break; 02894 case FAILURE_UPDATE: 02895 astman_send_error(s, m, "Update did not complete successfully"); 02896 break; 02897 case FAILURE_DELETE: 02898 astman_send_error(s, m, "Delete did not complete successfully"); 02899 break; 02900 case FAILURE_APPEND: 02901 astman_send_error(s, m, "Append did not complete successfully"); 02902 break; 02903 } 02904 } 02905 return 0; 02906 }
| static int action_userevent | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4431 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().
04432 { 04433 const char *event = astman_get_header(m, "UserEvent"); 04434 struct ast_str *body = ast_str_thread_get(&userevent_buf, 16); 04435 int x; 04436 04437 ast_str_reset(body); 04438 04439 for (x = 0; x < m->hdrcount; x++) { 04440 if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) { 04441 ast_str_append(&body, 0, "%s\r\n", m->headers[x]); 04442 } 04443 } 04444 04445 astman_send_ack(s, m, "Event Sent"); 04446 manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, ast_str_buffer(body)); 04447 return 0; 04448 }
| static int action_waitevent | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2926 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().
02927 { 02928 const char *timeouts = astman_get_header(m, "Timeout"); 02929 int timeout = -1; 02930 int x; 02931 int needexit = 0; 02932 const char *id = astman_get_header(m, "ActionID"); 02933 char idText[256]; 02934 02935 if (!ast_strlen_zero(id)) { 02936 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 02937 } else { 02938 idText[0] = '\0'; 02939 } 02940 02941 if (!ast_strlen_zero(timeouts)) { 02942 sscanf(timeouts, "%30i", &timeout); 02943 if (timeout < -1) { 02944 timeout = -1; 02945 } 02946 /* XXX maybe put an upper bound, or prevent the use of 0 ? */ 02947 } 02948 02949 ao2_lock(s->session); 02950 if (s->session->waiting_thread != AST_PTHREADT_NULL) { 02951 pthread_kill(s->session->waiting_thread, SIGURG); 02952 } 02953 02954 if (s->session->managerid) { /* AMI-over-HTTP session */ 02955 /* 02956 * Make sure the timeout is within the expire time of the session, 02957 * as the client will likely abort the request if it does not see 02958 * data coming after some amount of time. 02959 */ 02960 time_t now = time(NULL); 02961 int max = s->session->sessiontimeout - now - 10; 02962 02963 if (max < 0) { /* We are already late. Strange but possible. */ 02964 max = 0; 02965 } 02966 if (timeout < 0 || timeout > max) { 02967 timeout = max; 02968 } 02969 if (!s->session->send_events) { /* make sure we record events */ 02970 s->session->send_events = -1; 02971 } 02972 } 02973 ao2_unlock(s->session); 02974 02975 /* XXX should this go inside the lock ? */ 02976 s->session->waiting_thread = pthread_self(); /* let new events wake up this thread */ 02977 ast_debug(1, "Starting waiting for an event!\n"); 02978 02979 for (x = 0; x < timeout || timeout < 0; x++) { 02980 ao2_lock(s->session); 02981 if (AST_RWLIST_NEXT(s->session->last_ev, eq_next)) { 02982 needexit = 1; 02983 } 02984 /* We can have multiple HTTP session point to the same mansession entry. 02985 * The way we deal with it is not very nice: newcomers kick out the previous 02986 * HTTP session. XXX this needs to be improved. 02987 */ 02988 if (s->session->waiting_thread != pthread_self()) { 02989 needexit = 1; 02990 } 02991 if (s->session->needdestroy) { 02992 needexit = 1; 02993 } 02994 ao2_unlock(s->session); 02995 if (needexit) { 02996 break; 02997 } 02998 if (s->session->managerid == 0) { /* AMI session */ 02999 if (ast_wait_for_input(s->session->fd, 1000)) { 03000 break; 03001 } 03002 } else { /* HTTP session */ 03003 sleep(1); 03004 } 03005 } 03006 ast_debug(1, "Finished waiting for an event!\n"); 03007 03008 ao2_lock(s->session); 03009 if (s->session->waiting_thread == pthread_self()) { 03010 struct eventqent *eqe = s->session->last_ev; 03011 astman_send_response(s, m, "Success", "Waiting for Event completed."); 03012 while ((eqe = advance_event(eqe))) { 03013 if (((s->session->readperm & eqe->category) == eqe->category) && 03014 ((s->session->send_events & eqe->category) == eqe->category)) { 03015 astman_append(s, "%s", eqe->eventdata); 03016 } 03017 s->session->last_ev = eqe; 03018 } 03019 astman_append(s, 03020 "Event: WaitEventComplete\r\n" 03021 "%s" 03022 "\r\n", idText); 03023 s->session->waiting_thread = AST_PTHREADT_NULL; 03024 } else { 03025 ast_debug(1, "Abandoning event request!\n"); 03026 } 03027 ao2_unlock(s->session); 03028 03029 return 0; 03030 }
Definition at line 1792 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().
01793 { 01794 struct eventqent *next; 01795 01796 AST_RWLIST_RDLOCK(&all_events); 01797 if ((next = AST_RWLIST_NEXT(e, eq_next))) { 01798 ast_atomic_fetchadd_int(&next->usecount, 1); 01799 ast_atomic_fetchadd_int(&e->usecount, -1); 01800 } 01801 AST_RWLIST_UNLOCK(&all_events); 01802 return next; 01803 }
| static int aocmessage_get_unit_entry | ( | const struct message * | m, | |
| struct ast_aoc_unit_entry * | entry, | |||
| unsigned int | entry_num | |||
| ) | [static] |
Definition at line 3877 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().
03878 { 03879 const char *unitamount; 03880 const char *unittype; 03881 struct ast_str *str = ast_str_alloca(32); 03882 03883 memset(entry, 0, sizeof(*entry)); 03884 03885 ast_str_set(&str, 0, "UnitAmount(%u)", entry_num); 03886 unitamount = astman_get_header(m, ast_str_buffer(str)); 03887 03888 ast_str_set(&str, 0, "UnitType(%u)", entry_num); 03889 unittype = astman_get_header(m, ast_str_buffer(str)); 03890 03891 if (!ast_strlen_zero(unitamount) && (sscanf(unitamount, "%30u", &entry->amount) == 1)) { 03892 entry->valid_amount = 1; 03893 } 03894 03895 if (!ast_strlen_zero(unittype) && sscanf(unittype, "%30u", &entry->type) == 1) { 03896 entry->valid_type = 1; 03897 } 03898 03899 return 0; 03900 }
| static void append_channel_vars | ( | struct ast_str ** | pbuf, | |
| struct ast_channel * | chan | |||
| ) | [static] |
Definition at line 5214 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().
05215 { 05216 struct manager_channel_variable *var; 05217 05218 AST_RWLIST_RDLOCK(&channelvars); 05219 AST_LIST_TRAVERSE(&channelvars, var, entry) { 05220 const char *val; 05221 struct ast_str *res; 05222 05223 if (var->isfunc) { 05224 res = ast_str_thread_get(&manager_event_funcbuf, 16); 05225 if (res && ast_func_read2(chan, var->name, &res, 0) == 0) { 05226 val = ast_str_buffer(res); 05227 } else { 05228 val = NULL; 05229 } 05230 } else { 05231 val = pbx_builtin_getvar_helper(chan, var->name); 05232 } 05233 ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", chan->name, var->name, val ? val : ""); 05234 } 05235 AST_RWLIST_UNLOCK(&channelvars); 05236 }
| static int append_event | ( | const char * | str, | |
| int | category | |||
| ) | [static] |
Definition at line 5188 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().
05189 { 05190 struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str)); 05191 static int seq; /* sequence number */ 05192 05193 if (!tmp) { 05194 return -1; 05195 } 05196 05197 /* need to init all fields, because ast_malloc() does not */ 05198 tmp->usecount = 0; 05199 tmp->category = category; 05200 tmp->seq = ast_atomic_fetchadd_int(&seq, 1); 05201 tmp->tv = ast_tvnow(); 05202 AST_RWLIST_NEXT(tmp, eq_next) = NULL; 05203 strcpy(tmp->eventdata, str); 05204 05205 AST_RWLIST_WRLOCK(&all_events); 05206 AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next); 05207 AST_RWLIST_UNLOCK(&all_events); 05208 05209 return 0; 05210 }
| 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 1939 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.
01940 { 01941 const char *action; 01942 int ret = 0; 01943 struct manager_action *act_found; 01944 struct mansession s = {.session = NULL, }; 01945 struct message m = { 0 }; 01946 char *dup_str; 01947 char *src; 01948 int x = 0; 01949 int curlen; 01950 01951 if (hook == NULL) { 01952 return -1; 01953 } 01954 01955 /* Create our own copy of the AMI action msg string. */ 01956 src = dup_str = ast_strdup(msg); 01957 if (!dup_str) { 01958 return -1; 01959 } 01960 01961 /* convert msg string to message struct */ 01962 curlen = strlen(src); 01963 for (x = 0; x < curlen; x++) { 01964 int cr; /* set if we have \r */ 01965 if (src[x] == '\r' && x+1 < curlen && src[x+1] == '\n') 01966 cr = 2; /* Found. Update length to include \r\n */ 01967 else if (src[x] == '\n') 01968 cr = 1; /* also accept \n only */ 01969 else 01970 continue; 01971 /* don't keep empty lines */ 01972 if (x && m.hdrcount < ARRAY_LEN(m.headers)) { 01973 /* ... but trim \r\n and terminate the header string */ 01974 src[x] = '\0'; 01975 m.headers[m.hdrcount++] = src; 01976 } 01977 x += cr; 01978 curlen -= x; /* remaining size */ 01979 src += x; /* update pointer */ 01980 x = -1; /* reset loop */ 01981 } 01982 01983 action = astman_get_header(&m, "Action"); 01984 if (strcasecmp(action, "login")) { 01985 act_found = action_find(action); 01986 if (act_found) { 01987 /* 01988 * we have to simulate a session for this action request 01989 * to be able to pass it down for processing 01990 * This is necessary to meet the previous design of manager.c 01991 */ 01992 s.hook = hook; 01993 s.f = (void*)1; /* set this to something so our request will make it through all functions that test it*/ 01994 01995 ao2_lock(act_found); 01996 if (act_found->registered && act_found->func) { 01997 ++act_found->active_count; 01998 ao2_unlock(act_found); 01999 ret = act_found->func(&s, &m); 02000 ao2_lock(act_found); 02001 --act_found->active_count; 02002 } else { 02003 ret = -1; 02004 } 02005 ao2_unlock(act_found); 02006 ao2_t_ref(act_found, -1, "done with found action object"); 02007 } 02008 } 02009 ast_free(dup_str); 02010 return ret; 02011 }
| 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 5443 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().
05444 { 05445 struct manager_action *cur; 05446 05447 cur = ao2_alloc(sizeof(*cur), action_destroy); 05448 if (!cur) { 05449 return -1; 05450 } 05451 if (ast_string_field_init(cur, 128)) { 05452 ao2_t_ref(cur, -1, "action object creation failed"); 05453 return -1; 05454 } 05455 05456 cur->action = action; 05457 cur->authority = auth; 05458 cur->func = func; 05459 #ifdef AST_XML_DOCS 05460 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 05461 char *tmpxml; 05462 05463 tmpxml = ast_xmldoc_build_synopsis("manager", action, NULL); 05464 ast_string_field_set(cur, synopsis, tmpxml); 05465 ast_free(tmpxml); 05466 05467 tmpxml = ast_xmldoc_build_syntax("manager", action, NULL); 05468 ast_string_field_set(cur, syntax, tmpxml); 05469 ast_free(tmpxml); 05470 05471 tmpxml = ast_xmldoc_build_description("manager", action, NULL); 05472 ast_string_field_set(cur, description, tmpxml); 05473 ast_free(tmpxml); 05474 05475 tmpxml = ast_xmldoc_build_seealso("manager", action, NULL); 05476 ast_string_field_set(cur, seealso, tmpxml); 05477 ast_free(tmpxml); 05478 05479 tmpxml = ast_xmldoc_build_arguments("manager", action, NULL); 05480 ast_string_field_set(cur, arguments, tmpxml); 05481 ast_free(tmpxml); 05482 05483 cur->docsrc = AST_XML_DOC; 05484 } else 05485 #endif 05486 { 05487 ast_string_field_set(cur, synopsis, synopsis); 05488 ast_string_field_set(cur, description, description); 05489 #ifdef AST_XML_DOCS 05490 cur->docsrc = AST_STATIC_DOC; 05491 #endif 05492 } 05493 if (ast_manager_register_struct(cur)) { 05494 ao2_t_ref(cur, -1, "action object registration failed"); 05495 return -1; 05496 } 05497 05498 ao2_t_ref(cur, -1, "action object registration successful"); 05499 return 0; 05500 }
| 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 5388 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().
05389 { 05390 struct manager_action *cur, *prev = NULL; 05391 05392 AST_RWLIST_WRLOCK(&actions); 05393 AST_RWLIST_TRAVERSE(&actions, cur, list) { 05394 int ret; 05395 05396 ret = strcasecmp(cur->action, act->action); 05397 if (ret == 0) { 05398 ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action); 05399 AST_RWLIST_UNLOCK(&actions); 05400 return -1; 05401 } 05402 if (ret > 0) { /* Insert these alphabetically */ 05403 prev = cur; 05404 break; 05405 } 05406 } 05407 05408 ao2_t_ref(act, +1, "action object added to list"); 05409 act->registered = 1; 05410 if (prev) { 05411 AST_RWLIST_INSERT_AFTER(&actions, prev, act, list); 05412 } else { 05413 AST_RWLIST_INSERT_HEAD(&actions, act, list); 05414 } 05415 05416 ast_verb(2, "Manager registered action %s\n", act->action); 05417 05418 AST_RWLIST_UNLOCK(&actions); 05419 05420 return 0; 05421 }
| int ast_manager_unregister | ( | char * | action | ) |
Unregister a registered manager command.
| action | Name of registered Action: |
Definition at line 5329 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().
05330 { 05331 struct manager_action *cur; 05332 05333 AST_RWLIST_WRLOCK(&actions); 05334 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) { 05335 if (!strcasecmp(action, cur->action)) { 05336 AST_RWLIST_REMOVE_CURRENT(list); 05337 break; 05338 } 05339 } 05340 AST_RWLIST_TRAVERSE_SAFE_END; 05341 AST_RWLIST_UNLOCK(&actions); 05342 05343 if (cur) { 05344 time_t now; 05345 05346 /* 05347 * We have removed the action object from the container so we 05348 * are no longer in a hurry. 05349 */ 05350 ao2_lock(cur); 05351 cur->registered = 0; 05352 ao2_unlock(cur); 05353 05354 /* 05355 * Wait up to 5 seconds for any active invocations to complete 05356 * before returning. We have to wait instead of blocking 05357 * because we may be waiting for ourself to complete. 05358 */ 05359 now = time(NULL); 05360 while (cur->active_count) { 05361 if (5 <= time(NULL) - now) { 05362 ast_debug(1, 05363 "Unregister manager action %s timed out waiting for %d active instances to complete\n", 05364 action, cur->active_count); 05365 break; 05366 } 05367 05368 sched_yield(); 05369 } 05370 05371 ao2_t_ref(cur, -1, "action object removed from list"); 05372 ast_verb(2, "Manager unregistered action %s\n", action); 05373 } 05374 05375 return 0; 05376 }
| 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 2057 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_one(), _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().
02058 { 02059 va_list ap; 02060 struct ast_str *buf; 02061 02062 if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) { 02063 return; 02064 } 02065 02066 va_start(ap, fmt); 02067 ast_str_set_va(&buf, 0, fmt, ap); 02068 va_end(ap); 02069 02070 if (s->f != NULL || s->session->f != NULL) { 02071 send_string(s, ast_str_buffer(buf)); 02072 } else { 02073 ast_verbose("fd == -1 in astman_append, should not happen\n"); 02074 } 02075 }
| static void astman_append_json | ( | struct mansession * | s, | |
| const char * | str | |||
| ) | [static] |
Definition at line 2627 of file manager.c.
References ast_alloca, astman_append(), and json_escape().
Referenced by action_getconfigjson().
02628 { 02629 char *buf; 02630 02631 buf = ast_alloca(2 * strlen(str) + 1); 02632 json_escape(buf, str); 02633 astman_append(s, "%s", buf); 02634 }
| 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 1859 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().
01860 { 01861 return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH); 01862 }
| struct ast_variable* astman_get_variables | ( | const struct message * | m | ) | [read] |
Get a linked list of the Variable: headers.
Definition at line 1917 of file manager.c.
References message::hdrcount, message::headers, and man_do_variable_value().
Referenced by action_originate(), and manager_sipnotify().
01918 { 01919 int varlen; 01920 int x; 01921 struct ast_variable *head = NULL; 01922 01923 static const char var_hdr[] = "Variable:"; 01924 01925 /* Process all "Variable:" headers. */ 01926 varlen = strlen(var_hdr); 01927 for (x = 0; x < m->hdrcount; x++) { 01928 if (strncasecmp(var_hdr, m->headers[x], varlen)) { 01929 continue; 01930 } 01931 head = man_do_variable_value(head, m->headers[x] + varlen); 01932 } 01933 01934 return head; 01935 }
| void astman_send_ack | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| char * | msg | |||
| ) |
Send ack in manager transaction.
Definition at line 2124 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().
02125 { 02126 astman_send_response_full(s, m, "Success", msg, NULL); 02127 }
| void astman_send_error | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| char * | error | |||
| ) |
Send error in manager transaction.
Definition at line 2119 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().
02120 { 02121 astman_send_response_full(s, m, "Error", error, NULL); 02122 }
| void astman_send_listack | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| char * | msg, | |||
| char * | listflag | |||
| ) |
Send ack in manager list transaction.
Definition at line 2134 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().
02135 { 02136 astman_send_response_full(s, m, "Success", msg, listflag); 02137 }
| void astman_send_response | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| char * | resp, | |||
| char * | msg | |||
| ) |
Send response in manager transaction.
Definition at line 2114 of file manager.c.
References astman_send_response_full().
Referenced by action_logoff(), and action_waitevent().
02115 { 02116 astman_send_response_full(s, m, resp, msg, NULL); 02117 }
| static void astman_send_response_full | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| char * | resp, | |||
| char * | msg, | |||
| char * | listflag | |||
| ) | [static] |
Definition at line 2094 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().
02095 { 02096 const char *id = astman_get_header(m, "ActionID"); 02097 02098 astman_append(s, "Response: %s\r\n", resp); 02099 if (!ast_strlen_zero(id)) { 02100 astman_append(s, "ActionID: %s\r\n", id); 02101 } 02102 if (listflag) { 02103 astman_append(s, "EventList: %s\r\n", listflag); /* Start, complete, cancelled */ 02104 } 02105 if (msg == MSG_MOREDATA) { 02106 return; 02107 } else if (msg) { 02108 astman_append(s, "Message: %s\r\n\r\n", msg); 02109 } else { 02110 astman_append(s, "\r\n"); 02111 } 02112 }
| static void astman_start_ack | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2129 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().
02130 { 02131 astman_send_response_full(s, m, "Success", MSG_MOREDATA, NULL); 02132 }
| static int authenticate | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2411 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().
02412 { 02413 const char *username = astman_get_header(m, "Username"); 02414 const char *password = astman_get_header(m, "Secret"); 02415 int error = -1; 02416 struct ast_manager_user *user = NULL; 02417 regex_t *regex_filter; 02418 struct ao2_iterator filter_iter; 02419 struct ast_sockaddr addr; 02420 02421 if (ast_strlen_zero(username)) { /* missing username */ 02422 return -1; 02423 } 02424 02425 /* locate user in locked state */ 02426 AST_RWLIST_WRLOCK(&users); 02427 02428 ast_sockaddr_from_sin(&addr, &s->session->sin); 02429 02430 if (!(user = get_manager_by_name_locked(username))) { 02431 report_invalid_user(s, username); 02432 ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02433 } else if (user->ha && !ast_apply_ha(user->ha, &addr)) { 02434 report_failed_acl(s, username); 02435 ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02436 } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) { 02437 const char *key = astman_get_header(m, "Key"); 02438 if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) { 02439 int x; 02440 int len = 0; 02441 char md5key[256] = ""; 02442 struct MD5Context md5; 02443 unsigned char digest[16]; 02444 02445 MD5Init(&md5); 02446 MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge)); 02447 MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret)); 02448 MD5Final(digest, &md5); 02449 for (x = 0; x < 16; x++) 02450 len += sprintf(md5key + len, "%2.2x", digest[x]); 02451 if (!strcmp(md5key, key)) { 02452 error = 0; 02453 } else { 02454 report_failed_challenge_response(s, key, md5key); 02455 } 02456 } else { 02457 ast_debug(1, "MD5 authentication is not possible. challenge: '%s'\n", 02458 S_OR(s->session->challenge, "")); 02459 } 02460 } else if (user->secret) { 02461 if (!strcmp(password, user->secret)) { 02462 error = 0; 02463 } else { 02464 report_inval_password(s, username); 02465 } 02466 } 02467 02468 if (error) { 02469 ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02470 AST_RWLIST_UNLOCK(&users); 02471 return -1; 02472 } 02473 02474 /* auth complete */ 02475 02476 /* All of the user parameters are copied to the session so that in the event 02477 * of a reload and a configuration change, the session parameters are not 02478 * changed. */ 02479 ast_copy_string(s->session->username, username, sizeof(s->session->username)); 02480 s->session->readperm = user->readperm; 02481 s->session->writeperm = user->writeperm; 02482 s->session->writetimeout = user->writetimeout; 02483 02484 filter_iter = ao2_iterator_init(user->whitefilters, 0); 02485 while ((regex_filter = ao2_iterator_next(&filter_iter))) { 02486 ao2_t_link(s->session->whitefilters, regex_filter, "add white user filter to session"); 02487 ao2_t_ref(regex_filter, -1, "remove iterator ref"); 02488 } 02489 ao2_iterator_destroy(&filter_iter); 02490 02491 filter_iter = ao2_iterator_init(user->blackfilters, 0); 02492 while ((regex_filter = ao2_iterator_next(&filter_iter))) { 02493 ao2_t_link(s->session->blackfilters, regex_filter, "add black user filter to session"); 02494 ao2_t_ref(regex_filter, -1, "remove iterator ref"); 02495 } 02496 ao2_iterator_destroy(&filter_iter); 02497 02498 s->session->sessionstart = time(NULL); 02499 s->session->sessionstart_tv = ast_tvnow(); 02500 set_eventmask(s, astman_get_header(m, "Events")); 02501 02502 report_auth_success(s); 02503 02504 AST_RWLIST_UNLOCK(&users); 02505 return 0; 02506 }
| 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 4362 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 3679 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().
03680 { 03681 char *cmd_copy, *cur_cmd; 03682 char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, }; 03683 int i; 03684 03685 cmd_copy = ast_strdupa(cmd); 03686 for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) { 03687 cur_cmd = ast_strip(cur_cmd); 03688 if (ast_strlen_zero(cur_cmd)) { 03689 i--; 03690 continue; 03691 } 03692 03693 cmd_words[i] = cur_cmd; 03694 } 03695 03696 for (i = 0; i < ARRAY_LEN(command_blacklist); i++) { 03697 int j, match = 1; 03698 03699 for (j = 0; command_blacklist[i].words[j]; j++) { 03700 if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) { 03701 match = 0; 03702 break; 03703 } 03704 } 03705 03706 if (match) { 03707 return 1; 03708 } 03709 } 03710 03711 return 0; 03712 }
| 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 3816 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().
03817 { 03818 ast_variables_destroy(doomed->vars); 03819 ast_string_field_free_memory(doomed); 03820 ast_free(doomed); 03821 }
| static int do_message | ( | struct mansession * | s | ) | [static] |
Definition at line 4968 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().
04969 { 04970 struct message m = { 0 }; 04971 char header_buf[sizeof(s->session->inbuf)] = { '\0' }; 04972 int res; 04973 int idx; 04974 int hdr_loss; 04975 time_t now; 04976 04977 hdr_loss = 0; 04978 for (;;) { 04979 /* Check if any events are pending and do them if needed */ 04980 if (process_events(s)) { 04981 res = -1; 04982 break; 04983 } 04984 res = get_input(s, header_buf); 04985 if (res == 0) { 04986 /* No input line received. */ 04987 if (!s->session->authenticated) { 04988 if (time(&now) == -1) { 04989 ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); 04990 res = -1; 04991 break; 04992 } 04993 04994 if (now - s->session->authstart > authtimeout) { 04995 if (displayconnects) { 04996 ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout); 04997 } 04998 res = -1; 04999 break; 05000 } 05001 } 05002 continue; 05003 } else if (res > 0) { 05004 /* Input line received. */ 05005 if (ast_strlen_zero(header_buf)) { 05006 if (hdr_loss) { 05007 mansession_lock(s); 05008 astman_send_error(s, &m, "Too many lines in message or allocation failure"); 05009 mansession_unlock(s); 05010 res = 0; 05011 } else { 05012 switch (s->parsing) { 05013 case MESSAGE_OKAY: 05014 res = process_message(s, &m) ? -1 : 0; 05015 break; 05016 case MESSAGE_LINE_TOO_LONG: 05017 handle_parse_error(s, &m, "Failed to parse message: line too long"); 05018 res = 0; 05019 break; 05020 } 05021 } 05022 break; 05023 } else if (m.hdrcount < ARRAY_LEN(m.headers)) { 05024 m.headers[m.hdrcount] = ast_strdup(header_buf); 05025 if (!m.headers[m.hdrcount]) { 05026 /* Allocation failure. */ 05027 hdr_loss = 1; 05028 } else { 05029 ++m.hdrcount; 05030 } 05031 } else { 05032 /* Too many lines in message. */ 05033 hdr_loss = 1; 05034 } 05035 } else { 05036 /* Input error. */ 05037 break; 05038 } 05039 } 05040 05041 /* Free AMI request headers. */ 05042 for (idx = 0; idx < m.hdrcount; ++idx) { 05043 ast_free((void *) m.headers[idx]); 05044 } 05045 return res; 05046 }
| 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 3823 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().
03824 { 03825 struct fast_originate_helper *in = data; 03826 int res; 03827 int reason = 0; 03828 struct ast_channel *chan = NULL, *chans[1]; 03829 char requested_channel[AST_CHANNEL_NAME]; 03830 03831 if (!ast_strlen_zero(in->app)) { 03832 res = ast_pbx_outgoing_app(in->tech, in->format, (char *) in->data, 03833 in->timeout, in->app, in->appdata, &reason, 1, 03834 S_OR(in->cid_num, NULL), 03835 S_OR(in->cid_name, NULL), 03836 in->vars, in->account, &chan); 03837 } else { 03838 res = ast_pbx_outgoing_exten(in->tech, in->format, (char *) in->data, 03839 in->timeout, in->context, in->exten, in->priority, &reason, 1, 03840 S_OR(in->cid_num, NULL), 03841 S_OR(in->cid_name, NULL), 03842 in->vars, in->account, &chan); 03843 } 03844 /* Any vars memory was passed to the ast_pbx_outgoing_xxx() calls. */ 03845 in->vars = NULL; 03846 03847 if (!chan) { 03848 snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data); 03849 } 03850 /* Tell the manager what happened with the channel */ 03851 chans[0] = chan; 03852 ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans, 03853 "%s" 03854 "Response: %s\r\n" 03855 "Channel: %s\r\n" 03856 "Context: %s\r\n" 03857 "Exten: %s\r\n" 03858 "Reason: %d\r\n" 03859 "Uniqueid: %s\r\n" 03860 "CallerIDNum: %s\r\n" 03861 "CallerIDName: %s\r\n", 03862 in->idtext, res ? "Failure" : "Success", 03863 chan ? chan->name : requested_channel, in->context, in->exten, reason, 03864 chan ? chan->uniqueid : "<null>", 03865 S_OR(in->cid_num, "<unknown>"), 03866 S_OR(in->cid_name, "<unknown>") 03867 ); 03868 03869 /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */ 03870 if (chan) { 03871 ast_channel_unlock(chan); 03872 } 03873 destroy_fast_originate_helper(in); 03874 return NULL; 03875 }
| static void free_channelvars | ( | void | ) | [static] |
Definition at line 7227 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().
07228 { 07229 struct manager_channel_variable *var; 07230 AST_RWLIST_WRLOCK(&channelvars); 07231 while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) { 07232 ast_free(var); 07233 } 07234 AST_RWLIST_UNLOCK(&channelvars); 07235 }
| 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 4853 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().
04854 { 04855 int res, x; 04856 int maxlen = sizeof(s->session->inbuf) - 1; 04857 char *src = s->session->inbuf; 04858 int timeout = -1; 04859 time_t now; 04860 04861 /* 04862 * Look for \r\n within the buffer. If found, copy to the output 04863 * buffer and return, trimming the \r\n (not used afterwards). 04864 */ 04865 for (x = 0; x < s->session->inlen; x++) { 04866 int cr; /* set if we have \r */ 04867 if (src[x] == '\r' && x+1 < s->session->inlen && src[x + 1] == '\n') { 04868 cr = 2; /* Found. Update length to include \r\n */ 04869 } else if (src[x] == '\n') { 04870 cr = 1; /* also accept \n only */ 04871 } else { 04872 continue; 04873 } 04874 memmove(output, src, x); /*... but trim \r\n */ 04875 output[x] = '\0'; /* terminate the string */ 04876 x += cr; /* number of bytes used */ 04877 s->session->inlen -= x; /* remaining size */ 04878 memmove(src, src + x, s->session->inlen); /* remove used bytes */ 04879 return 1; 04880 } 04881 if (s->session->inlen >= maxlen) { 04882 /* no crlf found, and buffer full - sorry, too long for us */ 04883 ast_log(LOG_WARNING, "Discarding message from %s. Line too long: %.25s...\n", ast_inet_ntoa(s->session->sin.sin_addr), src); 04884 s->session->inlen = 0; 04885 s->parsing = MESSAGE_LINE_TOO_LONG; 04886 } 04887 res = 0; 04888 while (res == 0) { 04889 /* calculate a timeout if we are not authenticated */ 04890 if (!s->session->authenticated) { 04891 if(time(&now) == -1) { 04892 ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); 04893 return -1; 04894 } 04895 04896 timeout = (authtimeout - (now - s->session->authstart)) * 1000; 04897 if (timeout < 0) { 04898 /* we have timed out */ 04899 return 0; 04900 } 04901 } 04902 04903 ao2_lock(s->session); 04904 if (s->session->pending_event) { 04905 s->session->pending_event = 0; 04906 ao2_unlock(s->session); 04907 return 0; 04908 } 04909 s->session->waiting_thread = pthread_self(); 04910 ao2_unlock(s->session); 04911 04912 res = ast_wait_for_input(s->session->fd, timeout); 04913 04914 ao2_lock(s->session); 04915 s->session->waiting_thread = AST_PTHREADT_NULL; 04916 ao2_unlock(s->session); 04917 } 04918 if (res < 0) { 04919 /* If we get a signal from some other thread (typically because 04920 * there are new events queued), return 0 to notify the caller. 04921 */ 04922 if (errno == EINTR || errno == EAGAIN) { 04923 return 0; 04924 } 04925 ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno)); 04926 return -1; 04927 } 04928 04929 ao2_lock(s->session); 04930 res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f); 04931 if (res < 1) { 04932 res = -1; /* error return */ 04933 } else { 04934 s->session->inlen += res; 04935 src[s->session->inlen] = '\0'; 04936 res = 0; 04937 } 04938 ao2_unlock(s->session); 04939 return res; 04940 }
| 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 1773 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.
01774 { 01775 switch (cmd) { 01776 case CLI_INIT: 01777 e->command = "manager reload"; 01778 e->usage = 01779 "Usage: manager reload\n" 01780 " Reloads the manager configuration.\n"; 01781 return NULL; 01782 case CLI_GENERATE: 01783 return NULL; 01784 } 01785 if (a->argc > 2) { 01786 return CLI_SHOWUSAGE; 01787 } 01788 reload_manager(); 01789 return CLI_SUCCESS; 01790 }
| static char* handle_mandebug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1547 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.
01548 { 01549 switch (cmd) { 01550 case CLI_INIT: 01551 e->command = "manager set debug [on|off]"; 01552 e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n"; 01553 return NULL; 01554 case CLI_GENERATE: 01555 return NULL; 01556 } 01557 01558 if (a->argc == 3) { 01559 ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off"); 01560 } else if (a->argc == 4) { 01561 if (!strcasecmp(a->argv[3], "on")) { 01562 manager_debug = 1; 01563 } else if (!strcasecmp(a->argv[3], "off")) { 01564 manager_debug = 0; 01565 } else { 01566 return CLI_SHOWUSAGE; 01567 } 01568 } 01569 return CLI_SUCCESS; 01570 }
| static void handle_parse_error | ( | struct mansession * | s, | |
| struct message * | m, | |||
| char * | error | |||
| ) | [static] |
Definition at line 4951 of file manager.c.
References astman_send_error(), mansession_lock(), mansession_unlock(), MESSAGE_OKAY, and mansession::parsing.
Referenced by do_message().
04952 { 04953 mansession_lock(s); 04954 astman_send_error(s, m, error); 04955 s->parsing = MESSAGE_OKAY; 04956 mansession_unlock(s); 04957 }
| static char* handle_showmanager | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1572 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.
01573 { 01574 struct ast_manager_user *user = NULL; 01575 int l, which; 01576 char *ret = NULL; 01577 struct ast_str *rauthority = ast_str_alloca(128); 01578 struct ast_str *wauthority = ast_str_alloca(128); 01579 01580 switch (cmd) { 01581 case CLI_INIT: 01582 e->command = "manager show user"; 01583 e->usage = 01584 " Usage: manager show user <user>\n" 01585 " Display all information related to the manager user specified.\n"; 01586 return NULL; 01587 case CLI_GENERATE: 01588 l = strlen(a->word); 01589 which = 0; 01590 if (a->pos != 3) { 01591 return NULL; 01592 } 01593 AST_RWLIST_RDLOCK(&users); 01594 AST_RWLIST_TRAVERSE(&users, user, list) { 01595 if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) { 01596 ret = ast_strdup(user->username); 01597 break; 01598 } 01599 } 01600 AST_RWLIST_UNLOCK(&users); 01601 return ret; 01602 } 01603 01604 if (a->argc != 4) { 01605 return CLI_SHOWUSAGE; 01606 } 01607 01608 AST_RWLIST_RDLOCK(&users); 01609 01610 if (!(user = get_manager_by_name_locked(a->argv[3]))) { 01611 ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]); 01612 AST_RWLIST_UNLOCK(&users); 01613 return CLI_SUCCESS; 01614 } 01615 01616 ast_cli(a->fd, "\n"); 01617 ast_cli(a->fd, 01618 " username: %s\n" 01619 " secret: %s\n" 01620 " acl: %s\n" 01621 " read perm: %s\n" 01622 " write perm: %s\n" 01623 "displayconnects: %s\n", 01624 (user->username ? user->username : "(N/A)"), 01625 (user->secret ? "<Set>" : "(N/A)"), 01626 (user->ha ? "yes" : "no"), 01627 user_authority_to_str(user->readperm, &rauthority), 01628 user_authority_to_str(user->writeperm, &wauthority), 01629 (user->displayconnects ? "yes" : "no")); 01630 01631 AST_RWLIST_UNLOCK(&users); 01632 01633 return CLI_SUCCESS; 01634 }
| static char* handle_showmanagers | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1636 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.
01637 { 01638 struct ast_manager_user *user = NULL; 01639 int count_amu = 0; 01640 switch (cmd) { 01641 case CLI_INIT: 01642 e->command = "manager show users"; 01643 e->usage = 01644 "Usage: manager show users\n" 01645 " Prints a listing of all managers that are currently configured on that\n" 01646 " system.\n"; 01647 return NULL; 01648 case CLI_GENERATE: 01649 return NULL; 01650 } 01651 if (a->argc != 3) { 01652 return CLI_SHOWUSAGE; 01653 } 01654 01655 AST_RWLIST_RDLOCK(&users); 01656 01657 /* If there are no users, print out something along those lines */ 01658 if (AST_RWLIST_EMPTY(&users)) { 01659 ast_cli(a->fd, "There are no manager users.\n"); 01660 AST_RWLIST_UNLOCK(&users); 01661 return CLI_SUCCESS; 01662 } 01663 01664 ast_cli(a->fd, "\nusername\n--------\n"); 01665 01666 AST_RWLIST_TRAVERSE(&users, user, list) { 01667 ast_cli(a->fd, "%s\n", user->username); 01668 count_amu++; 01669 } 01670 01671 AST_RWLIST_UNLOCK(&users); 01672 01673 ast_cli(a->fd,"-------------------\n" 01674 "%d manager users configured.\n", count_amu); 01675 return CLI_SUCCESS; 01676 }
| 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_free, 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, synopsis, 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 char *syntax = ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1); 01516 char *synopsis = ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1); 01517 char *description = ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1); 01518 char *arguments = ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1); 01519 char *seealso = ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1); 01520 ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n", 01521 syntax_title, syntax, 01522 synopsis_title, synopsis, 01523 description_title, description, 01524 arguments_title, arguments, 01525 seealso_title, seealso); 01526 ast_free(syntax); 01527 ast_free(synopsis); 01528 ast_free(description); 01529 ast_free(arguments); 01530 ast_free(seealso); 01531 } else 01532 #endif 01533 { 01534 ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n", 01535 cur->action, cur->synopsis, 01536 authority_to_str(cur->authority, &authority), 01537 S_OR(cur->description, "")); 01538 } 01539 } 01540 } 01541 } 01542 AST_RWLIST_UNLOCK(&actions); 01543 01544 return CLI_SUCCESS; 01545 }
| 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 1679 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.
01680 { 01681 struct manager_action *cur; 01682 struct ast_str *authority; 01683 #define HSMC_FORMAT " %-15.15s %-15.15s %-55.55s\n" 01684 switch (cmd) { 01685 case CLI_INIT: 01686 e->command = "manager show commands"; 01687 e->usage = 01688 "Usage: manager show commands\n" 01689 " Prints a listing of all the available Asterisk manager interface commands.\n"; 01690 return NULL; 01691 case CLI_GENERATE: 01692 return NULL; 01693 } 01694 authority = ast_str_alloca(80); 01695 ast_cli(a->fd, HSMC_FORMAT, "Action", "Privilege", "Synopsis"); 01696 ast_cli(a->fd, HSMC_FORMAT, "------", "---------", "--------"); 01697 01698 AST_RWLIST_RDLOCK(&actions); 01699 AST_RWLIST_TRAVERSE(&actions, cur, list) { 01700 ast_cli(a->fd, HSMC_FORMAT, cur->action, authority_to_str(cur->authority, &authority), cur->synopsis); 01701 } 01702 AST_RWLIST_UNLOCK(&actions); 01703 01704 return CLI_SUCCESS; 01705 }
| 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 1708 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.
01709 { 01710 struct mansession_session *session; 01711 time_t now = time(NULL); 01712 #define HSMCONN_FORMAT1 " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n" 01713 #define HSMCONN_FORMAT2 " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n" 01714 int count = 0; 01715 struct ao2_iterator i; 01716 01717 switch (cmd) { 01718 case CLI_INIT: 01719 e->command = "manager show connected"; 01720 e->usage = 01721 "Usage: manager show connected\n" 01722 " Prints a listing of the users that are currently connected to the\n" 01723 "Asterisk manager interface.\n"; 01724 return NULL; 01725 case CLI_GENERATE: 01726 return NULL; 01727 } 01728 01729 ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write"); 01730 01731 i = ao2_iterator_init(sessions, 0); 01732 while ((session = ao2_iterator_next(&i))) { 01733 ao2_lock(session); 01734 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); 01735 count++; 01736 ao2_unlock(session); 01737 unref_mansession(session); 01738 } 01739 ao2_iterator_destroy(&i); 01740 ast_cli(a->fd, "%d users connected.\n", count); 01741 01742 return CLI_SUCCESS; 01743 }
| 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 1747 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.
01748 { 01749 struct eventqent *s; 01750 switch (cmd) { 01751 case CLI_INIT: 01752 e->command = "manager show eventq"; 01753 e->usage = 01754 "Usage: manager show eventq\n" 01755 " Prints a listing of all events pending in the Asterisk manger\n" 01756 "event queue.\n"; 01757 return NULL; 01758 case CLI_GENERATE: 01759 return NULL; 01760 } 01761 AST_RWLIST_RDLOCK(&all_events); 01762 AST_RWLIST_TRAVERSE(&all_events, s, eq_next) { 01763 ast_cli(a->fd, "Usecount: %d\n", s->usecount); 01764 ast_cli(a->fd, "Category: %d\n", s->category); 01765 ast_cli(a->fd, "Event:\n%s", s->eventdata); 01766 } 01767 AST_RWLIST_UNLOCK(&all_events); 01768 01769 return CLI_SUCCESS; 01770 }
| static enum error_type handle_updates | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| struct ast_config * | cfg, | |||
| const char * | dfn | |||
| ) | [static] |
Definition at line 2685 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().
02686 { 02687 int x; 02688 char hdr[40]; 02689 const char *action, *cat, *var, *value, *match, *line; 02690 struct ast_category *category; 02691 struct ast_variable *v; 02692 struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16); 02693 enum error_type result = 0; 02694 02695 for (x = 0; x < 100000; x++) { /* 100000 = the max number of allowed updates + 1 */ 02696 unsigned int object = 0; 02697 02698 snprintf(hdr, sizeof(hdr), "Action-%06d", x); 02699 action = astman_get_header(m, hdr); 02700 if (ast_strlen_zero(action)) /* breaks the for loop if no action header */ 02701 break; /* this could cause problems if actions come in misnumbered */ 02702 02703 snprintf(hdr, sizeof(hdr), "Cat-%06d", x); 02704 cat = astman_get_header(m, hdr); 02705 if (ast_strlen_zero(cat)) { /* every action needs a category */ 02706 result = UNSPECIFIED_CATEGORY; 02707 break; 02708 } 02709 02710 snprintf(hdr, sizeof(hdr), "Var-%06d", x); 02711 var = astman_get_header(m, hdr); 02712 02713 snprintf(hdr, sizeof(hdr), "Value-%06d", x); 02714 value = astman_get_header(m, hdr); 02715 02716 if (!ast_strlen_zero(value) && *value == '>') { 02717 object = 1; 02718 value++; 02719 } 02720 02721 snprintf(hdr, sizeof(hdr), "Match-%06d", x); 02722 match = astman_get_header(m, hdr); 02723 02724 snprintf(hdr, sizeof(hdr), "Line-%06d", x); 02725 line = astman_get_header(m, hdr); 02726 02727 if (!strcasecmp(action, "newcat")) { 02728 if (ast_category_get(cfg,cat)) { /* check to make sure the cat doesn't */ 02729 result = FAILURE_NEWCAT; /* already exist */ 02730 break; 02731 } 02732 if (!(category = ast_category_new(cat, dfn, -1))) { 02733 result = FAILURE_ALLOCATION; 02734 break; 02735 } 02736 if (ast_strlen_zero(match)) { 02737 ast_category_append(cfg, category); 02738 } else { 02739 ast_category_insert(cfg, category, match); 02740 } 02741 } else if (!strcasecmp(action, "renamecat")) { 02742 if (ast_strlen_zero(value)) { 02743 result = UNSPECIFIED_ARGUMENT; 02744 break; 02745 } 02746 if (!(category = ast_category_get(cfg, cat))) { 02747 result = UNKNOWN_CATEGORY; 02748 break; 02749 } 02750 ast_category_rename(category, value); 02751 } else if (!strcasecmp(action, "delcat")) { 02752 if (ast_category_delete(cfg, cat)) { 02753 result = FAILURE_DELCAT; 02754 break; 02755 } 02756 } else if (!strcasecmp(action, "emptycat")) { 02757 if (ast_category_empty(cfg, cat)) { 02758 result = FAILURE_EMPTYCAT; 02759 break; 02760 } 02761 } else if (!strcasecmp(action, "update")) { 02762 if (ast_strlen_zero(var)) { 02763 result = UNSPECIFIED_ARGUMENT; 02764 break; 02765 } 02766 if (!(category = ast_category_get(cfg,cat))) { 02767 result = UNKNOWN_CATEGORY; 02768 break; 02769 } 02770 if (ast_variable_update(category, var, value, match, object)) { 02771 result = FAILURE_UPDATE; 02772 break; 02773 } 02774 } else if (!strcasecmp(action, "delete")) { 02775 if ((ast_strlen_zero(var) && ast_strlen_zero(line))) { 02776 result = UNSPECIFIED_ARGUMENT; 02777 break; 02778 } 02779 if (!(category = ast_category_get(cfg, cat))) { 02780 result = UNKNOWN_CATEGORY; 02781 break; 02782 } 02783 if (ast_variable_delete(category, var, match, line)) { 02784 result = FAILURE_DELETE; 02785 break; 02786 } 02787 } else if (!strcasecmp(action, "append")) { 02788 if (ast_strlen_zero(var)) { 02789 result = UNSPECIFIED_ARGUMENT; 02790 break; 02791 } 02792 if (!(category = ast_category_get(cfg, cat))) { 02793 result = UNKNOWN_CATEGORY; 02794 break; 02795 } 02796 if (!(v = ast_variable_new(var, value, dfn))) { 02797 result = FAILURE_ALLOCATION; 02798 break; 02799 } 02800 if (object || (match && !strcasecmp(match, "object"))) { 02801 v->object = 1; 02802 } 02803 ast_variable_append(category, v); 02804 } else if (!strcasecmp(action, "insert")) { 02805 if (ast_strlen_zero(var) || ast_strlen_zero(line)) { 02806 result = UNSPECIFIED_ARGUMENT; 02807 break; 02808 } 02809 if (!(category = ast_category_get(cfg, cat))) { 02810 result = UNKNOWN_CATEGORY; 02811 break; 02812 } 02813 if (!(v = ast_variable_new(var, value, dfn))) { 02814 result = FAILURE_ALLOCATION; 02815 break; 02816 } 02817 ast_variable_insert(category, v, line); 02818 } 02819 else { 02820 ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action); 02821 result = UNKNOWN_ACTION; 02822 break; 02823 } 02824 } 02825 ast_free(str1); 02826 ast_free(str2); 02827 return result; 02828 }
| 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 2607 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 1873 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().
01874 { 01875 char *parse; 01876 AST_DECLARE_APP_ARGS(args, 01877 AST_APP_ARG(vars)[64]; 01878 ); 01879 01880 hdr_val = ast_skip_blanks(hdr_val); /* ignore leading spaces in the value */ 01881 parse = ast_strdupa(hdr_val); 01882 01883 /* Break the header value string into name=val pair items. */ 01884 AST_STANDARD_APP_ARGS(args, parse); 01885 if (args.argc) { 01886 int y; 01887 01888 /* Process each name=val pair item. */ 01889 for (y = 0; y < args.argc; y++) { 01890 struct ast_variable *cur; 01891 char *var; 01892 char *val; 01893 01894 if (!args.vars[y]) { 01895 continue; 01896 } 01897 var = val = args.vars[y]; 01898 strsep(&val, "="); 01899 01900 /* XXX We may wish to trim whitespace from the strings. */ 01901 if (!val || ast_strlen_zero(var)) { 01902 continue; 01903 } 01904 01905 /* Create new variable list node and prepend it to the list. */ 01906 cur = ast_variable_new(var, val, ""); 01907 if (cur) { 01908 cur->next = head; 01909 head = cur; 01910 } 01911 } 01912 } 01913 01914 return head; 01915 }
| 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 4643 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().
04644 { 04645 int res; 04646 const char *module = astman_get_header(m, "Module"); 04647 const char *id = astman_get_header(m, "ActionID"); 04648 char idText[256]; 04649 #if !defined(LOW_MEMORY) 04650 const char *version; 04651 #endif 04652 char filename[PATH_MAX]; 04653 char *cut; 04654 04655 ast_copy_string(filename, module, sizeof(filename)); 04656 if ((cut = strchr(filename, '.'))) { 04657 *cut = '\0'; 04658 } else { 04659 cut = filename + strlen(filename); 04660 } 04661 snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".so"); 04662 ast_log(LOG_DEBUG, "**** ModuleCheck .so file %s\n", filename); 04663 res = ast_module_check(filename); 04664 if (!res) { 04665 astman_send_error(s, m, "Module not loaded"); 04666 return 0; 04667 } 04668 snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".c"); 04669 ast_log(LOG_DEBUG, "**** ModuleCheck .c file %s\n", filename); 04670 #if !defined(LOW_MEMORY) 04671 version = ast_file_version_find(filename); 04672 #endif 04673 04674 if (!ast_strlen_zero(id)) { 04675 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 04676 } else { 04677 idText[0] = '\0'; 04678 } 04679 astman_append(s, "Response: Success\r\n%s", idText); 04680 #if !defined(LOW_MEMORY) 04681 astman_append(s, "Version: %s\r\n\r\n", version ? version : ""); 04682 #endif 04683 return 0; 04684 }
| static int manager_moduleload | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4686 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().
04687 { 04688 int res; 04689 const char *module = astman_get_header(m, "Module"); 04690 const char *loadtype = astman_get_header(m, "LoadType"); 04691 04692 if (!loadtype || strlen(loadtype) == 0) { 04693 astman_send_error(s, m, "Incomplete ModuleLoad action."); 04694 } 04695 if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0) { 04696 astman_send_error(s, m, "Need module name"); 04697 } 04698 04699 if (!strcasecmp(loadtype, "load")) { 04700 res = ast_load_resource(module); 04701 if (res) { 04702 astman_send_error(s, m, "Could not load module."); 04703 } else { 04704 astman_send_ack(s, m, "Module loaded."); 04705 } 04706 } else if (!strcasecmp(loadtype, "unload")) { 04707 res = ast_unload_resource(module, AST_FORCE_SOFT); 04708 if (res) { 04709 astman_send_error(s, m, "Could not unload module."); 04710 } else { 04711 astman_send_ack(s, m, "Module unloaded."); 04712 } 04713 } else if (!strcasecmp(loadtype, "reload")) { 04714 if (!ast_strlen_zero(module)) { 04715 res = ast_module_reload(module); 04716 if (res == 0) { 04717 astman_send_error(s, m, "No such module."); 04718 } else if (res == 1) { 04719 astman_send_error(s, m, "Module does not support reload action."); 04720 } else { 04721 astman_send_ack(s, m, "Module reloaded."); 04722 } 04723 } else { 04724 ast_module_reload(NULL); /* Reload all modules */ 04725 astman_send_ack(s, m, "All modules reloaded"); 04726 } 04727 } else 04728 astman_send_error(s, m, "Incomplete ModuleLoad action."); 04729 return 0; 04730 }
| static int manager_state_cb | ( | char * | context, | |
| char * | exten, | |||
| int | state, | |||
| void * | data | |||
| ) | [static] |
Definition at line 5378 of file manager.c.
References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.
Referenced by __init_manager().
05379 { 05380 /* Notify managers of change */ 05381 char hint[512]; 05382 ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten); 05383 05384 manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state); 05385 return 0; 05386 }
| 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 2174 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().
02176 { 02177 ast_sockaddr_to_sin(&s->tcptls_session->parent->local_address, 02178 sin_local); 02179 02180 return sin_local; 02181 }
| static enum ast_security_event_transport_type mansession_get_transport | ( | const struct mansession * | s | ) | [static] |
Definition at line 2168 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().
02169 { 02170 return s->tcptls_session->parent->tls_cfg ? AST_SECURITY_EVENT_TRANSPORT_TLS : 02171 AST_SECURITY_EVENT_TRANSPORT_TCP; 02172 }
| static void mansession_lock | ( | struct mansession * | s | ) | [static] |
Lock the 'mansession' structure.
Definition at line 2140 of file manager.c.
References ast_mutex_lock, and mansession::lock.
Referenced by action_challenge(), do_message(), handle_parse_error(), and process_message().
02141 { 02142 ast_mutex_lock(&s->lock); 02143 }
| static void mansession_unlock | ( | struct mansession * | s | ) | [static] |
Unlock the 'mansession' structure.
Definition at line 2146 of file manager.c.
References ast_mutex_unlock, and mansession::lock.
Referenced by action_challenge(), do_message(), handle_parse_error(), and process_message().
02147 { 02148 ast_mutex_unlock(&s->lock); 02149 }
| static int match_filter | ( | struct mansession * | s, | |
| char * | eventdata | |||
| ) | [static] |
Definition at line 4377 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().
04378 { 04379 int result = 0; 04380 04381 ast_debug(3, "Examining event:\n%s\n", eventdata); 04382 if (!ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) { 04383 return 1; /* no filtering means match all */ 04384 } else if (ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) { 04385 /* white filters only: implied black all filter processed first, then white filters */ 04386 ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04387 } else if (!ao2_container_count(s->session->whitefilters) && ao2_container_count(s->session->blackfilters)) { 04388 /* black filters only: implied white all filter processed first, then black filters */ 04389 ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04390 } else { 04391 /* white and black filters: implied black all filter processed first, then white filters, and lastly black filters */ 04392 ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04393 if (result) { 04394 result = 0; 04395 ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04396 } 04397 } 04398 04399 return result; 04400 }
| 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 4407 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().
04408 { 04409 int ret = 0; 04410 04411 ao2_lock(s->session); 04412 if (s->session->f != NULL) { 04413 struct eventqent *eqe = s->session->last_ev; 04414 04415 while ((eqe = advance_event(eqe))) { 04416 if (!ret && s->session->authenticated && 04417 (s->session->readperm & eqe->category) == eqe->category && 04418 (s->session->send_events & eqe->category) == eqe->category) { 04419 if (match_filter(s, eqe->eventdata)) { 04420 if (send_string(s, eqe->eventdata) < 0) 04421 ret = -1; /* don't send more */ 04422 } 04423 } 04424 s->session->last_ev = eqe; 04425 } 04426 } 04427 ao2_unlock(s->session); 04428 return ret; 04429 }
| static int process_message | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4745 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().
04746 { 04747 int ret = 0; 04748 struct manager_action *act_found; 04749 const char *user; 04750 const char *action; 04751 04752 action = __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY); 04753 if (ast_strlen_zero(action)) { 04754 report_req_bad_format(s, "NONE"); 04755 mansession_lock(s); 04756 astman_send_error(s, m, "Missing action in request"); 04757 mansession_unlock(s); 04758 return 0; 04759 } 04760 04761 if (!s->session->authenticated 04762 && strcasecmp(action, "Login") 04763 && strcasecmp(action, "Logoff") 04764 && strcasecmp(action, "Challenge")) { 04765 if (!s->session->authenticated) { 04766 report_req_not_allowed(s, action); 04767 } 04768 mansession_lock(s); 04769 astman_send_error(s, m, "Permission denied"); 04770 mansession_unlock(s); 04771 return 0; 04772 } 04773 04774 if (!allowmultiplelogin 04775 && !s->session->authenticated 04776 && (!strcasecmp(action, "Login") 04777 || !strcasecmp(action, "Challenge"))) { 04778 user = astman_get_header(m, "Username"); 04779 04780 if (!ast_strlen_zero(user) && check_manager_session_inuse(user)) { 04781 report_session_limit(s); 04782 sleep(1); 04783 mansession_lock(s); 04784 astman_send_error(s, m, "Login Already In Use"); 04785 mansession_unlock(s); 04786 return -1; 04787 } 04788 } 04789 04790 act_found = action_find(action); 04791 if (act_found) { 04792 /* Found the requested AMI action. */ 04793 int acted = 0; 04794 04795 if ((s->session->writeperm & act_found->authority) 04796 || act_found->authority == 0) { 04797 /* We have the authority to execute the action. */ 04798 ao2_lock(act_found); 04799 if (act_found->registered && act_found->func) { 04800 ast_debug(1, "Running action '%s'\n", act_found->action); 04801 ++act_found->active_count; 04802 ao2_unlock(act_found); 04803 ret = act_found->func(s, m); 04804 acted = 1; 04805 ao2_lock(act_found); 04806 --act_found->active_count; 04807 } 04808 ao2_unlock(act_found); 04809 } 04810 if (!acted) { 04811 /* 04812 * We did not execute the action because access was denied, it 04813 * was no longer registered, or no action was really registered. 04814 * Complain about it and leave. 04815 */ 04816 report_req_not_allowed(s, action); 04817 mansession_lock(s); 04818 astman_send_error(s, m, "Permission denied"); 04819 mansession_unlock(s); 04820 } 04821 ao2_t_ref(act_found, -1, "done with found action object"); 04822 } else { 04823 char buf[512]; 04824 04825 report_req_bad_format(s, action); 04826 snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action); 04827 mansession_lock(s); 04828 astman_send_error(s, m, buf); 04829 mansession_unlock(s); 04830 } 04831 if (ret) { 04832 return ret; 04833 } 04834 /* Once done with our message, deliver any pending events unless the 04835 requester doesn't want them as part of this response. 04836 */ 04837 if (ast_strlen_zero(astman_get_header(m, "SuppressEvents"))) { 04838 return process_events(s); 04839 } else { 04840 return ret; 04841 } 04842 }
| 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 5155 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().
05156 { 05157 struct mansession_session *session; 05158 time_t now = time(NULL); 05159 struct ao2_iterator i; 05160 05161 if (!sessions) { 05162 return; 05163 } 05164 05165 i = ao2_iterator_init(sessions, 0); 05166 while ((session = ao2_iterator_next(&i)) && n_max > 0) { 05167 ao2_lock(session); 05168 if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) { 05169 if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) { 05170 ast_verb(2, "HTTP Manager '%s' timed out from %s\n", 05171 session->username, ast_inet_ntoa(session->sin.sin_addr)); 05172 } 05173 ao2_unlock(session); 05174 session_destroy(session); 05175 n_max--; 05176 } else { 05177 ao2_unlock(session); 05178 unref_mansession(session); 05179 } 05180 } 05181 ao2_iterator_destroy(&i); 05182 }
| static void report_auth_success | ( | const struct mansession * | s | ) | [static] |
Definition at line 2261 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().
02262 { 02263 struct sockaddr_in sin_local; 02264 char session_id[32]; 02265 struct ast_security_event_successful_auth successful_auth = { 02266 .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH, 02267 .common.version = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION, 02268 .common.service = "AMI", 02269 .common.account_id = s->session->username, 02270 .common.session_tv = &s->session->sessionstart_tv, 02271 .common.local_addr = { 02272 .sin = mansession_encode_sin_local(s, &sin_local), 02273 .transport = mansession_get_transport(s), 02274 }, 02275 .common.remote_addr = { 02276 .sin = &s->session->sin, 02277 .transport = mansession_get_transport(s), 02278 }, 02279 .common.session_id = session_id, 02280 }; 02281 02282 snprintf(session_id, sizeof(session_id), "%p", s->session); 02283 02284 ast_security_event_report(AST_SEC_EVT(&successful_auth)); 02285 }
| static void report_failed_acl | ( | const struct mansession * | s, | |
| const char * | username | |||
| ) | [static] |
Definition at line 2209 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().
02210 { 02211 struct sockaddr_in sin_local; 02212 char session_id[32]; 02213 struct ast_security_event_failed_acl failed_acl_event = { 02214 .common.event_type = AST_SECURITY_EVENT_FAILED_ACL, 02215 .common.version = AST_SECURITY_EVENT_FAILED_ACL_VERSION, 02216 .common.service = "AMI", 02217 .common.account_id = username, 02218 .common.session_tv = &s->session->sessionstart_tv, 02219 .common.local_addr = { 02220 .sin = mansession_encode_sin_local(s, &sin_local), 02221 .transport = mansession_get_transport(s), 02222 }, 02223 .common.remote_addr = { 02224 .sin = &s->session->sin, 02225 .transport = mansession_get_transport(s), 02226 }, 02227 .common.session_id = session_id, 02228 }; 02229 02230 snprintf(session_id, sizeof(session_id), "%p", s->session); 02231 02232 ast_security_event_report(AST_SEC_EVT(&failed_acl_event)); 02233 }
| static void report_failed_challenge_response | ( | const struct mansession * | s, | |
| const char * | response, | |||
| const char * | expected_response | |||
| ) | [static] |
Definition at line 2347 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().
02349 { 02350 struct sockaddr_in sin_local; 02351 char session_id[32]; 02352 struct ast_security_event_chal_resp_failed chal_resp_failed = { 02353 .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED, 02354 .common.version = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION, 02355 .common.service = "AMI", 02356 .common.account_id = s->session->username, 02357 .common.session_tv = &s->session->sessionstart_tv, 02358 .common.local_addr = { 02359 .sin = mansession_encode_sin_local(s, &sin_local), 02360 .transport = mansession_get_transport(s), 02361 }, 02362 .common.remote_addr = { 02363 .sin = &s->session->sin, 02364 .transport = mansession_get_transport(s), 02365 }, 02366 .common.session_id = session_id, 02367 02368 .challenge = s->session->challenge, 02369 .response = response, 02370 .expected_response = expected_response, 02371 }; 02372 02373 snprintf(session_id, sizeof(session_id), "%p", s->session); 02374 02375 ast_security_event_report(AST_SEC_EVT(&chal_resp_failed)); 02376 }
| static void report_inval_password | ( | const struct mansession * | s, | |
| const char * | username | |||
| ) | [static] |
Definition at line 2235 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().
02236 { 02237 struct sockaddr_in sin_local; 02238 char session_id[32]; 02239 struct ast_security_event_inval_password inval_password = { 02240 .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD, 02241 .common.version = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION, 02242 .common.service = "AMI", 02243 .common.account_id = username, 02244 .common.session_tv = &s->session->sessionstart_tv, 02245 .common.local_addr = { 02246 .sin = mansession_encode_sin_local(s, &sin_local), 02247 .transport = mansession_get_transport(s), 02248 }, 02249 .common.remote_addr = { 02250 .sin = &s->session->sin, 02251 .transport = mansession_get_transport(s), 02252 }, 02253 .common.session_id = session_id, 02254 }; 02255 02256 snprintf(session_id, sizeof(session_id), "%p", s->session); 02257 02258 ast_security_event_report(AST_SEC_EVT(&inval_password)); 02259 }
| static void report_invalid_user | ( | const struct mansession * | s, | |
| const char * | username | |||
| ) | [static] |
Definition at line 2183 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().
02184 { 02185 struct sockaddr_in sin_local; 02186 char session_id[32]; 02187 struct ast_security_event_inval_acct_id inval_acct_id = { 02188 .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID, 02189 .common.version = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION, 02190 .common.service = "AMI", 02191 .common.account_id = username, 02192 .common.session_tv = &s->session->sessionstart_tv, 02193 .common.local_addr = { 02194 .sin = mansession_encode_sin_local(s, &sin_local), 02195 .transport = mansession_get_transport(s), 02196 }, 02197 .common.remote_addr = { 02198 .sin = &s->session->sin, 02199 .transport = mansession_get_transport(s), 02200 }, 02201 .common.session_id = session_id, 02202 }; 02203 02204 snprintf(session_id, sizeof(session_id), "%p", s); 02205 02206 ast_security_event_report(AST_SEC_EVT(&inval_acct_id)); 02207 }
| static void report_req_bad_format | ( | const struct mansession * | s, | |
| const char * | action | |||
| ) | [static] |
Definition at line 2317 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().
02318 { 02319 struct sockaddr_in sin_local; 02320 char session_id[32]; 02321 char request_type[64]; 02322 struct ast_security_event_req_bad_format req_bad_format = { 02323 .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT, 02324 .common.version = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION, 02325 .common.service = "AMI", 02326 .common.account_id = s->session->username, 02327 .common.session_tv = &s->session->sessionstart_tv, 02328 .common.local_addr = { 02329 .sin = mansession_encode_sin_local(s, &sin_local), 02330 .transport = mansession_get_transport(s), 02331 }, 02332 .common.remote_addr = { 02333 .sin = &s->session->sin, 02334 .transport = mansession_get_transport(s), 02335 }, 02336 .common.session_id = session_id, 02337 02338 .request_type = request_type, 02339 }; 02340 02341 snprintf(session_id, sizeof(session_id), "%p", s->session); 02342 snprintf(request_type, sizeof(request_type), "Action: %s", action); 02343 02344 ast_security_event_report(AST_SEC_EVT(&req_bad_format)); 02345 }
| static void report_req_not_allowed | ( | const struct mansession * | s, | |
| const char * | action | |||
| ) | [static] |
Definition at line 2287 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().
02288 { 02289 struct sockaddr_in sin_local; 02290 char session_id[32]; 02291 char request_type[64]; 02292 struct ast_security_event_req_not_allowed req_not_allowed = { 02293 .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED, 02294 .common.version = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION, 02295 .common.service = "AMI", 02296 .common.account_id = s->session->username, 02297 .common.session_tv = &s->session->sessionstart_tv, 02298 .common.local_addr = { 02299 .sin = mansession_encode_sin_local(s, &sin_local), 02300 .transport = mansession_get_transport(s), 02301 }, 02302 .common.remote_addr = { 02303 .sin = &s->session->sin, 02304 .transport = mansession_get_transport(s), 02305 }, 02306 .common.session_id = session_id, 02307 02308 .request_type = request_type, 02309 }; 02310 02311 snprintf(session_id, sizeof(session_id), "%p", s->session); 02312 snprintf(request_type, sizeof(request_type), "Action: %s", action); 02313 02314 ast_security_event_report(AST_SEC_EVT(&req_not_allowed)); 02315 }
| static void report_session_limit | ( | const struct mansession * | s | ) | [static] |
Definition at line 2378 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().
02379 { 02380 struct sockaddr_in sin_local; 02381 char session_id[32]; 02382 struct ast_security_event_session_limit session_limit = { 02383 .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT, 02384 .common.version = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION, 02385 .common.service = "AMI", 02386 .common.account_id = s->session->username, 02387 .common.session_tv = &s->session->sessionstart_tv, 02388 .common.local_addr = { 02389 .sin = mansession_encode_sin_local(s, &sin_local), 02390 .transport = mansession_get_transport(s), 02391 }, 02392 .common.remote_addr = { 02393 .sin = &s->session->sin, 02394 .transport = mansession_get_transport(s), 02395 }, 02396 .common.session_id = session_id, 02397 }; 02398 02399 snprintf(session_id, sizeof(session_id), "%p", s->session); 02400 02401 ast_security_event_report(AST_SEC_EVT(&session_limit)); 02402 }
| 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 2018 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().
02019 { 02020 int res; 02021 FILE *f = s->f ? s->f : s->session->f; 02022 int fd = s->f ? s->fd : s->session->fd; 02023 02024 /* It's a result from one of the hook's action invocation */ 02025 if (s->hook) { 02026 /* 02027 * to send responses, we're using the same function 02028 * as for receiving events. We call the event "HookResponse" 02029 */ 02030 s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string); 02031 return 0; 02032 } 02033 02034 if ((res = ast_careful_fwrite(f, fd, string, strlen(string), s->session->writetimeout))) { 02035 s->write_error = 1; 02036 } 02037 02038 return res; 02039 }
| 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 5056 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.
05057 { 05058 struct ast_tcptls_session_instance *ser = data; 05059 struct mansession_session *session; 05060 struct mansession s = { 05061 .tcptls_session = data, 05062 }; 05063 int flags; 05064 int res; 05065 struct sockaddr_in ser_remote_address_tmp; 05066 struct protoent *p; 05067 05068 if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) { 05069 fclose(ser->f); 05070 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05071 goto done; 05072 } 05073 05074 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 05075 session = build_mansession(ser_remote_address_tmp); 05076 05077 if (session == NULL) { 05078 fclose(ser->f); 05079 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05080 goto done; 05081 } 05082 05083 /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm. 05084 * This is necessary to prevent delays (caused by buffering) as we 05085 * write to the socket in bits and peices. */ 05086 p = getprotobyname("tcp"); 05087 if (p) { 05088 int arg = 1; 05089 if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) { 05090 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)); 05091 } 05092 } else { 05093 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"); 05094 } 05095 05096 flags = fcntl(ser->fd, F_GETFL); 05097 if (!block_sockets) { /* make sure socket is non-blocking */ 05098 flags |= O_NONBLOCK; 05099 } else { 05100 flags &= ~O_NONBLOCK; 05101 } 05102 fcntl(ser->fd, F_SETFL, flags); 05103 05104 ao2_lock(session); 05105 /* Hook to the tail of the event queue */ 05106 session->last_ev = grab_last(); 05107 05108 ast_mutex_init(&s.lock); 05109 05110 /* these fields duplicate those in the 'ser' structure */ 05111 session->fd = s.fd = ser->fd; 05112 session->f = s.f = ser->f; 05113 session->sin = ser_remote_address_tmp; 05114 s.session = session; 05115 05116 AST_LIST_HEAD_INIT_NOLOCK(&session->datastores); 05117 05118 if(time(&session->authstart) == -1) { 05119 ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno)); 05120 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05121 ao2_unlock(session); 05122 session_destroy(session); 05123 goto done; 05124 } 05125 ao2_unlock(session); 05126 05127 astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */ 05128 for (;;) { 05129 if ((res = do_message(&s)) < 0 || s.write_error) { 05130 break; 05131 } 05132 } 05133 /* session is over, explain why and terminate */ 05134 if (session->authenticated) { 05135 if (manager_displayconnects(session)) { 05136 ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 05137 } 05138 } else { 05139 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05140 if (displayconnects) { 05141 ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr)); 05142 } 05143 } 05144 05145 session_destroy(session); 05146 05147 ast_mutex_destroy(&s.lock); 05148 done: 05149 ao2_ref(ser, -1); 05150 ser = NULL; 05151 return NULL; 05152 }
| 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 2155 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().
02156 { 02157 int maskint = strings_to_mask(eventmask); 02158 02159 ao2_lock(s->session); 02160 if (maskint >= 0) { 02161 s->session->send_events = maskint; 02162 } 02163 ao2_unlock(s->session); 02164 02165 return maskint; 02166 }
| 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 4348 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 2048 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 5239 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 5212 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 2049 of file manager.c.
Referenced by action_userevent().
int webmanager_enabled = 0 [static] |
1.6.1