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 |
| In case you didn't read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data. More... | |
| 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) |
Enumerations | |
| enum | add_filter_result { FILTER_SUCCESS, FILTER_ALLOC_FAILED, FILTER_COMPILE_FAIL } |
| enum | error_type { UNKNOWN_ACTION = 1, UNKNOWN_CATEGORY, UNSPECIFIED_CATEGORY, UNSPECIFIED_ARGUMENT, FAILURE_ALLOCATION, FAILURE_NEWCAT, FAILURE_DELCAT, FAILURE_EMPTYCAT, FAILURE_UPDATE, FAILURE_DELETE, FAILURE_APPEND } |
Functions | |
| int | __ast_manager_event_multichan (int category, const char *event, int chancount, struct ast_channel **chans, const char *file, int line, const char *func, const char *fmt,...) |
| static const char * | __astman_get_header (const struct message *m, char *var, int mode) |
| Return a matching header value. | |
| static void | __fini_actions (void) |
| static void | __fini_all_events (void) |
| static void | __fini_channelvars (void) |
| static void | __fini_manager_hooks (void) |
| static void | __fini_users (void) |
| static void | __init_actions (void) |
| static void | __init_all_events (void) |
| static void | __init_astman_append_buf (void) |
| thread local buffer for astman_append | |
| static void | __init_channelvars (void) |
| static void | __init_manager_event_buf (void) |
| static void | __init_manager_event_funcbuf (void) |
| static void | __init_manager_hooks (void) |
| static void | __init_userevent_buf (void) |
| static void | __init_users (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 int | action_filter (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) |
| events are appended to a queue from where they can be dispatched to clients. | |
| int | ast_hook_send_action (struct manager_custom_hook *hook, const char *msg) |
| access for hooks to send action messages to ami | |
| 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) |
| support functions to register/unregister AMI action handlers, | |
| 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) |
| send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field. | |
| static void | astman_start_ack (struct mansession *s, const struct message *m) |
| static int | authenticate (struct mansession *s, const struct message *m) |
| static const char * | authority_to_str (int authority, struct ast_str **res) |
| Convert authority code to a list of options. | |
| static int | blackfilter_cmp_fn (void *obj, void *arg, void *data, int flags) |
| static struct mansession_session * | build_mansession (struct sockaddr_in sin) |
| Allocate manager session structure and add it to the list of sessions. | |
| static int | check_blacklist (const char *cmd) |
| int | check_manager_enabled (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 | get_input (struct mansession *s, char *output) |
| static struct ast_manager_user * | get_manager_by_name_locked (const char *name) |
| static int | get_perm (const char *instr) |
| static struct eventqent * | grab_last (void) |
| static char * | handle_manager_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command manager reload. | |
| static char * | handle_mandebug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_showmanager (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_showmanagers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_showmancmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_showmancmds (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command manager list commands. | |
| static char * | handle_showmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command manager list connected. | |
| static char * | handle_showmaneventq (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command manager list eventq. | |
| static enum error_type | handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn) |
| helper function for action_updateconfig | |
| 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 enum add_filter_result | manager_add_filter (const char *filter_pattern, struct ao2_container *whitefilters, struct ao2_container *blackfilters) |
| static int | manager_displayconnects (struct mansession_session *session) |
| Get displayconnects config option. | |
| static int | manager_modulecheck (struct mansession *s, const struct message *m) |
| Manager function to check if module is loaded. | |
| static int | manager_moduleload (struct mansession *s, const struct message *m) |
| static int | manager_state_cb (const char *context, const char *exten, enum ast_extension_states 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) |
| Process an AMI message, performing desired action. Return 0 on success, -1 on error that require the session to be destroyed. | |
| static void | purge_events (void) |
| static void | purge_sessions (int n_max) |
| remove at most n_max stale session from the list. | |
| static void | report_auth_success (const struct mansession *s) |
| static void | report_failed_acl (const struct mansession *s, const char *username) |
| static void | report_failed_challenge_response (const struct mansession *s, const char *response, const char *expected_response) |
| static void | report_inval_password (const struct mansession *s, const char *username) |
| static void | report_invalid_user (const struct mansession *s, const char *username) |
| static void | report_req_bad_format (const struct mansession *s, const char *action) |
| static void | report_req_not_allowed (const struct mansession *s, const char *action) |
| static void | report_session_limit (const struct mansession *s) |
| static int | send_string (struct mansession *s, char *string) |
| static void | session_destroy (struct mansession_session *s) |
| static void | session_destructor (void *obj) |
| static void * | session_do (void *data) |
| The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ). | |
| static int | set_eventmask (struct mansession *s, const char *eventmask) |
| Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm. | |
| static int | strings_to_mask (const char *string) |
| static struct mansession_session * | unref_mansession (struct mansession_session *s) |
| Unreference manager session object. If no more references, then go ahead and delete it. | |
| static int | whitefilter_cmp_fn (void *obj, void *arg, void *data, int flags) |
Variables | |
| static int | allowmultiplelogin = 1 |
| static struct ast_threadstorage | astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , } |
| static int | authlimit |
| static int | authtimeout |
| static int | block_sockets |
| static int | broken_events_action = 0 |
| struct { | |
| const char * words [AST_MAX_CMD_LEN] | |
| } | command_blacklist [] |
| static int | displayconnects = 1 |
| static char | global_realm [MAXHOSTNAMELEN] |
| static int | httptimeout = 60 |
| 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 list of locally configured nodes
| #define ASTMAN_APPEND_BUF_INITSIZE 256 |
initial allocated size for the astman_append_buf
Definition at line 2030 of file manager.c.
Referenced by astman_append().
| #define DEFAULT_REALM "asterisk" |
| #define GET_HEADER_FIRST_MATCH 0 |
| #define GET_HEADER_LAST_MATCH 1 |
| #define GET_HEADER_SKIP_EMPTY 2 |
Definition at line 1793 of file manager.c.
Referenced by __astman_get_header(), and process_message().
| #define MANAGER_EVENT_BUF_INITSIZE 256 |
| #define MAX_BLACKLIST_CMD_LEN 2 |
Descriptor for a manager session, either on the AMI socket or over HTTP.
Definition at line 959 of file manager.c.
Referenced by check_blacklist().
| #define MSG_MOREDATA ((char *)astman_send_response) |
Definition at line 2065 of file manager.c.
Referenced by astman_send_response_full(), and astman_start_ack().
| enum add_filter_result |
Definition at line 894 of file manager.c.
00894 { 00895 FILTER_SUCCESS, 00896 FILTER_ALLOC_FAILED, 00897 FILTER_COMPILE_FAIL, 00898 };
| 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 880 of file manager.c.
00880 { 00881 UNKNOWN_ACTION = 1, 00882 UNKNOWN_CATEGORY, 00883 UNSPECIFIED_CATEGORY, 00884 UNSPECIFIED_ARGUMENT, 00885 FAILURE_ALLOCATION, 00886 FAILURE_NEWCAT, 00887 FAILURE_DELCAT, 00888 FAILURE_EMPTYCAT, 00889 FAILURE_UPDATE, 00890 FAILURE_DELETE, 00891 FAILURE_APPEND 00892 };
| 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 5199 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, unref_mansession(), and mansession_session::waiting_thread.
05201 { 05202 struct mansession_session *session; 05203 struct manager_custom_hook *hook; 05204 struct ast_str *auth = ast_str_alloca(80); 05205 const char *cat_str; 05206 va_list ap; 05207 struct timeval now; 05208 struct ast_str *buf; 05209 int i; 05210 05211 if (!(sessions && ao2_container_count(sessions)) && AST_RWLIST_EMPTY(&manager_hooks)) { 05212 return 0; 05213 } 05214 05215 if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) { 05216 return -1; 05217 } 05218 05219 cat_str = authority_to_str(category, &auth); 05220 ast_str_set(&buf, 0, 05221 "Event: %s\r\nPrivilege: %s\r\n", 05222 event, cat_str); 05223 05224 if (timestampevents) { 05225 now = ast_tvnow(); 05226 ast_str_append(&buf, 0, 05227 "Timestamp: %ld.%06lu\r\n", 05228 (long)now.tv_sec, (unsigned long) now.tv_usec); 05229 } 05230 if (manager_debug) { 05231 static int seq; 05232 ast_str_append(&buf, 0, 05233 "SequenceNumber: %d\r\n", 05234 ast_atomic_fetchadd_int(&seq, 1)); 05235 ast_str_append(&buf, 0, 05236 "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func); 05237 } 05238 05239 va_start(ap, fmt); 05240 ast_str_append_va(&buf, 0, fmt, ap); 05241 va_end(ap); 05242 for (i = 0; i < chancount; i++) { 05243 append_channel_vars(&buf, chans[i]); 05244 } 05245 05246 ast_str_append(&buf, 0, "\r\n"); 05247 05248 append_event(ast_str_buffer(buf), category); 05249 05250 /* Wake up any sleeping sessions */ 05251 if (sessions) { 05252 struct ao2_iterator i; 05253 i = ao2_iterator_init(sessions, 0); 05254 while ((session = ao2_iterator_next(&i))) { 05255 ao2_lock(session); 05256 if (session->waiting_thread != AST_PTHREADT_NULL) { 05257 pthread_kill(session->waiting_thread, SIGURG); 05258 } else { 05259 /* We have an event to process, but the mansession is 05260 * not waiting for it. We still need to indicate that there 05261 * is an event waiting so that get_input processes the pending 05262 * event instead of polling. 05263 */ 05264 session->pending_event = 1; 05265 } 05266 ao2_unlock(session); 05267 unref_mansession(session); 05268 } 05269 ao2_iterator_destroy(&i); 05270 } 05271 05272 if (!AST_RWLIST_EMPTY(&manager_hooks)) { 05273 AST_RWLIST_RDLOCK(&manager_hooks); 05274 AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) { 05275 hook->helper(category, event, ast_str_buffer(buf)); 05276 } 05277 AST_RWLIST_UNLOCK(&manager_hooks); 05278 } 05279 05280 return 0; 05281 }
| 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.
Never returns NULL.
Definition at line 1808 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().
01809 { 01810 int x, l = strlen(var); 01811 const char *result = ""; 01812 01813 for (x = 0; x < m->hdrcount; x++) { 01814 const char *h = m->headers[x]; 01815 if (!strncasecmp(var, h, l) && h[l] == ':') { 01816 const char *value = h + l + 1; 01817 value = ast_skip_blanks(value); /* ignore leading spaces in the value */ 01818 /* found a potential candidate */ 01819 if ((mode & GET_HEADER_SKIP_EMPTY) && ast_strlen_zero(value)) { 01820 continue; /* not interesting */ 01821 } 01822 if (mode & GET_HEADER_LAST_MATCH) { 01823 result = value; /* record the last match so far */ 01824 } else { 01825 return value; 01826 } 01827 } 01828 } 01829 01830 return result; 01831 }
| static void __fini_manager_hooks | ( | void | ) | [static] |
| static void __init_astman_append_buf | ( | void | ) | [static] |
thread local buffer for astman_append
Definition at line 2025 of file manager.c.
| static void __init_manager_event_buf | ( | void | ) | [static] |
| static void __init_manager_event_funcbuf | ( | void | ) | [static] |
| static void __init_manager_hooks | ( | void | ) | [static] |
| static void __init_userevent_buf | ( | void | ) | [static] |
| static int action_aocmessage | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3800 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().
03801 { 03802 const char *channel = astman_get_header(m, "Channel"); 03803 const char *pchannel = astman_get_header(m, "ChannelPrefix"); 03804 const char *msgtype = astman_get_header(m, "MsgType"); 03805 const char *chargetype = astman_get_header(m, "ChargeType"); 03806 const char *currencyname = astman_get_header(m, "CurrencyName"); 03807 const char *currencyamount = astman_get_header(m, "CurrencyAmount"); 03808 const char *mult = astman_get_header(m, "CurrencyMultiplier"); 03809 const char *totaltype = astman_get_header(m, "TotalType"); 03810 const char *aocbillingid = astman_get_header(m, "AOCBillingId"); 03811 const char *association_id= astman_get_header(m, "ChargingAssociationId"); 03812 const char *association_num = astman_get_header(m, "ChargingAssociationNumber"); 03813 const char *association_plan = astman_get_header(m, "ChargingAssociationPlan"); 03814 03815 enum ast_aoc_type _msgtype; 03816 enum ast_aoc_charge_type _chargetype; 03817 enum ast_aoc_currency_multiplier _mult = AST_AOC_MULT_ONE; 03818 enum ast_aoc_total_type _totaltype = AST_AOC_TOTAL; 03819 enum ast_aoc_billing_id _billingid = AST_AOC_BILLING_NA; 03820 unsigned int _currencyamount = 0; 03821 int _association_id = 0; 03822 unsigned int _association_plan = 0; 03823 struct ast_channel *chan = NULL; 03824 03825 struct ast_aoc_decoded *decoded = NULL; 03826 struct ast_aoc_encoded *encoded = NULL; 03827 size_t encoded_size = 0; 03828 03829 if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) { 03830 astman_send_error(s, m, "Channel and PartialChannel are not specified. Specify at least one of these."); 03831 goto aocmessage_cleanup; 03832 } 03833 03834 if (!(chan = ast_channel_get_by_name(channel)) && !ast_strlen_zero(pchannel)) { 03835 chan = ast_channel_get_by_name_prefix(pchannel, strlen(pchannel)); 03836 } 03837 03838 if (!chan) { 03839 astman_send_error(s, m, "No such channel"); 03840 goto aocmessage_cleanup; 03841 } 03842 03843 if (ast_strlen_zero(msgtype) || (strcasecmp(msgtype, "d") && strcasecmp(msgtype, "e"))) { 03844 astman_send_error(s, m, "Invalid MsgType"); 03845 goto aocmessage_cleanup; 03846 } 03847 03848 if (ast_strlen_zero(chargetype)) { 03849 astman_send_error(s, m, "ChargeType not specified"); 03850 goto aocmessage_cleanup; 03851 } 03852 03853 _msgtype = strcasecmp(msgtype, "d") ? AST_AOC_E : AST_AOC_D; 03854 03855 if (!strcasecmp(chargetype, "NA")) { 03856 _chargetype = AST_AOC_CHARGE_NA; 03857 } else if (!strcasecmp(chargetype, "Free")) { 03858 _chargetype = AST_AOC_CHARGE_FREE; 03859 } else if (!strcasecmp(chargetype, "Currency")) { 03860 _chargetype = AST_AOC_CHARGE_CURRENCY; 03861 } else if (!strcasecmp(chargetype, "Unit")) { 03862 _chargetype = AST_AOC_CHARGE_UNIT; 03863 } else { 03864 astman_send_error(s, m, "Invalid ChargeType"); 03865 goto aocmessage_cleanup; 03866 } 03867 03868 if (_chargetype == AST_AOC_CHARGE_CURRENCY) { 03869 03870 if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u", &_currencyamount) != 1)) { 03871 astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency"); 03872 goto aocmessage_cleanup; 03873 } 03874 03875 if (ast_strlen_zero(mult)) { 03876 astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency."); 03877 goto aocmessage_cleanup; 03878 } else if (!strcasecmp(mult, "onethousandth")) { 03879 _mult = AST_AOC_MULT_ONETHOUSANDTH; 03880 } else if (!strcasecmp(mult, "onehundredth")) { 03881 _mult = AST_AOC_MULT_ONEHUNDREDTH; 03882 } else if (!strcasecmp(mult, "onetenth")) { 03883 _mult = AST_AOC_MULT_ONETENTH; 03884 } else if (!strcasecmp(mult, "one")) { 03885 _mult = AST_AOC_MULT_ONE; 03886 } else if (!strcasecmp(mult, "ten")) { 03887 _mult = AST_AOC_MULT_TEN; 03888 } else if (!strcasecmp(mult, "hundred")) { 03889 _mult = AST_AOC_MULT_HUNDRED; 03890 } else if (!strcasecmp(mult, "thousand")) { 03891 _mult = AST_AOC_MULT_THOUSAND; 03892 } else { 03893 astman_send_error(s, m, "Invalid ChargeMultiplier"); 03894 goto aocmessage_cleanup; 03895 } 03896 } 03897 03898 /* create decoded object and start setting values */ 03899 if (!(decoded = ast_aoc_create(_msgtype, _chargetype, 0))) { 03900 astman_send_error(s, m, "Message Creation Failed"); 03901 goto aocmessage_cleanup; 03902 } 03903 03904 if (_msgtype == AST_AOC_D) { 03905 if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype, "subtotal")) { 03906 _totaltype = AST_AOC_SUBTOTAL; 03907 } 03908 03909 if (ast_strlen_zero(aocbillingid)) { 03910 /* ignore this is optional */ 03911 } else if (!strcasecmp(aocbillingid, "Normal")) { 03912 _billingid = AST_AOC_BILLING_NORMAL; 03913 } else if (!strcasecmp(aocbillingid, "ReverseCharge")) { 03914 _billingid = AST_AOC_BILLING_REVERSE_CHARGE; 03915 } else if (!strcasecmp(aocbillingid, "CreditCard")) { 03916 _billingid = AST_AOC_BILLING_CREDIT_CARD; 03917 } else { 03918 astman_send_error(s, m, "Invalid AOC-D AOCBillingId"); 03919 goto aocmessage_cleanup; 03920 } 03921 } else { 03922 if (ast_strlen_zero(aocbillingid)) { 03923 /* ignore this is optional */ 03924 } else if (!strcasecmp(aocbillingid, "Normal")) { 03925 _billingid = AST_AOC_BILLING_NORMAL; 03926 } else if (!strcasecmp(aocbillingid, "ReverseCharge")) { 03927 _billingid = AST_AOC_BILLING_REVERSE_CHARGE; 03928 } else if (!strcasecmp(aocbillingid, "CreditCard")) { 03929 _billingid = AST_AOC_BILLING_CREDIT_CARD; 03930 } else if (!strcasecmp(aocbillingid, "CallFwdUnconditional")) { 03931 _billingid = AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL; 03932 } else if (!strcasecmp(aocbillingid, "CallFwdBusy")) { 03933 _billingid = AST_AOC_BILLING_CALL_FWD_BUSY; 03934 } else if (!strcasecmp(aocbillingid, "CallFwdNoReply")) { 03935 _billingid = AST_AOC_BILLING_CALL_FWD_NO_REPLY; 03936 } else if (!strcasecmp(aocbillingid, "CallDeflection")) { 03937 _billingid = AST_AOC_BILLING_CALL_DEFLECTION; 03938 } else if (!strcasecmp(aocbillingid, "CallTransfer")) { 03939 _billingid = AST_AOC_BILLING_CALL_TRANSFER; 03940 } else { 03941 astman_send_error(s, m, "Invalid AOC-E AOCBillingId"); 03942 goto aocmessage_cleanup; 03943 } 03944 03945 if (!ast_strlen_zero(association_id) && (sscanf(association_id, "%30d", &_association_id) != 1)) { 03946 astman_send_error(s, m, "Invalid ChargingAssociationId"); 03947 goto aocmessage_cleanup; 03948 } 03949 if (!ast_strlen_zero(association_plan) && (sscanf(association_plan, "%30u", &_association_plan) != 1)) { 03950 astman_send_error(s, m, "Invalid ChargingAssociationPlan"); 03951 goto aocmessage_cleanup; 03952 } 03953 03954 if (_association_id) { 03955 ast_aoc_set_association_id(decoded, _association_id); 03956 } else if (!ast_strlen_zero(association_num)) { 03957 ast_aoc_set_association_number(decoded, association_num, _association_plan); 03958 } 03959 } 03960 03961 if (_chargetype == AST_AOC_CHARGE_CURRENCY) { 03962 ast_aoc_set_currency_info(decoded, _currencyamount, _mult, ast_strlen_zero(currencyname) ? NULL : currencyname); 03963 } else if (_chargetype == AST_AOC_CHARGE_UNIT) { 03964 struct ast_aoc_unit_entry entry; 03965 int i; 03966 03967 /* multiple unit entries are possible, lets get them all */ 03968 for (i = 0; i < 32; i++) { 03969 if (aocmessage_get_unit_entry(m, &entry, i)) { 03970 break; /* that's the end then */ 03971 } 03972 03973 ast_aoc_add_unit_entry(decoded, entry.valid_amount, entry.amount, entry.valid_type, entry.type); 03974 } 03975 03976 /* at least one unit entry is required */ 03977 if (!i) { 03978 astman_send_error(s, m, "Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit"); 03979 goto aocmessage_cleanup; 03980 } 03981 03982 } 03983 03984 ast_aoc_set_billing_id(decoded, _billingid); 03985 ast_aoc_set_total_type(decoded, _totaltype); 03986 03987 03988 if ((encoded = ast_aoc_encode(decoded, &encoded_size, NULL)) && !ast_indicate_data(chan, AST_CONTROL_AOC, encoded, encoded_size)) { 03989 astman_send_ack(s, m, "AOC Message successfully queued on channel"); 03990 } else { 03991 astman_send_error(s, m, "Error encoding AOC message, could not queue onto channel"); 03992 } 03993 03994 aocmessage_cleanup: 03995 03996 ast_aoc_destroy_decoded(decoded); 03997 ast_aoc_destroy_encoded(encoded); 03998 03999 if (chan) { 04000 chan = ast_channel_unref(chan); 04001 } 04002 return 0; 04003 }
| static int action_atxfer | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3546 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().
03547 { 03548 const char *name = astman_get_header(m, "Channel"); 03549 const char *exten = astman_get_header(m, "Exten"); 03550 const char *context = astman_get_header(m, "Context"); 03551 struct ast_channel *chan = NULL; 03552 struct ast_call_feature *atxfer_feature = NULL; 03553 char *feature_code = NULL; 03554 03555 if (ast_strlen_zero(name)) { 03556 astman_send_error(s, m, "No channel specified"); 03557 return 0; 03558 } 03559 if (ast_strlen_zero(exten)) { 03560 astman_send_error(s, m, "No extension specified"); 03561 return 0; 03562 } 03563 03564 if (!(atxfer_feature = ast_find_call_feature("atxfer"))) { 03565 astman_send_error(s, m, "No attended transfer feature found"); 03566 return 0; 03567 } 03568 03569 if (!(chan = ast_channel_get_by_name(name))) { 03570 astman_send_error(s, m, "Channel specified does not exist"); 03571 return 0; 03572 } 03573 03574 if (!ast_strlen_zero(context)) { 03575 pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context); 03576 } 03577 03578 for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) { 03579 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code }; 03580 ast_queue_frame(chan, &f); 03581 } 03582 03583 for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) { 03584 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code }; 03585 ast_queue_frame(chan, &f); 03586 } 03587 03588 chan = ast_channel_unref(chan); 03589 03590 astman_send_ack(s, m, "Atxfer successfully queued"); 03591 03592 return 0; 03593 }
| static int action_challenge | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3112 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().
03113 { 03114 const char *authtype = astman_get_header(m, "AuthType"); 03115 03116 if (!strcasecmp(authtype, "MD5")) { 03117 if (ast_strlen_zero(s->session->challenge)) { 03118 snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random()); 03119 } 03120 mansession_lock(s); 03121 astman_start_ack(s, m); 03122 astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge); 03123 mansession_unlock(s); 03124 } else { 03125 astman_send_error(s, m, "Must specify AuthType"); 03126 } 03127 return 0; 03128 }
| static int action_command | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Manager command "command" - execute CLI command.
Definition at line 3631 of file manager.c.
References ast_calloc, ast_cli_command, ast_free, ast_log(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), check_blacklist(), errno, LOG_WARNING, S_OR, and term_strip().
Referenced by __init_manager().
03632 { 03633 const char *cmd = astman_get_header(m, "Command"); 03634 const char *id = astman_get_header(m, "ActionID"); 03635 char *buf, *final_buf; 03636 char template[] = "/tmp/ast-ami-XXXXXX"; /* template for temporary file */ 03637 int fd; 03638 off_t l; 03639 03640 if (ast_strlen_zero(cmd)) { 03641 astman_send_error(s, m, "No command provided"); 03642 return 0; 03643 } 03644 03645 if (check_blacklist(cmd)) { 03646 astman_send_error(s, m, "Command blacklisted"); 03647 return 0; 03648 } 03649 03650 fd = mkstemp(template); 03651 03652 astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n"); 03653 if (!ast_strlen_zero(id)) { 03654 astman_append(s, "ActionID: %s\r\n", id); 03655 } 03656 /* FIXME: Wedge a ActionID response in here, waiting for later changes */ 03657 ast_cli_command(fd, cmd); /* XXX need to change this to use a FILE * */ 03658 l = lseek(fd, 0, SEEK_END); /* how many chars available */ 03659 03660 /* This has a potential to overflow the stack. Hence, use the heap. */ 03661 buf = ast_calloc(1, l + 1); 03662 final_buf = ast_calloc(1, l + 1); 03663 if (buf) { 03664 lseek(fd, 0, SEEK_SET); 03665 if (read(fd, buf, l) < 0) { 03666 ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); 03667 } 03668 buf[l] = '\0'; 03669 if (final_buf) { 03670 term_strip(final_buf, buf, l); 03671 final_buf[l] = '\0'; 03672 } 03673 astman_append(s, "%s", S_OR(final_buf, buf)); 03674 ast_free(buf); 03675 } 03676 close(fd); 03677 unlink(template); 03678 astman_append(s, "--END COMMAND--\r\n\r\n"); 03679 if (final_buf) { 03680 ast_free(final_buf); 03681 } 03682 return 0; 03683 }
| static int action_coresettings | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show PBX core settings information.
Definition at line 4454 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().
04455 { 04456 const char *actionid = astman_get_header(m, "ActionID"); 04457 char idText[150]; 04458 04459 if (!ast_strlen_zero(actionid)) { 04460 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04461 } else { 04462 idText[0] = '\0'; 04463 } 04464 04465 astman_append(s, "Response: Success\r\n" 04466 "%s" 04467 "AMIversion: %s\r\n" 04468 "AsteriskVersion: %s\r\n" 04469 "SystemName: %s\r\n" 04470 "CoreMaxCalls: %d\r\n" 04471 "CoreMaxLoadAvg: %f\r\n" 04472 "CoreRunUser: %s\r\n" 04473 "CoreRunGroup: %s\r\n" 04474 "CoreMaxFilehandles: %d\r\n" 04475 "CoreRealTimeEnabled: %s\r\n" 04476 "CoreCDRenabled: %s\r\n" 04477 "CoreHTTPenabled: %s\r\n" 04478 "\r\n", 04479 idText, 04480 AMI_VERSION, 04481 ast_get_version(), 04482 ast_config_AST_SYSTEM_NAME, 04483 option_maxcalls, 04484 option_maxload, 04485 ast_config_AST_RUN_USER, 04486 ast_config_AST_RUN_GROUP, 04487 option_maxfiles, 04488 AST_CLI_YESNO(ast_realtime_enabled()), 04489 AST_CLI_YESNO(check_cdr_enabled()), 04490 AST_CLI_YESNO(check_webmanager_enabled()) 04491 ); 04492 return 0; 04493 }
| 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 4551 of file manager.c.
References ast_channel::_state, ast_channel::appl, ast_bridged_channel(), ast_channel_accountcode(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_name(), ast_channel_uniqueid(), 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().
04552 { 04553 const char *actionid = astman_get_header(m, "ActionID"); 04554 char idText[256]; 04555 struct ast_channel *c = NULL; 04556 int numchans = 0; 04557 int duration, durh, durm, durs; 04558 struct ast_channel_iterator *iter; 04559 04560 if (!ast_strlen_zero(actionid)) { 04561 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04562 } else { 04563 idText[0] = '\0'; 04564 } 04565 04566 if (!(iter = ast_channel_iterator_all_new())) { 04567 astman_send_error(s, m, "Memory Allocation Failure"); 04568 return 1; 04569 } 04570 04571 astman_send_listack(s, m, "Channels will follow", "start"); 04572 04573 for (; (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) { 04574 struct ast_channel *bc; 04575 char durbuf[10] = ""; 04576 04577 ast_channel_lock(c); 04578 04579 bc = ast_bridged_channel(c); 04580 if (c->cdr && !ast_tvzero(c->cdr->start)) { 04581 duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000); 04582 durh = duration / 3600; 04583 durm = (duration % 3600) / 60; 04584 durs = duration % 60; 04585 snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs); 04586 } 04587 04588 astman_append(s, 04589 "Event: CoreShowChannel\r\n" 04590 "%s" 04591 "Channel: %s\r\n" 04592 "UniqueID: %s\r\n" 04593 "Context: %s\r\n" 04594 "Extension: %s\r\n" 04595 "Priority: %d\r\n" 04596 "ChannelState: %d\r\n" 04597 "ChannelStateDesc: %s\r\n" 04598 "Application: %s\r\n" 04599 "ApplicationData: %s\r\n" 04600 "CallerIDnum: %s\r\n" 04601 "CallerIDname: %s\r\n" 04602 "ConnectedLineNum: %s\r\n" 04603 "ConnectedLineName: %s\r\n" 04604 "Duration: %s\r\n" 04605 "AccountCode: %s\r\n" 04606 "BridgedChannel: %s\r\n" 04607 "BridgedUniqueID: %s\r\n" 04608 "\r\n", idText, ast_channel_name(c), ast_channel_uniqueid(c), c->context, c->exten, c->priority, c->_state, 04609 ast_state2str(c->_state), c->appl ? c->appl : "", c->data ? S_OR(c->data, "") : "", 04610 S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""), 04611 S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""), 04612 S_COR(c->connected.id.number.valid, c->connected.id.number.str, ""), 04613 S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""), 04614 durbuf, S_OR(ast_channel_accountcode(c), ""), bc ? ast_channel_name(bc) : "", bc ? ast_channel_uniqueid(bc) : ""); 04615 04616 ast_channel_unlock(c); 04617 04618 numchans++; 04619 } 04620 04621 astman_append(s, 04622 "Event: CoreShowChannelsComplete\r\n" 04623 "EventList: Complete\r\n" 04624 "ListItems: %d\r\n" 04625 "%s" 04626 "\r\n", numchans, idText); 04627 04628 ast_channel_iterator_destroy(iter); 04629 04630 return 0; 04631 }
| static int action_corestatus | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Show PBX core status information.
Definition at line 4496 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().
04497 { 04498 const char *actionid = astman_get_header(m, "ActionID"); 04499 char idText[150]; 04500 char startuptime[150], startupdate[150]; 04501 char reloadtime[150], reloaddate[150]; 04502 struct ast_tm tm; 04503 04504 if (!ast_strlen_zero(actionid)) { 04505 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04506 } else { 04507 idText[0] = '\0'; 04508 } 04509 04510 ast_localtime(&ast_startuptime, &tm, NULL); 04511 ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm); 04512 ast_strftime(startupdate, sizeof(startupdate), "%Y-%m-%d", &tm); 04513 ast_localtime(&ast_lastreloadtime, &tm, NULL); 04514 ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm); 04515 ast_strftime(reloaddate, sizeof(reloaddate), "%Y-%m-%d", &tm); 04516 04517 astman_append(s, "Response: Success\r\n" 04518 "%s" 04519 "CoreStartupDate: %s\r\n" 04520 "CoreStartupTime: %s\r\n" 04521 "CoreReloadDate: %s\r\n" 04522 "CoreReloadTime: %s\r\n" 04523 "CoreCurrentCalls: %d\r\n" 04524 "\r\n", 04525 idText, 04526 startupdate, 04527 startuptime, 04528 reloaddate, 04529 reloadtime, 04530 ast_active_channels() 04531 ); 04532 return 0; 04533 }
| static int action_createconfig | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2888 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().
02889 { 02890 int fd; 02891 const char *fn = astman_get_header(m, "Filename"); 02892 struct ast_str *filepath = ast_str_alloca(PATH_MAX); 02893 ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR); 02894 ast_str_append(&filepath, 0, "%s", fn); 02895 02896 if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) { 02897 close(fd); 02898 astman_send_ack(s, m, "New configuration file created successfully"); 02899 } else { 02900 astman_send_error(s, m, strerror(errno)); 02901 } 02902 02903 return 0; 02904 }
| static void action_destroy | ( | void * | obj | ) | [static] |
Definition at line 5369 of file manager.c.
References ast_string_field_free_memory.
Referenced by ast_manager_register2().
05370 { 05371 struct manager_action *doomed = obj; 05372 05373 if (doomed->synopsis) { 05374 /* The string fields were initialized. */ 05375 ast_string_field_free_memory(doomed); 05376 } 05377 }
| static int action_events | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3031 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().
03032 { 03033 const char *mask = astman_get_header(m, "EventMask"); 03034 int res, x; 03035 const char *id = astman_get_header(m, "ActionID"); 03036 char id_text[256]; 03037 03038 if (!ast_strlen_zero(id)) { 03039 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id); 03040 } else { 03041 id_text[0] = '\0'; 03042 } 03043 03044 res = set_eventmask(s, mask); 03045 if (broken_events_action) { 03046 /* if this option is set we should not return a response on 03047 * error, or when all events are set */ 03048 03049 if (res > 0) { 03050 for (x = 0; x < ARRAY_LEN(perms); x++) { 03051 if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) { 03052 return 0; 03053 } 03054 } 03055 astman_append(s, "Response: Success\r\n%s" 03056 "Events: On\r\n\r\n", id_text); 03057 } else if (res == 0) 03058 astman_append(s, "Response: Success\r\n%s" 03059 "Events: Off\r\n\r\n", id_text); 03060 return 0; 03061 } 03062 03063 if (res > 0) 03064 astman_append(s, "Response: Success\r\n%s" 03065 "Events: On\r\n\r\n", id_text); 03066 else if (res == 0) 03067 astman_append(s, "Response: Success\r\n%s" 03068 "Events: Off\r\n\r\n", id_text); 03069 else 03070 astman_send_error(s, m, "Invalid event mask"); 03071 03072 return 0; 03073 }
| static int action_extensionstate | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4210 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().
04211 { 04212 const char *exten = astman_get_header(m, "Exten"); 04213 const char *context = astman_get_header(m, "Context"); 04214 char hint[256] = ""; 04215 int status; 04216 if (ast_strlen_zero(exten)) { 04217 astman_send_error(s, m, "Extension not specified"); 04218 return 0; 04219 } 04220 if (ast_strlen_zero(context)) { 04221 context = "default"; 04222 } 04223 status = ast_extension_state(NULL, context, exten); 04224 ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten); 04225 astman_start_ack(s, m); 04226 astman_append(s, "Message: Extension Status\r\n" 04227 "Exten: %s\r\n" 04228 "Context: %s\r\n" 04229 "Hint: %s\r\n" 04230 "Status: %d\r\n\r\n", 04231 exten, context, hint, status); 04232 return 0; 04233 }
| static int action_filter | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4302 of file manager.c.
References astman_get_header(), astman_send_ack(), astman_send_error(), mansession_session::blackfilters, filter(), FILTER_ALLOC_FAILED, FILTER_COMPILE_FAIL, FILTER_SUCCESS, manager_add_filter(), mansession::session, and mansession_session::whitefilters.
Referenced by __init_manager().
04303 { 04304 const char *filter = astman_get_header(m, "Filter"); 04305 const char *operation = astman_get_header(m, "Operation"); 04306 int res; 04307 04308 if (!strcasecmp(operation, "Add")) { 04309 res = manager_add_filter(filter, s->session->whitefilters, s->session->blackfilters); 04310 04311 if (res != FILTER_SUCCESS) { 04312 if (res == FILTER_ALLOC_FAILED) { 04313 astman_send_error(s, m, "Internal Error. Failed to allocate regex for filter"); 04314 return 0; 04315 } else if (res == FILTER_COMPILE_FAIL) { 04316 astman_send_error(s, m, "Filter did not compile. Check the syntax of the filter given."); 04317 return 0; 04318 } else { 04319 astman_send_error(s, m, "Internal Error. Failed adding filter."); 04320 return 0; 04321 } 04322 } 04323 04324 astman_send_ack(s, m, "Success"); 04325 return 0; 04326 } 04327 04328 astman_send_error(s, m, "Unknown operation"); 04329 return 0; 04330 }
| static struct manager_action* action_find | ( | const char * | name | ) | [static, read] |
Definition at line 1100 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().
01101 { 01102 struct manager_action *act; 01103 01104 AST_RWLIST_RDLOCK(&actions); 01105 AST_RWLIST_TRAVERSE(&actions, act, list) { 01106 if (!strcasecmp(name, act->action)) { 01107 ao2_t_ref(act, +1, "found action object"); 01108 break; 01109 } 01110 } 01111 AST_RWLIST_UNLOCK(&actions); 01112 01113 return act; 01114 }
| static int action_getconfig | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2506 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().
02507 { 02508 struct ast_config *cfg; 02509 const char *fn = astman_get_header(m, "Filename"); 02510 const char *category = astman_get_header(m, "Category"); 02511 int catcount = 0; 02512 int lineno = 0; 02513 char *cur_category = NULL; 02514 struct ast_variable *v; 02515 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02516 02517 if (ast_strlen_zero(fn)) { 02518 astman_send_error(s, m, "Filename not specified"); 02519 return 0; 02520 } 02521 cfg = ast_config_load2(fn, "manager", config_flags); 02522 if (cfg == CONFIG_STATUS_FILEMISSING) { 02523 astman_send_error(s, m, "Config file not found"); 02524 return 0; 02525 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02526 astman_send_error(s, m, "Config file has invalid format"); 02527 return 0; 02528 } 02529 02530 astman_start_ack(s, m); 02531 while ((cur_category = ast_category_browse(cfg, cur_category))) { 02532 if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) { 02533 lineno = 0; 02534 astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category); 02535 for (v = ast_variable_browse(cfg, cur_category); v; v = v->next) { 02536 astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value); 02537 } 02538 catcount++; 02539 } 02540 } 02541 if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */ 02542 astman_append(s, "No categories found\r\n"); 02543 } 02544 ast_config_destroy(cfg); 02545 astman_append(s, "\r\n"); 02546 02547 return 0; 02548 }
| static int action_getconfigjson | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2616 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().
02617 { 02618 struct ast_config *cfg; 02619 const char *fn = astman_get_header(m, "Filename"); 02620 char *category = NULL; 02621 struct ast_variable *v; 02622 int comma1 = 0; 02623 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02624 02625 if (ast_strlen_zero(fn)) { 02626 astman_send_error(s, m, "Filename not specified"); 02627 return 0; 02628 } 02629 02630 if (!(cfg = ast_config_load2(fn, "manager", config_flags))) { 02631 astman_send_error(s, m, "Config file not found"); 02632 return 0; 02633 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02634 astman_send_error(s, m, "Config file has invalid format"); 02635 return 0; 02636 } 02637 02638 astman_start_ack(s, m); 02639 astman_append(s, "JSON: {"); 02640 while ((category = ast_category_browse(cfg, category))) { 02641 int comma2 = 0; 02642 02643 astman_append(s, "%s\"", comma1 ? "," : ""); 02644 astman_append_json(s, category); 02645 astman_append(s, "\":["); 02646 comma1 = 1; 02647 for (v = ast_variable_browse(cfg, category); v; v = v->next) { 02648 astman_append(s, "%s\"", comma2 ? "," : ""); 02649 astman_append_json(s, v->name); 02650 astman_append(s, "\":\""); 02651 astman_append_json(s, v->value); 02652 astman_append(s, "\""); 02653 comma2 = 1; 02654 } 02655 astman_append(s, "]"); 02656 } 02657 astman_append(s, "}\r\n\r\n"); 02658 02659 ast_config_destroy(cfg); 02660 02661 return 0; 02662 }
| static int action_getvar | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3206 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(), LOG_ERROR, pbx_retrieve_variable(), and S_OR.
Referenced by __init_manager().
03207 { 03208 struct ast_channel *c = NULL; 03209 const char *name = astman_get_header(m, "Channel"); 03210 const char *varname = astman_get_header(m, "Variable"); 03211 char *varval; 03212 char workspace[1024]; 03213 03214 if (ast_strlen_zero(varname)) { 03215 astman_send_error(s, m, "No variable specified"); 03216 return 0; 03217 } 03218 03219 if (!ast_strlen_zero(name)) { 03220 if (!(c = ast_channel_get_by_name(name))) { 03221 astman_send_error(s, m, "No such channel"); 03222 return 0; 03223 } 03224 } 03225 03226 workspace[0] = '\0'; 03227 if (varname[strlen(varname) - 1] == ')') { 03228 if (!c) { 03229 c = ast_dummy_channel_alloc(); 03230 if (c) { 03231 ast_func_read(c, (char *) varname, workspace, sizeof(workspace)); 03232 } else 03233 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03234 } else { 03235 ast_func_read(c, (char *) varname, workspace, sizeof(workspace)); 03236 } 03237 varval = workspace; 03238 } else { 03239 pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL); 03240 } 03241 03242 if (c) { 03243 c = ast_channel_unref(c); 03244 } 03245 03246 astman_start_ack(s, m); 03247 astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, S_OR(varval, "")); 03248 03249 return 0; 03250 }
| static int action_hangup | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3130 of file manager.c.
References ast_channel_get_by_name(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_debug, ast_log(), AST_SOFTHANGUP_EXPLICIT, ast_softhangup_nolock(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), cause, ast_channel::hangupcause, and LOG_NOTICE.
Referenced by __init_manager().
03131 { 03132 struct ast_channel *c = NULL; 03133 int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */ 03134 const char *name = astman_get_header(m, "Channel"); 03135 const char *cause = astman_get_header(m, "Cause"); 03136 03137 if (ast_strlen_zero(name)) { 03138 astman_send_error(s, m, "No channel specified"); 03139 return 0; 03140 } 03141 03142 if (!ast_strlen_zero(cause)) { 03143 char *endptr; 03144 causecode = strtol(cause, &endptr, 10); 03145 if (causecode < 0 || causecode > 127 || *endptr != '\0') { 03146 ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause); 03147 /* keep going, better to hangup without cause than to not hang up at all */ 03148 causecode = 0; /* do not set channel's hangupcause */ 03149 } 03150 } 03151 03152 if (!(c = ast_channel_get_by_name(name))) { 03153 astman_send_error(s, m, "No such channel"); 03154 return 0; 03155 } 03156 03157 ast_channel_lock(c); 03158 if (causecode > 0) { 03159 ast_debug(1, "Setting hangupcause of channel %s to %d (is %d now)\n", 03160 ast_channel_name(c), causecode, c->hangupcause); 03161 c->hangupcause = causecode; 03162 } 03163 ast_softhangup_nolock(c, AST_SOFTHANGUP_EXPLICIT); 03164 ast_channel_unlock(c); 03165 03166 c = ast_channel_unref(c); 03167 03168 astman_send_ack(s, m, "Channel Hungup"); 03169 03170 return 0; 03171 }
| static int action_listcategories | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2550 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().
02551 { 02552 struct ast_config *cfg; 02553 const char *fn = astman_get_header(m, "Filename"); 02554 char *category = NULL; 02555 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02556 int catcount = 0; 02557 02558 if (ast_strlen_zero(fn)) { 02559 astman_send_error(s, m, "Filename not specified"); 02560 return 0; 02561 } 02562 if (!(cfg = ast_config_load2(fn, "manager", config_flags))) { 02563 astman_send_error(s, m, "Config file not found"); 02564 return 0; 02565 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02566 astman_send_error(s, m, "Config file has invalid format"); 02567 return 0; 02568 } 02569 astman_start_ack(s, m); 02570 while ((category = ast_category_browse(cfg, category))) { 02571 astman_append(s, "Category-%06d: %s\r\n", catcount, category); 02572 catcount++; 02573 } 02574 if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */ 02575 astman_append(s, "Error: no categories found\r\n"); 02576 } 02577 ast_config_destroy(cfg); 02578 astman_append(s, "\r\n"); 02579 02580 return 0; 02581 }
| static int action_listcommands | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3012 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().
03013 { 03014 struct manager_action *cur; 03015 struct ast_str *temp = ast_str_alloca(256); 03016 03017 astman_start_ack(s, m); 03018 AST_RWLIST_RDLOCK(&actions); 03019 AST_RWLIST_TRAVERSE(&actions, cur, list) { 03020 if ((s->session->writeperm & cur->authority) || cur->authority == 0) { 03021 astman_append(s, "%s: %s (Priv: %s)\r\n", 03022 cur->action, cur->synopsis, authority_to_str(cur->authority, &temp)); 03023 } 03024 } 03025 AST_RWLIST_UNLOCK(&actions); 03026 astman_append(s, "\r\n"); 03027 03028 return 0; 03029 }
| static int action_login | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3081 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().
03082 { 03083 03084 /* still authenticated - don't process again */ 03085 if (s->session->authenticated) { 03086 astman_send_ack(s, m, "Already authenticated"); 03087 return 0; 03088 } 03089 03090 if (authenticate(s, m)) { 03091 sleep(1); 03092 astman_send_error(s, m, "Authentication failed"); 03093 return -1; 03094 } 03095 s->session->authenticated = 1; 03096 ast_atomic_fetchadd_int(&unauth_sessions, -1); 03097 if (manager_displayconnects(s->session)) { 03098 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)); 03099 } 03100 astman_send_ack(s, m, "Authentication accepted"); 03101 if ((s->session->send_events & EVENT_FLAG_SYSTEM) 03102 && ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 03103 struct ast_str *auth = ast_str_alloca(80); 03104 const char *cat_str = authority_to_str(EVENT_FLAG_SYSTEM, &auth); 03105 astman_append(s, "Event: FullyBooted\r\n" 03106 "Privilege: %s\r\n" 03107 "Status: Fully Booted\r\n\r\n", cat_str); 03108 } 03109 return 0; 03110 }
| static int action_logoff | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3075 of file manager.c.
References astman_send_response().
Referenced by __init_manager().
03076 { 03077 astman_send_response(s, m, "Goodbye", "Thanks for all the fish."); 03078 return -1; 03079 }
| static int action_mailboxcount | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4189 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().
04190 { 04191 const char *mailbox = astman_get_header(m, "Mailbox"); 04192 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;; 04193 04194 if (ast_strlen_zero(mailbox)) { 04195 astman_send_error(s, m, "Mailbox not specified"); 04196 return 0; 04197 } 04198 ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs); 04199 astman_start_ack(s, m); 04200 astman_append(s, "Message: Mailbox Message Count\r\n" 04201 "Mailbox: %s\r\n" 04202 "UrgMessages: %d\r\n" 04203 "NewMessages: %d\r\n" 04204 "OldMessages: %d\r\n" 04205 "\r\n", 04206 mailbox, urgentmsgs, newmsgs, oldmsgs); 04207 return 0; 04208 }
| static int action_mailboxstatus | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4172 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().
04173 { 04174 const char *mailbox = astman_get_header(m, "Mailbox"); 04175 int ret; 04176 04177 if (ast_strlen_zero(mailbox)) { 04178 astman_send_error(s, m, "Mailbox not specified"); 04179 return 0; 04180 } 04181 ret = ast_app_has_voicemail(mailbox, NULL); 04182 astman_start_ack(s, m); 04183 astman_append(s, "Message: Mailbox Status\r\n" 04184 "Mailbox: %s\r\n" 04185 "Waiting: %d\r\n\r\n", mailbox, ret); 04186 return 0; 04187 }
| static int action_originate | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4005 of file manager.c.
References app, ast_callerid_parse(), ast_calloc, ast_copy_string(), ast_exists_extension(), ast_findlabel_extension(), ast_format_cap_add(), ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_format_cap_remove_all(), ast_format_set(), 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(), fast_originate_helper::cap, cid_name, cid_num, context, ast_frame::data, destroy_fast_originate_helper(), EVENT_FLAG_SYSTEM, exten, fast_originate(), fast_originate_helper::priority, mansession::session, strcasestr(), fast_originate_helper::timeout, fast_originate_helper::vars, and mansession_session::writeperm.
Referenced by __init_manager().
04006 { 04007 const char *name = astman_get_header(m, "Channel"); 04008 const char *exten = astman_get_header(m, "Exten"); 04009 const char *context = astman_get_header(m, "Context"); 04010 const char *priority = astman_get_header(m, "Priority"); 04011 const char *timeout = astman_get_header(m, "Timeout"); 04012 const char *callerid = astman_get_header(m, "CallerID"); 04013 const char *account = astman_get_header(m, "Account"); 04014 const char *app = astman_get_header(m, "Application"); 04015 const char *appdata = astman_get_header(m, "Data"); 04016 const char *async = astman_get_header(m, "Async"); 04017 const char *id = astman_get_header(m, "ActionID"); 04018 const char *codecs = astman_get_header(m, "Codecs"); 04019 struct ast_variable *vars; 04020 char *tech, *data; 04021 char *l = NULL, *n = NULL; 04022 int pi = 0; 04023 int res; 04024 int to = 30000; 04025 int reason = 0; 04026 char tmp[256]; 04027 char tmp2[256]; 04028 struct ast_format_cap *cap = ast_format_cap_alloc_nolock(); 04029 struct ast_format tmp_fmt; 04030 pthread_t th; 04031 04032 if (!cap) { 04033 astman_send_error(s, m, "Internal Error. Memory allocation failure."); 04034 } 04035 ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0)); 04036 04037 if (ast_strlen_zero(name)) { 04038 astman_send_error(s, m, "Channel not specified"); 04039 res = 0; 04040 goto fast_orig_cleanup; 04041 } 04042 if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) { 04043 if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) { 04044 astman_send_error(s, m, "Invalid priority"); 04045 res = 0; 04046 goto fast_orig_cleanup; 04047 } 04048 } 04049 if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) { 04050 astman_send_error(s, m, "Invalid timeout"); 04051 res = 0; 04052 goto fast_orig_cleanup; 04053 } 04054 ast_copy_string(tmp, name, sizeof(tmp)); 04055 tech = tmp; 04056 data = strchr(tmp, '/'); 04057 if (!data) { 04058 astman_send_error(s, m, "Invalid channel"); 04059 res = 0; 04060 goto fast_orig_cleanup; 04061 } 04062 *data++ = '\0'; 04063 ast_copy_string(tmp2, callerid, sizeof(tmp2)); 04064 ast_callerid_parse(tmp2, &n, &l); 04065 if (n) { 04066 if (ast_strlen_zero(n)) { 04067 n = NULL; 04068 } 04069 } 04070 if (l) { 04071 ast_shrink_phone_number(l); 04072 if (ast_strlen_zero(l)) { 04073 l = NULL; 04074 } 04075 } 04076 if (!ast_strlen_zero(codecs)) { 04077 ast_format_cap_remove_all(cap); 04078 ast_parse_allow_disallow(NULL, cap, codecs, 1); 04079 } 04080 04081 if (!ast_strlen_zero(app)) { 04082 /* To run the System application (or anything else that goes to 04083 * shell), you must have the additional System privilege */ 04084 if (!(s->session->writeperm & EVENT_FLAG_SYSTEM) 04085 && ( 04086 strcasestr(app, "system") || /* System(rm -rf /) 04087 TrySystem(rm -rf /) */ 04088 strcasestr(app, "exec") || /* Exec(System(rm -rf /)) 04089 TryExec(System(rm -rf /)) */ 04090 strcasestr(app, "agi") || /* AGI(/bin/rm,-rf /) 04091 EAGI(/bin/rm,-rf /) */ 04092 strstr(appdata, "SHELL") || /* NoOp(${SHELL(rm -rf /)}) */ 04093 strstr(appdata, "EVAL") /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ 04094 )) { 04095 astman_send_error(s, m, "Originate with certain 'Application' arguments requires the additional System privilege, which you do not have."); 04096 res = 0; 04097 goto fast_orig_cleanup; 04098 } 04099 } 04100 04101 /* Check early if the extension exists. If not, we need to bail out here. */ 04102 if (exten && context && pi) { 04103 if (! ast_exists_extension(NULL, context, exten, pi, l)) { 04104 /* The extension does not exist. */ 04105 astman_send_error(s, m, "Extension does not exist."); 04106 res = 0; 04107 goto fast_orig_cleanup; 04108 } 04109 } 04110 04111 /* Allocate requested channel variables */ 04112 vars = astman_get_variables(m); 04113 04114 if (ast_true(async)) { 04115 struct fast_originate_helper *fast; 04116 04117 fast = ast_calloc(1, sizeof(*fast)); 04118 if (!fast || ast_string_field_init(fast, 252)) { 04119 ast_free(fast); 04120 ast_variables_destroy(vars); 04121 res = -1; 04122 } else { 04123 if (!ast_strlen_zero(id)) { 04124 ast_string_field_build(fast, idtext, "ActionID: %s\r\n", id); 04125 } 04126 ast_string_field_set(fast, tech, tech); 04127 ast_string_field_set(fast, data, data); 04128 ast_string_field_set(fast, app, app); 04129 ast_string_field_set(fast, appdata, appdata); 04130 ast_string_field_set(fast, cid_num, l); 04131 ast_string_field_set(fast, cid_name, n); 04132 ast_string_field_set(fast, context, context); 04133 ast_string_field_set(fast, exten, exten); 04134 ast_string_field_set(fast, account, account); 04135 fast->vars = vars; 04136 fast->cap = cap; 04137 cap = NULL; /* transfered originate helper the capabilities structure. It is now responsible for freeing it. */ 04138 fast->timeout = to; 04139 fast->priority = pi; 04140 if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) { 04141 destroy_fast_originate_helper(fast); 04142 res = -1; 04143 } else { 04144 res = 0; 04145 } 04146 } 04147 } else if (!ast_strlen_zero(app)) { 04148 res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL); 04149 /* Any vars memory was passed to ast_pbx_outgoing_app(). */ 04150 } else { 04151 if (exten && context && pi) { 04152 res = ast_pbx_outgoing_exten(tech, cap, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL); 04153 /* Any vars memory was passed to ast_pbx_outgoing_exten(). */ 04154 } else { 04155 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'"); 04156 ast_variables_destroy(vars); 04157 res = 0; 04158 goto fast_orig_cleanup; 04159 } 04160 } 04161 if (!res) { 04162 astman_send_ack(s, m, "Originate successfully queued"); 04163 } else { 04164 astman_send_error(s, m, "Originate failed"); 04165 } 04166 04167 fast_orig_cleanup: 04168 ast_format_cap_destroy(cap); 04169 return 0; 04170 }
| static int action_ping | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2488 of file manager.c.
References ast_strlen_zero(), ast_tvnow(), astman_append(), and astman_get_header().
Referenced by __init_manager().
02489 { 02490 const char *actionid = astman_get_header(m, "ActionID"); 02491 struct timeval now = ast_tvnow(); 02492 02493 astman_append(s, "Response: Success\r\n"); 02494 if (!ast_strlen_zero(actionid)){ 02495 astman_append(s, "ActionID: %s\r\n", actionid); 02496 } 02497 astman_append( 02498 s, 02499 "Ping: Pong\r\n" 02500 "Timestamp: %ld.%06lu\r\n" 02501 "\r\n", 02502 (long) now.tv_sec, (unsigned long) now.tv_usec); 02503 return 0; 02504 }
| static int action_redirect | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
action_redirect: The redirect manager command
Definition at line 3446 of file manager.c.
References ast_async_goto(), ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_check_hangup_locked(), ast_findlabel_extension(), AST_FLAG_BRIDGE_HANGUP_DONT, ast_set_flag, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), context, exten, ast_channel::pbx, and ast_channel::priority.
Referenced by __init_manager().
03447 { 03448 const char *name = astman_get_header(m, "Channel"); 03449 const char *name2 = astman_get_header(m, "ExtraChannel"); 03450 const char *exten = astman_get_header(m, "Exten"); 03451 const char *exten2 = astman_get_header(m, "ExtraExten"); 03452 const char *context = astman_get_header(m, "Context"); 03453 const char *context2 = astman_get_header(m, "ExtraContext"); 03454 const char *priority = astman_get_header(m, "Priority"); 03455 const char *priority2 = astman_get_header(m, "ExtraPriority"); 03456 struct ast_channel *chan, *chan2 = NULL; 03457 int pi, pi2 = 0; 03458 int res; 03459 03460 if (ast_strlen_zero(name)) { 03461 astman_send_error(s, m, "Channel not specified"); 03462 return 0; 03463 } 03464 03465 if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) { 03466 if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) { 03467 astman_send_error(s, m, "Invalid priority"); 03468 return 0; 03469 } 03470 } 03471 03472 if (!ast_strlen_zero(priority2) && (sscanf(priority2, "%30d", &pi2) != 1)) { 03473 if ((pi2 = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL)) < 1) { 03474 astman_send_error(s, m, "Invalid ExtraPriority"); 03475 return 0; 03476 } 03477 } 03478 03479 if (!(chan = ast_channel_get_by_name(name))) { 03480 char buf[256]; 03481 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name); 03482 astman_send_error(s, m, buf); 03483 return 0; 03484 } 03485 03486 if (ast_check_hangup_locked(chan)) { 03487 astman_send_error(s, m, "Redirect failed, channel not up."); 03488 chan = ast_channel_unref(chan); 03489 return 0; 03490 } 03491 03492 if (!ast_strlen_zero(name2)) { 03493 chan2 = ast_channel_get_by_name(name2); 03494 } 03495 03496 if (chan2 && ast_check_hangup_locked(chan2)) { 03497 astman_send_error(s, m, "Redirect failed, extra channel not up."); 03498 chan = ast_channel_unref(chan); 03499 chan2 = ast_channel_unref(chan2); 03500 return 0; 03501 } 03502 03503 if (chan->pbx) { 03504 ast_channel_lock(chan); 03505 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */ 03506 ast_channel_unlock(chan); 03507 } 03508 03509 res = ast_async_goto(chan, context, exten, pi); 03510 if (!res) { 03511 if (!ast_strlen_zero(name2)) { 03512 if (chan2) { 03513 if (chan2->pbx) { 03514 ast_channel_lock(chan2); 03515 ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */ 03516 ast_channel_unlock(chan2); 03517 } 03518 if (!ast_strlen_zero(context2)) { 03519 res = ast_async_goto(chan2, context2, exten2, pi2); 03520 } else { 03521 res = ast_async_goto(chan2, context, exten, pi); 03522 } 03523 } else { 03524 res = -1; 03525 } 03526 if (!res) { 03527 astman_send_ack(s, m, "Dual Redirect successful"); 03528 } else { 03529 astman_send_error(s, m, "Secondary redirect failed"); 03530 } 03531 } else { 03532 astman_send_ack(s, m, "Redirect successful"); 03533 } 03534 } else { 03535 astman_send_error(s, m, "Redirect failed"); 03536 } 03537 03538 chan = ast_channel_unref(chan); 03539 if (chan2) { 03540 chan2 = ast_channel_unref(chan2); 03541 } 03542 03543 return 0; 03544 }
| static int action_reload | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Send a reload event.
Definition at line 4536 of file manager.c.
References ast_module_reload(), astman_get_header(), astman_send_ack(), astman_send_error(), and S_OR.
Referenced by __init_manager().
04537 { 04538 const char *module = astman_get_header(m, "Module"); 04539 int res = ast_module_reload(S_OR(module, NULL)); 04540 04541 if (res == 2) { 04542 astman_send_ack(s, m, "Module Reloaded"); 04543 } else { 04544 astman_send_error(s, m, s == 0 ? "No such module" : "Module does not support reload"); 04545 } 04546 return 0; 04547 }
| static int action_sendtext | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3411 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().
03412 { 03413 struct ast_channel *c = NULL; 03414 const char *name = astman_get_header(m, "Channel"); 03415 const char *textmsg = astman_get_header(m, "Message"); 03416 int res = 0; 03417 03418 if (ast_strlen_zero(name)) { 03419 astman_send_error(s, m, "No channel specified"); 03420 return 0; 03421 } 03422 03423 if (ast_strlen_zero(textmsg)) { 03424 astman_send_error(s, m, "No Message specified"); 03425 return 0; 03426 } 03427 03428 if (!(c = ast_channel_get_by_name(name))) { 03429 astman_send_error(s, m, "No such channel"); 03430 return 0; 03431 } 03432 03433 res = ast_sendtext(c, textmsg); 03434 c = ast_channel_unref(c); 03435 03436 if (res >= 0) { 03437 astman_send_ack(s, m, "Success"); 03438 } else { 03439 astman_send_error(s, m, "Failure"); 03440 } 03441 03442 return res; 03443 }
| static int action_setvar | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 3173 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().
03174 { 03175 struct ast_channel *c = NULL; 03176 const char *name = astman_get_header(m, "Channel"); 03177 const char *varname = astman_get_header(m, "Variable"); 03178 const char *varval = astman_get_header(m, "Value"); 03179 int res = 0; 03180 03181 if (ast_strlen_zero(varname)) { 03182 astman_send_error(s, m, "No variable specified"); 03183 return 0; 03184 } 03185 03186 if (!ast_strlen_zero(name)) { 03187 if (!(c = ast_channel_get_by_name(name))) { 03188 astman_send_error(s, m, "No such channel"); 03189 return 0; 03190 } 03191 } 03192 03193 res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, "")); 03194 03195 if (c) { 03196 c = ast_channel_unref(c); 03197 } 03198 if (res == 0) { 03199 astman_send_ack(s, m, "Variable Set"); 03200 } else { 03201 astman_send_error(s, m, "Variable not set"); 03202 } 03203 return 0; 03204 }
| static int action_status | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Manager "status" command to show channels.
Definition at line 3254 of file manager.c.
References ast_channel::_bridge, ast_channel::_state, AST_APP_ARG, ast_channel_accountcode(), ast_channel_get_by_name(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_name(), ast_channel_uniqueid(), 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, 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, ast_cdr::start, ast_party_name::str, ast_party_number::str, str, ast_party_name::valid, and ast_party_number::valid.
Referenced by __init_manager().
03255 { 03256 const char *name = astman_get_header(m, "Channel"); 03257 const char *cvariables = astman_get_header(m, "Variables"); 03258 char *variables = ast_strdupa(S_OR(cvariables, "")); 03259 struct ast_channel *c; 03260 char bridge[256]; 03261 struct timeval now = ast_tvnow(); 03262 long elapsed_seconds = 0; 03263 int channels = 0; 03264 int all = ast_strlen_zero(name); /* set if we want all channels */ 03265 const char *id = astman_get_header(m, "ActionID"); 03266 char idText[256]; 03267 AST_DECLARE_APP_ARGS(vars, 03268 AST_APP_ARG(name)[100]; 03269 ); 03270 struct ast_str *str = ast_str_create(1000); 03271 struct ast_channel_iterator *iter = NULL; 03272 03273 if (!ast_strlen_zero(id)) { 03274 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 03275 } else { 03276 idText[0] = '\0'; 03277 } 03278 03279 if (all) { 03280 if (!(iter = ast_channel_iterator_all_new())) { 03281 ast_free(str); 03282 astman_send_error(s, m, "Memory Allocation Failure"); 03283 return 1; 03284 } 03285 c = ast_channel_iterator_next(iter); 03286 } else { 03287 if (!(c = ast_channel_get_by_name(name))) { 03288 astman_send_error(s, m, "No such channel"); 03289 ast_free(str); 03290 return 0; 03291 } 03292 } 03293 03294 astman_send_ack(s, m, "Channel status will follow"); 03295 03296 if (!ast_strlen_zero(cvariables)) { 03297 AST_STANDARD_APP_ARGS(vars, variables); 03298 } 03299 03300 /* if we look by name, we break after the first iteration */ 03301 for (; c; c = ast_channel_iterator_next(iter)) { 03302 ast_channel_lock(c); 03303 03304 if (!ast_strlen_zero(cvariables)) { 03305 int i; 03306 ast_str_reset(str); 03307 for (i = 0; i < vars.argc; i++) { 03308 char valbuf[512], *ret = NULL; 03309 03310 if (vars.name[i][strlen(vars.name[i]) - 1] == ')') { 03311 if (ast_func_read(c, vars.name[i], valbuf, sizeof(valbuf)) < 0) { 03312 valbuf[0] = '\0'; 03313 } 03314 ret = valbuf; 03315 } else { 03316 pbx_retrieve_variable(c, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL); 03317 } 03318 03319 ast_str_append(&str, 0, "Variable: %s=%s\r\n", vars.name[i], ret); 03320 } 03321 } 03322 03323 channels++; 03324 if (c->_bridge) { 03325 snprintf(bridge, sizeof(bridge), "BridgedChannel: %s\r\nBridgedUniqueid: %s\r\n", ast_channel_name(c->_bridge), ast_channel_uniqueid(c->_bridge)); 03326 } else { 03327 bridge[0] = '\0'; 03328 } 03329 if (c->pbx) { 03330 if (c->cdr) { 03331 elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec; 03332 } 03333 astman_append(s, 03334 "Event: Status\r\n" 03335 "Privilege: Call\r\n" 03336 "Channel: %s\r\n" 03337 "CallerIDNum: %s\r\n" 03338 "CallerIDName: %s\r\n" 03339 "ConnectedLineNum: %s\r\n" 03340 "ConnectedLineName: %s\r\n" 03341 "Accountcode: %s\r\n" 03342 "ChannelState: %d\r\n" 03343 "ChannelStateDesc: %s\r\n" 03344 "Context: %s\r\n" 03345 "Extension: %s\r\n" 03346 "Priority: %d\r\n" 03347 "Seconds: %ld\r\n" 03348 "%s" 03349 "Uniqueid: %s\r\n" 03350 "%s" 03351 "%s" 03352 "\r\n", 03353 ast_channel_name(c), 03354 S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"), 03355 S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"), 03356 S_COR(c->connected.id.number.valid, c->connected.id.number.str, "<unknown>"), 03357 S_COR(c->connected.id.name.valid, c->connected.id.name.str, "<unknown>"), 03358 ast_channel_accountcode(c), 03359 c->_state, 03360 ast_state2str(c->_state), c->context, 03361 c->exten, c->priority, (long)elapsed_seconds, bridge, ast_channel_uniqueid(c), ast_str_buffer(str), idText); 03362 } else { 03363 astman_append(s, 03364 "Event: Status\r\n" 03365 "Privilege: Call\r\n" 03366 "Channel: %s\r\n" 03367 "CallerIDNum: %s\r\n" 03368 "CallerIDName: %s\r\n" 03369 "ConnectedLineNum: %s\r\n" 03370 "ConnectedLineName: %s\r\n" 03371 "Account: %s\r\n" 03372 "State: %s\r\n" 03373 "%s" 03374 "Uniqueid: %s\r\n" 03375 "%s" 03376 "%s" 03377 "\r\n", 03378 ast_channel_name(c), 03379 S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"), 03380 S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"), 03381 S_COR(c->connected.id.number.valid, c->connected.id.number.str, "<unknown>"), 03382 S_COR(c->connected.id.name.valid, c->connected.id.name.str, "<unknown>"), 03383 ast_channel_accountcode(c), 03384 ast_state2str(c->_state), bridge, ast_channel_uniqueid(c), 03385 ast_str_buffer(str), idText); 03386 } 03387 03388 ast_channel_unlock(c); 03389 c = ast_channel_unref(c); 03390 03391 if (!all) { 03392 break; 03393 } 03394 } 03395 03396 if (iter) { 03397 ast_channel_iterator_destroy(iter); 03398 } 03399 03400 astman_append(s, 03401 "Event: StatusComplete\r\n" 03402 "%s" 03403 "Items: %d\r\n" 03404 "\r\n", idText, channels); 03405 03406 ast_free(str); 03407 03408 return 0; 03409 }
| static int action_timeout | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4235 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().
04236 { 04237 struct ast_channel *c; 04238 const char *name = astman_get_header(m, "Channel"); 04239 double timeout = atof(astman_get_header(m, "Timeout")); 04240 struct timeval when = { timeout, 0 }; 04241 04242 if (ast_strlen_zero(name)) { 04243 astman_send_error(s, m, "No channel specified"); 04244 return 0; 04245 } 04246 04247 if (!timeout || timeout < 0) { 04248 astman_send_error(s, m, "No timeout specified"); 04249 return 0; 04250 } 04251 04252 if (!(c = ast_channel_get_by_name(name))) { 04253 astman_send_error(s, m, "No such channel"); 04254 return 0; 04255 } 04256 04257 when.tv_usec = (timeout - when.tv_sec) * 1000000.0; 04258 04259 ast_channel_lock(c); 04260 ast_channel_setwhentohangup_tv(c, when); 04261 ast_channel_unlock(c); 04262 c = ast_channel_unref(c); 04263 04264 astman_send_ack(s, m, "Timeout Set"); 04265 04266 return 0; 04267 }
| static int action_updateconfig | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2810 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().
02811 { 02812 struct ast_config *cfg; 02813 const char *sfn = astman_get_header(m, "SrcFilename"); 02814 const char *dfn = astman_get_header(m, "DstFilename"); 02815 int res; 02816 const char *rld = astman_get_header(m, "Reload"); 02817 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02818 enum error_type result; 02819 02820 if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) { 02821 astman_send_error(s, m, "Filename not specified"); 02822 return 0; 02823 } 02824 if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) { 02825 astman_send_error(s, m, "Config file not found"); 02826 return 0; 02827 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02828 astman_send_error(s, m, "Config file has invalid format"); 02829 return 0; 02830 } 02831 result = handle_updates(s, m, cfg, dfn); 02832 if (!result) { 02833 ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */ 02834 res = ast_config_text_file_save(dfn, cfg, "Manager"); 02835 ast_config_destroy(cfg); 02836 if (res) { 02837 astman_send_error(s, m, "Save of config failed"); 02838 return 0; 02839 } 02840 astman_send_ack(s, m, NULL); 02841 if (!ast_strlen_zero(rld)) { 02842 if (ast_true(rld)) { 02843 rld = NULL; 02844 } 02845 ast_module_reload(rld); 02846 } 02847 } else { 02848 ast_config_destroy(cfg); 02849 switch(result) { 02850 case UNKNOWN_ACTION: 02851 astman_send_error(s, m, "Unknown action command"); 02852 break; 02853 case UNKNOWN_CATEGORY: 02854 astman_send_error(s, m, "Given category does not exist"); 02855 break; 02856 case UNSPECIFIED_CATEGORY: 02857 astman_send_error(s, m, "Category not specified"); 02858 break; 02859 case UNSPECIFIED_ARGUMENT: 02860 astman_send_error(s, m, "Problem with category, value, or line (if required)"); 02861 break; 02862 case FAILURE_ALLOCATION: 02863 astman_send_error(s, m, "Memory allocation failure, this should not happen"); 02864 break; 02865 case FAILURE_NEWCAT: 02866 astman_send_error(s, m, "Create category did not complete successfully"); 02867 break; 02868 case FAILURE_DELCAT: 02869 astman_send_error(s, m, "Delete category did not complete successfully"); 02870 break; 02871 case FAILURE_EMPTYCAT: 02872 astman_send_error(s, m, "Empty category did not complete successfully"); 02873 break; 02874 case FAILURE_UPDATE: 02875 astman_send_error(s, m, "Update did not complete successfully"); 02876 break; 02877 case FAILURE_DELETE: 02878 astman_send_error(s, m, "Delete did not complete successfully"); 02879 break; 02880 case FAILURE_APPEND: 02881 astman_send_error(s, m, "Append did not complete successfully"); 02882 break; 02883 } 02884 } 02885 return 0; 02886 }
| static int action_userevent | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4434 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().
04435 { 04436 const char *event = astman_get_header(m, "UserEvent"); 04437 struct ast_str *body = ast_str_thread_get(&userevent_buf, 16); 04438 int x; 04439 04440 ast_str_reset(body); 04441 04442 for (x = 0; x < m->hdrcount; x++) { 04443 if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) { 04444 ast_str_append(&body, 0, "%s\r\n", m->headers[x]); 04445 } 04446 } 04447 04448 astman_send_ack(s, m, "Event Sent"); 04449 manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, ast_str_buffer(body)); 04450 return 0; 04451 }
| static int action_waitevent | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2906 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().
02907 { 02908 const char *timeouts = astman_get_header(m, "Timeout"); 02909 int timeout = -1; 02910 int x; 02911 int needexit = 0; 02912 const char *id = astman_get_header(m, "ActionID"); 02913 char idText[256]; 02914 02915 if (!ast_strlen_zero(id)) { 02916 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 02917 } else { 02918 idText[0] = '\0'; 02919 } 02920 02921 if (!ast_strlen_zero(timeouts)) { 02922 sscanf(timeouts, "%30i", &timeout); 02923 if (timeout < -1) { 02924 timeout = -1; 02925 } 02926 /* XXX maybe put an upper bound, or prevent the use of 0 ? */ 02927 } 02928 02929 ao2_lock(s->session); 02930 if (s->session->waiting_thread != AST_PTHREADT_NULL) { 02931 pthread_kill(s->session->waiting_thread, SIGURG); 02932 } 02933 02934 if (s->session->managerid) { /* AMI-over-HTTP session */ 02935 /* 02936 * Make sure the timeout is within the expire time of the session, 02937 * as the client will likely abort the request if it does not see 02938 * data coming after some amount of time. 02939 */ 02940 time_t now = time(NULL); 02941 int max = s->session->sessiontimeout - now - 10; 02942 02943 if (max < 0) { /* We are already late. Strange but possible. */ 02944 max = 0; 02945 } 02946 if (timeout < 0 || timeout > max) { 02947 timeout = max; 02948 } 02949 if (!s->session->send_events) { /* make sure we record events */ 02950 s->session->send_events = -1; 02951 } 02952 } 02953 ao2_unlock(s->session); 02954 02955 /* XXX should this go inside the lock ? */ 02956 s->session->waiting_thread = pthread_self(); /* let new events wake up this thread */ 02957 ast_debug(1, "Starting waiting for an event!\n"); 02958 02959 for (x = 0; x < timeout || timeout < 0; x++) { 02960 ao2_lock(s->session); 02961 if (AST_RWLIST_NEXT(s->session->last_ev, eq_next)) { 02962 needexit = 1; 02963 } 02964 /* We can have multiple HTTP session point to the same mansession entry. 02965 * The way we deal with it is not very nice: newcomers kick out the previous 02966 * HTTP session. XXX this needs to be improved. 02967 */ 02968 if (s->session->waiting_thread != pthread_self()) { 02969 needexit = 1; 02970 } 02971 if (s->session->needdestroy) { 02972 needexit = 1; 02973 } 02974 ao2_unlock(s->session); 02975 if (needexit) { 02976 break; 02977 } 02978 if (s->session->managerid == 0) { /* AMI session */ 02979 if (ast_wait_for_input(s->session->fd, 1000)) { 02980 break; 02981 } 02982 } else { /* HTTP session */ 02983 sleep(1); 02984 } 02985 } 02986 ast_debug(1, "Finished waiting for an event!\n"); 02987 02988 ao2_lock(s->session); 02989 if (s->session->waiting_thread == pthread_self()) { 02990 struct eventqent *eqe = s->session->last_ev; 02991 astman_send_response(s, m, "Success", "Waiting for Event completed."); 02992 while ((eqe = advance_event(eqe))) { 02993 if (((s->session->readperm & eqe->category) == eqe->category) && 02994 ((s->session->send_events & eqe->category) == eqe->category)) { 02995 astman_append(s, "%s", eqe->eventdata); 02996 } 02997 s->session->last_ev = eqe; 02998 } 02999 astman_append(s, 03000 "Event: WaitEventComplete\r\n" 03001 "%s" 03002 "\r\n", idText); 03003 s->session->waiting_thread = AST_PTHREADT_NULL; 03004 } else { 03005 ast_debug(1, "Abandoning event request!\n"); 03006 } 03007 ao2_unlock(s->session); 03008 03009 return 0; 03010 }
Definition at line 1778 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().
01779 { 01780 struct eventqent *next; 01781 01782 AST_RWLIST_RDLOCK(&all_events); 01783 if ((next = AST_RWLIST_NEXT(e, eq_next))) { 01784 ast_atomic_fetchadd_int(&next->usecount, 1); 01785 ast_atomic_fetchadd_int(&e->usecount, -1); 01786 } 01787 AST_RWLIST_UNLOCK(&all_events); 01788 return next; 01789 }
| static int aocmessage_get_unit_entry | ( | const struct message * | m, | |
| struct ast_aoc_unit_entry * | entry, | |||
| unsigned int | entry_num | |||
| ) | [static] |
Definition at line 3775 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().
03776 { 03777 const char *unitamount; 03778 const char *unittype; 03779 struct ast_str *str = ast_str_alloca(32); 03780 03781 memset(entry, 0, sizeof(*entry)); 03782 03783 ast_str_set(&str, 0, "UnitAmount(%u)", entry_num); 03784 unitamount = astman_get_header(m, ast_str_buffer(str)); 03785 03786 ast_str_set(&str, 0, "UnitType(%u)", entry_num); 03787 unittype = astman_get_header(m, ast_str_buffer(str)); 03788 03789 if (!ast_strlen_zero(unitamount) && (sscanf(unitamount, "%30u", &entry->amount) == 1)) { 03790 entry->valid_amount = 1; 03791 } 03792 03793 if (!ast_strlen_zero(unittype) && sscanf(unittype, "%30u", &entry->type) == 1) { 03794 entry->valid_type = 1; 03795 } 03796 03797 return 0; 03798 }
| static void append_channel_vars | ( | struct ast_str ** | pbuf, | |
| struct ast_channel * | chan | |||
| ) | [static] |
Definition at line 5171 of file manager.c.
References ast_channel_name(), 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().
05172 { 05173 struct manager_channel_variable *var; 05174 05175 AST_RWLIST_RDLOCK(&channelvars); 05176 AST_LIST_TRAVERSE(&channelvars, var, entry) { 05177 const char *val; 05178 struct ast_str *res; 05179 05180 if (var->isfunc) { 05181 res = ast_str_thread_get(&manager_event_funcbuf, 16); 05182 if (res && ast_func_read2(chan, var->name, &res, 0) == 0) { 05183 val = ast_str_buffer(res); 05184 } else { 05185 val = NULL; 05186 } 05187 } else { 05188 val = pbx_builtin_getvar_helper(chan, var->name); 05189 } 05190 ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", ast_channel_name(chan), var->name, val ? val : ""); 05191 } 05192 AST_RWLIST_UNLOCK(&channelvars); 05193 }
| static int append_event | ( | const char * | str, | |
| int | category | |||
| ) | [static] |
events are appended to a queue from where they can be dispatched to clients.
Definition at line 5145 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().
05146 { 05147 struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str)); 05148 static int seq; /* sequence number */ 05149 05150 if (!tmp) { 05151 return -1; 05152 } 05153 05154 /* need to init all fields, because ast_malloc() does not */ 05155 tmp->usecount = 0; 05156 tmp->category = category; 05157 tmp->seq = ast_atomic_fetchadd_int(&seq, 1); 05158 tmp->tv = ast_tvnow(); 05159 AST_RWLIST_NEXT(tmp, eq_next) = NULL; 05160 strcpy(tmp->eventdata, str); 05161 05162 AST_RWLIST_WRLOCK(&all_events); 05163 AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next); 05164 AST_RWLIST_UNLOCK(&all_events); 05165 05166 return 0; 05167 }
| int ast_hook_send_action | ( | struct manager_custom_hook * | hook, | |
| const char * | msg | |||
| ) |
access for hooks to send action messages to ami
Registered hooks can call this function to invoke actions and they will receive responses through registered callback.
Definition at line 1920 of file manager.c.
References action_find(), 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.
01921 { 01922 const char *action; 01923 int ret = 0; 01924 struct manager_action *act_found; 01925 struct mansession s = {.session = NULL, }; 01926 struct message m = { 0 }; 01927 char *dup_str; 01928 char *src; 01929 int x = 0; 01930 int curlen; 01931 01932 if (hook == NULL) { 01933 return -1; 01934 } 01935 01936 /* Create our own copy of the AMI action msg string. */ 01937 src = dup_str = ast_strdup(msg); 01938 if (!dup_str) { 01939 return -1; 01940 } 01941 01942 /* convert msg string to message struct */ 01943 curlen = strlen(src); 01944 for (x = 0; x < curlen; x++) { 01945 int cr; /* set if we have \r */ 01946 if (src[x] == '\r' && x+1 < curlen && src[x+1] == '\n') 01947 cr = 2; /* Found. Update length to include \r\n */ 01948 else if (src[x] == '\n') 01949 cr = 1; /* also accept \n only */ 01950 else 01951 continue; 01952 /* don't keep empty lines */ 01953 if (x && m.hdrcount < ARRAY_LEN(m.headers)) { 01954 /* ... but trim \r\n and terminate the header string */ 01955 src[x] = '\0'; 01956 m.headers[m.hdrcount++] = src; 01957 } 01958 x += cr; 01959 curlen -= x; /* remaining size */ 01960 src += x; /* update pointer */ 01961 x = -1; /* reset loop */ 01962 } 01963 01964 action = astman_get_header(&m, "Action"); 01965 if (strcasecmp(action, "login")) { 01966 act_found = action_find(action); 01967 if (act_found) { 01968 /* 01969 * we have to simulate a session for this action request 01970 * to be able to pass it down for processing 01971 * This is necessary to meet the previous design of manager.c 01972 */ 01973 s.hook = hook; 01974 s.f = (void*)1; /* set this to something so our request will make it through all functions that test it*/ 01975 01976 ao2_lock(act_found); 01977 if (act_found->registered && act_found->func) { 01978 ret = act_found->func(&s, &m); 01979 } else { 01980 ret = -1; 01981 } 01982 ao2_unlock(act_found); 01983 ao2_t_ref(act_found, -1, "done with found action object"); 01984 } 01985 } 01986 ast_free(dup_str); 01987 return ret; 01988 }
| 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 1248 of file manager.c.
References eventqent::next.
Referenced by get_perm().
01249 { 01250 const char *val = bigstr, *next; 01251 01252 do { 01253 if ((next = strchr(val, delim))) { 01254 if (!strncmp(val, smallstr, (next - val))) { 01255 return 1; 01256 } else { 01257 continue; 01258 } 01259 } else { 01260 return !strcmp(smallstr, val); 01261 } 01262 } while (*(val = (next + 1))); 01263 01264 return 0; 01265 }
| 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 5381 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, manager_action::authority, manager_action::docsrc, and manager_action::func.
Referenced by load_module().
05382 { 05383 struct manager_action *cur; 05384 05385 cur = ao2_alloc(sizeof(*cur), action_destroy); 05386 if (!cur) { 05387 return -1; 05388 } 05389 if (ast_string_field_init(cur, 128)) { 05390 ao2_t_ref(cur, -1, "action object creation failed"); 05391 return -1; 05392 } 05393 05394 cur->action = action; 05395 cur->authority = auth; 05396 cur->func = func; 05397 #ifdef AST_XML_DOCS 05398 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 05399 char *tmpxml; 05400 05401 tmpxml = ast_xmldoc_build_synopsis("manager", action, NULL); 05402 ast_string_field_set(cur, synopsis, tmpxml); 05403 ast_free(tmpxml); 05404 05405 tmpxml = ast_xmldoc_build_syntax("manager", action, NULL); 05406 ast_string_field_set(cur, syntax, tmpxml); 05407 ast_free(tmpxml); 05408 05409 tmpxml = ast_xmldoc_build_description("manager", action, NULL); 05410 ast_string_field_set(cur, description, tmpxml); 05411 ast_free(tmpxml); 05412 05413 tmpxml = ast_xmldoc_build_seealso("manager", action, NULL); 05414 ast_string_field_set(cur, seealso, tmpxml); 05415 ast_free(tmpxml); 05416 05417 tmpxml = ast_xmldoc_build_arguments("manager", action, NULL); 05418 ast_string_field_set(cur, arguments, tmpxml); 05419 ast_free(tmpxml); 05420 05421 cur->docsrc = AST_XML_DOC; 05422 } else 05423 #endif 05424 { 05425 ast_string_field_set(cur, synopsis, synopsis); 05426 ast_string_field_set(cur, description, description); 05427 #ifdef AST_XML_DOCS 05428 cur->docsrc = AST_STATIC_DOC; 05429 #endif 05430 } 05431 if (ast_manager_register_struct(cur)) { 05432 ao2_t_ref(cur, -1, "action object registration failed"); 05433 return -1; 05434 } 05435 05436 ao2_t_ref(cur, -1, "action object registration successful"); 05437 return 0; 05438 }
| 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 1117 of file manager.c.
References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and manager_action::list.
01118 { 01119 AST_RWLIST_WRLOCK(&manager_hooks); 01120 AST_RWLIST_INSERT_TAIL(&manager_hooks, hook, list); 01121 AST_RWLIST_UNLOCK(&manager_hooks); 01122 }
| static int ast_manager_register_struct | ( | struct manager_action * | act | ) | [static] |
Definition at line 5326 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().
05327 { 05328 struct manager_action *cur, *prev = NULL; 05329 05330 AST_RWLIST_WRLOCK(&actions); 05331 AST_RWLIST_TRAVERSE(&actions, cur, list) { 05332 int ret; 05333 05334 ret = strcasecmp(cur->action, act->action); 05335 if (ret == 0) { 05336 ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action); 05337 AST_RWLIST_UNLOCK(&actions); 05338 return -1; 05339 } 05340 if (ret > 0) { /* Insert these alphabetically */ 05341 prev = cur; 05342 break; 05343 } 05344 } 05345 05346 ao2_t_ref(act, +1, "action object added to list"); 05347 act->registered = 1; 05348 if (prev) { 05349 AST_RWLIST_INSERT_AFTER(&actions, prev, act, list); 05350 } else { 05351 AST_RWLIST_INSERT_HEAD(&actions, act, list); 05352 } 05353 05354 ast_verb(2, "Manager registered action %s\n", act->action); 05355 05356 AST_RWLIST_UNLOCK(&actions); 05357 05358 return 0; 05359 }
| int ast_manager_unregister | ( | char * | action | ) |
support functions to register/unregister AMI action handlers,
Unregister a registered manager command.
Definition at line 5286 of file manager.c.
References manager_action::action, ao2_lock, ao2_t_ref, ao2_unlock, 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(), and unload_module().
05287 { 05288 struct manager_action *cur; 05289 05290 AST_RWLIST_WRLOCK(&actions); 05291 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) { 05292 if (!strcasecmp(action, cur->action)) { 05293 AST_RWLIST_REMOVE_CURRENT(list); 05294 break; 05295 } 05296 } 05297 AST_RWLIST_TRAVERSE_SAFE_END; 05298 AST_RWLIST_UNLOCK(&actions); 05299 05300 if (cur) { 05301 /* 05302 * We have removed the action object from the container so we 05303 * are no longer in a hurry. 05304 */ 05305 ao2_lock(cur); 05306 cur->registered = 0; 05307 ao2_unlock(cur); 05308 05309 ao2_t_ref(cur, -1, "action object removed from list"); 05310 ast_verb(2, "Manager unregistered action %s\n", action); 05311 } 05312 05313 return 0; 05314 }
| 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 1125 of file manager.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and manager_action::list.
01126 { 01127 AST_RWLIST_WRLOCK(&manager_hooks); 01128 AST_RWLIST_REMOVE(&manager_hooks, hook, list); 01129 AST_RWLIST_UNLOCK(&manager_hooks); 01130 }
| void astman_append | ( | struct mansession * | s, | |
| const char * | fmt, | |||
| ... | ||||
| ) |
utility functions for creating AMI replies
Definition at line 2035 of file manager.c.
References ast_str_buffer(), ast_str_set_va(), ast_str_thread_get(), ast_verbose, astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE, mansession_session::f, mansession::f, send_string(), and mansession::session.
Referenced by __iax2_show_peers(), _sip_show_peer(), _sip_show_peers(), _skinny_show_device(), _skinny_show_devices(), _skinny_show_line(), _skinny_show_lines(), action_agents(), action_challenge(), action_command(), action_confbridgelist(), action_confbridgelistrooms(), 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_meetmelistrooms(), 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_mixmonitor(), manager_modulecheck(), manager_mute_mixmonitor(), manager_mutestream(), manager_parking_status(), manager_queue_rule_show(), manager_queues_show(), manager_queues_status(), manager_queues_summary(), manager_rpt_local_nodes(), manager_rpt_status(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_show_registry(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), manager_stop_mixmonitor(), rpt_manager_do_stats(), rpt_manager_success(), and session_do().
02036 { 02037 va_list ap; 02038 struct ast_str *buf; 02039 02040 if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) { 02041 return; 02042 } 02043 02044 va_start(ap, fmt); 02045 ast_str_set_va(&buf, 0, fmt, ap); 02046 va_end(ap); 02047 02048 if (s->f != NULL || s->session->f != NULL) { 02049 send_string(s, ast_str_buffer(buf)); 02050 } else { 02051 ast_verbose("fd == -1 in astman_append, should not happen\n"); 02052 } 02053 }
| static void astman_append_json | ( | struct mansession * | s, | |
| const char * | str | |||
| ) | [static] |
Definition at line 2607 of file manager.c.
References astman_append(), and json_escape().
Referenced by action_getconfigjson().
02608 { 02609 char *buf; 02610 02611 buf = alloca(2 * strlen(str) + 1); 02612 json_escape(buf, str); 02613 astman_append(s, "%s", buf); 02614 }
| const char* astman_get_header | ( | const struct message * | m, | |
| char * | var | |||
| ) |
Return the first matching variable from an array.
Get header from mananger transaction.
Never returns NULL.
Definition at line 1841 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_confbridgekick(), action_confbridgelist(), action_confbridgelistrooms(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdishowchannels(), action_events(), action_extensionstate(), action_filter(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_lock_unlock_helper(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_meetmelistrooms(), action_mute_unmute_helper(), 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_mixmonitor(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_optimize_away(), manager_park(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_queue_rule_show(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), manager_rpt_status(), manager_show_dialplan(), manager_show_registry(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), manager_stop_mixmonitor(), meetmemute(), process_message(), rpt_manager_do_stats(), rpt_manager_success(), start_monitor_action(), and stop_monitor_action().
01842 { 01843 return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH); 01844 }
| struct ast_variable* astman_get_variables | ( | const struct message * | m | ) | [read] |
Get a linked list of the Variable: headers.
Definition at line 1899 of file manager.c.
References message::hdrcount, message::headers, and man_do_variable_value().
Referenced by action_originate(), and manager_sipnotify().
01900 { 01901 int varlen; 01902 int x; 01903 struct ast_variable *head = NULL; 01904 01905 static const char var_hdr[] = "Variable:"; 01906 01907 /* Process all "Variable:" headers. */ 01908 varlen = strlen(var_hdr); 01909 for (x = 0; x < m->hdrcount; x++) { 01910 if (strncasecmp(var_hdr, m->headers[x], varlen)) { 01911 continue; 01912 } 01913 head = man_do_variable_value(head, m->headers[x] + varlen); 01914 } 01915 01916 return head; 01917 }
| void astman_send_ack | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| char * | msg | |||
| ) |
Send ack in manager transaction.
Definition at line 2104 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_confbridgekick(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_dahdishowchannels(), action_filter(), action_hangup(), action_lock_unlock_helper(), action_login(), action_mute_unmute_helper(), 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().
02105 { 02106 astman_send_response_full(s, m, "Success", msg, NULL); 02107 }
| void astman_send_error | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| char * | error | |||
| ) |
Send error in manager transaction.
Definition at line 2099 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_confbridgekick(), action_confbridgelist(), action_confbridgelistrooms(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_coreshowchannels(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_events(), action_extensionstate(), action_filter(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_lock_unlock_helper(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_meetmelistrooms(), action_mute_unmute_helper(), 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(), manager_add_queue_member(), manager_data_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_jabber_send(), manager_mixmonitor(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_optimize_away(), manager_park(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_remove_queue_member(), manager_rpt_status(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_line(), manager_stop_mixmonitor(), meetmemute(), process_message(), rpt_manager_do_stats(), start_monitor_action(), and stop_monitor_action().
02100 { 02101 astman_send_response_full(s, m, "Error", error, NULL); 02102 }
| void astman_send_listack | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| char * | msg, | |||
| char * | listflag | |||
| ) |
Send ack in manager list transaction.
Definition at line 2114 of file manager.c.
References astman_send_response_full().
Referenced by action_confbridgelist(), action_confbridgelistrooms(), action_coreshowchannels(), action_meetmelist(), action_meetmelistrooms(), 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().
02115 { 02116 astman_send_response_full(s, m, "Success", msg, listflag); 02117 }
| void astman_send_response | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| char * | resp, | |||
| char * | msg | |||
| ) |
Send response in manager transaction.
Definition at line 2094 of file manager.c.
References astman_send_response_full().
Referenced by action_logoff(), and action_waitevent().
02095 { 02096 astman_send_response_full(s, m, resp, msg, NULL); 02097 }
| static void astman_send_response_full | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| char * | resp, | |||
| char * | msg, | |||
| char * | listflag | |||
| ) | [static] |
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 2074 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().
02075 { 02076 const char *id = astman_get_header(m, "ActionID"); 02077 02078 astman_append(s, "Response: %s\r\n", resp); 02079 if (!ast_strlen_zero(id)) { 02080 astman_append(s, "ActionID: %s\r\n", id); 02081 } 02082 if (listflag) { 02083 astman_append(s, "EventList: %s\r\n", listflag); /* Start, complete, cancelled */ 02084 } 02085 if (msg == MSG_MOREDATA) { 02086 return; 02087 } else if (msg) { 02088 astman_append(s, "Message: %s\r\n\r\n", msg); 02089 } else { 02090 astman_append(s, "\r\n"); 02091 } 02092 }
| static void astman_start_ack | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2109 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().
02110 { 02111 astman_send_response_full(s, m, "Success", MSG_MOREDATA, NULL); 02112 }
| static int authenticate | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2391 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.
02392 { 02393 const char *username = astman_get_header(m, "Username"); 02394 const char *password = astman_get_header(m, "Secret"); 02395 int error = -1; 02396 struct ast_manager_user *user = NULL; 02397 regex_t *regex_filter; 02398 struct ao2_iterator filter_iter; 02399 struct ast_sockaddr addr; 02400 02401 if (ast_strlen_zero(username)) { /* missing username */ 02402 return -1; 02403 } 02404 02405 /* locate user in locked state */ 02406 AST_RWLIST_WRLOCK(&users); 02407 02408 ast_sockaddr_from_sin(&addr, &s->session->sin); 02409 02410 if (!(user = get_manager_by_name_locked(username))) { 02411 report_invalid_user(s, username); 02412 ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02413 } else if (user->ha && !ast_apply_ha(user->ha, &addr)) { 02414 report_failed_acl(s, username); 02415 ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02416 } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) { 02417 const char *key = astman_get_header(m, "Key"); 02418 if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) { 02419 int x; 02420 int len = 0; 02421 char md5key[256] = ""; 02422 struct MD5Context md5; 02423 unsigned char digest[16]; 02424 02425 MD5Init(&md5); 02426 MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge)); 02427 MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret)); 02428 MD5Final(digest, &md5); 02429 for (x = 0; x < 16; x++) 02430 len += sprintf(md5key + len, "%2.2x", digest[x]); 02431 if (!strcmp(md5key, key)) { 02432 error = 0; 02433 } else { 02434 report_failed_challenge_response(s, key, md5key); 02435 } 02436 } else { 02437 ast_debug(1, "MD5 authentication is not possible. challenge: '%s'\n", 02438 S_OR(s->session->challenge, "")); 02439 } 02440 } else if (user->secret) { 02441 if (!strcmp(password, user->secret)) { 02442 error = 0; 02443 } else { 02444 report_inval_password(s, username); 02445 } 02446 } 02447 02448 if (error) { 02449 ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02450 AST_RWLIST_UNLOCK(&users); 02451 return -1; 02452 } 02453 02454 /* auth complete */ 02455 02456 /* All of the user parameters are copied to the session so that in the event 02457 * of a reload and a configuration change, the session parameters are not 02458 * changed. */ 02459 ast_copy_string(s->session->username, username, sizeof(s->session->username)); 02460 s->session->readperm = user->readperm; 02461 s->session->writeperm = user->writeperm; 02462 s->session->writetimeout = user->writetimeout; 02463 02464 filter_iter = ao2_iterator_init(user->whitefilters, 0); 02465 while ((regex_filter = ao2_iterator_next(&filter_iter))) { 02466 ao2_t_link(s->session->whitefilters, regex_filter, "add white user filter to session"); 02467 ao2_t_ref(regex_filter, -1, "remove iterator ref"); 02468 } 02469 ao2_iterator_destroy(&filter_iter); 02470 02471 filter_iter = ao2_iterator_init(user->blackfilters, 0); 02472 while ((regex_filter = ao2_iterator_next(&filter_iter))) { 02473 ao2_t_link(s->session->blackfilters, regex_filter, "add black user filter to session"); 02474 ao2_t_ref(regex_filter, -1, "remove iterator ref"); 02475 } 02476 ao2_iterator_destroy(&filter_iter); 02477 02478 s->session->sessionstart = time(NULL); 02479 s->session->sessionstart_tv = ast_tvnow(); 02480 set_eventmask(s, astman_get_header(m, "Events")); 02481 02482 report_auth_success(s); 02483 02484 AST_RWLIST_UNLOCK(&users); 02485 return 0; 02486 }
| static const char* authority_to_str | ( | int | authority, | |
| struct ast_str ** | res | |||
| ) | [static] |
Convert authority code to a list of options.
Definition at line 1224 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_showmanager(), handle_showmancmd(), and handle_showmancmds().
01225 { 01226 int i; 01227 char *sep = ""; 01228 01229 ast_str_reset(*res); 01230 for (i = 0; i < ARRAY_LEN(perms) - 1; i++) { 01231 if (authority & perms[i].num) { 01232 ast_str_append(res, 0, "%s%s", sep, perms[i].label); 01233 sep = ","; 01234 } 01235 } 01236 01237 if (ast_str_strlen(*res) == 0) /* replace empty string with something sensible */ 01238 ast_str_append(res, 0, "<none>"); 01239 01240 return ast_str_buffer(*res); 01241 }
| static int blackfilter_cmp_fn | ( | void * | obj, | |
| void * | arg, | |||
| void * | data, | |||
| int | flags | |||
| ) | [static] |
Definition at line 4283 of file manager.c.
References CMP_MATCH, and CMP_STOP.
Referenced by match_filter().
04284 { 04285 regex_t *regex_filter = obj; 04286 const char *eventdata = arg; 04287 int *result = data; 04288 04289 if (!regexec(regex_filter, eventdata, 0, NULL, 0)) { 04290 *result = 0; 04291 return (CMP_MATCH | CMP_STOP); 04292 } 04293 04294 *result = 1; 04295 return 0; 04296 }
| 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 1365 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(), 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().
01366 { 01367 struct mansession_session *newsession; 01368 01369 if (!(newsession = ao2_alloc(sizeof(*newsession), session_destructor))) { 01370 return NULL; 01371 } 01372 01373 if (!(newsession->whitefilters = ao2_container_alloc(1, NULL, NULL))) { 01374 ao2_ref(newsession, -1); 01375 return NULL; 01376 } 01377 01378 if (!(newsession->blackfilters = ao2_container_alloc(1, NULL, NULL))) { 01379 ao2_ref(newsession, -1); /* session_destructor will cleanup the other filter */ 01380 return NULL; 01381 } 01382 01383 newsession->fd = -1; 01384 newsession->waiting_thread = AST_PTHREADT_NULL; 01385 newsession->writetimeout = 100; 01386 newsession->send_events = -1; 01387 newsession->sin = sin; 01388 01389 ao2_link(sessions, newsession); 01390 01391 return newsession; 01392 }
| static int check_blacklist | ( | const char * | cmd | ) | [static] |
Definition at line 3595 of file manager.c.
References ARRAY_LEN, ast_strdupa, ast_strip(), ast_strlen_zero(), command_blacklist, match(), MAX_BLACKLIST_CMD_LEN, strsep(), and words.
Referenced by action_command().
03596 { 03597 char *cmd_copy, *cur_cmd; 03598 char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, }; 03599 int i; 03600 03601 cmd_copy = ast_strdupa(cmd); 03602 for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) { 03603 cur_cmd = ast_strip(cur_cmd); 03604 if (ast_strlen_zero(cur_cmd)) { 03605 i--; 03606 continue; 03607 } 03608 03609 cmd_words[i] = cur_cmd; 03610 } 03611 03612 for (i = 0; i < ARRAY_LEN(command_blacklist); i++) { 03613 int j, match = 1; 03614 03615 for (j = 0; command_blacklist[i].words[j]; j++) { 03616 if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) { 03617 match = 0; 03618 break; 03619 } 03620 } 03621 03622 if (match) { 03623 return 1; 03624 } 03625 } 03626 03627 return 0; 03628 }
| int check_manager_enabled | ( | void | ) |
Check if AMI is enabled.
Definition at line 1132 of file manager.c.
Referenced by handle_show_settings().
01133 { 01134 return manager_enabled; 01135 }
| static int check_manager_session_inuse | ( | const char * | name | ) | [static] |
Definition at line 1408 of file manager.c.
References ao2_find, mansession_session::inuse, and unref_mansession().
Referenced by process_message().
01409 { 01410 struct mansession_session *session = ao2_find(sessions, (char *) name, 0); 01411 int inuse = 0; 01412 01413 if (session) { 01414 inuse = 1; 01415 unref_mansession(session); 01416 } 01417 return inuse; 01418 }
| int check_webmanager_enabled | ( | void | ) |
Check if AMI/HTTP is enabled.
Definition at line 1137 of file manager.c.
Referenced by action_coresettings(), and handle_show_settings().
01138 { 01139 return (webmanager_enabled && manager_enabled); 01140 }
| static void destroy_fast_originate_helper | ( | struct fast_originate_helper * | doomed | ) | [static] |
Definition at line 3713 of file manager.c.
References ast_format_cap_destroy(), ast_free, ast_string_field_free_memory, ast_variables_destroy(), fast_originate_helper::cap, and fast_originate_helper::vars.
Referenced by action_originate(), and fast_originate().
03714 { 03715 ast_format_cap_destroy(doomed->cap); 03716 ast_variables_destroy(doomed->vars); 03717 ast_string_field_free_memory(doomed); 03718 ast_free(doomed); 03719 }
| static int do_message | ( | struct mansession * | s | ) | [static] |
Definition at line 4937 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(), message::hdrcount, message::headers, mansession_session::inbuf, LOG_ERROR, mansession_lock(), mansession_unlock(), process_events(), process_message(), mansession::session, and mansession_session::sin.
Referenced by session_do().
04938 { 04939 struct message m = { 0 }; 04940 char header_buf[sizeof(s->session->inbuf)] = { '\0' }; 04941 int res; 04942 int idx; 04943 int hdr_loss; 04944 time_t now; 04945 04946 hdr_loss = 0; 04947 for (;;) { 04948 /* Check if any events are pending and do them if needed */ 04949 if (process_events(s)) { 04950 res = -1; 04951 break; 04952 } 04953 res = get_input(s, header_buf); 04954 if (res == 0) { 04955 /* No input line received. */ 04956 if (!s->session->authenticated) { 04957 if (time(&now) == -1) { 04958 ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); 04959 res = -1; 04960 break; 04961 } 04962 04963 if (now - s->session->authstart > authtimeout) { 04964 if (displayconnects) { 04965 ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout); 04966 } 04967 res = -1; 04968 break; 04969 } 04970 } 04971 continue; 04972 } else if (res > 0) { 04973 /* Input line received. */ 04974 if (ast_strlen_zero(header_buf)) { 04975 if (hdr_loss) { 04976 mansession_lock(s); 04977 astman_send_error(s, &m, "Too many lines in message or allocation failure"); 04978 mansession_unlock(s); 04979 res = 0; 04980 } else { 04981 res = process_message(s, &m) ? -1 : 0; 04982 } 04983 break; 04984 } else if (m.hdrcount < ARRAY_LEN(m.headers)) { 04985 m.headers[m.hdrcount] = ast_strdup(header_buf); 04986 if (!m.headers[m.hdrcount]) { 04987 /* Allocation failure. */ 04988 hdr_loss = 1; 04989 } else { 04990 ++m.hdrcount; 04991 } 04992 } else { 04993 /* Too many lines in message. */ 04994 hdr_loss = 1; 04995 } 04996 } else { 04997 /* Input error. */ 04998 break; 04999 } 05000 } 05001 05002 /* Free AMI request headers. */ 05003 for (idx = 0; idx < m.hdrcount; ++idx) { 05004 ast_free((void *) m.headers[idx]); 05005 } 05006 return res; 05007 }
| static void event_filter_destructor | ( | void * | obj | ) | [static] |
| static void* fast_originate | ( | void * | data | ) | [static] |
Definition at line 3721 of file manager.c.
References fast_originate_helper::account, fast_originate_helper::app, fast_originate_helper::appdata, ast_channel_name(), AST_CHANNEL_NAME, ast_channel_uniqueid(), ast_channel_unlock, ast_manager_event_multichan, ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_strlen_zero(), fast_originate_helper::cap, 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::idtext, fast_originate_helper::priority, S_OR, fast_originate_helper::tech, fast_originate_helper::timeout, and fast_originate_helper::vars.
Referenced by action_originate().
03722 { 03723 struct fast_originate_helper *in = data; 03724 int res; 03725 int reason = 0; 03726 struct ast_channel *chan = NULL, *chans[1]; 03727 char requested_channel[AST_CHANNEL_NAME]; 03728 03729 if (!ast_strlen_zero(in->app)) { 03730 res = ast_pbx_outgoing_app(in->tech, in->cap, in->data, 03731 in->timeout, in->app, in->appdata, &reason, 1, 03732 S_OR(in->cid_num, NULL), 03733 S_OR(in->cid_name, NULL), 03734 in->vars, in->account, &chan); 03735 } else { 03736 res = ast_pbx_outgoing_exten(in->tech, in->cap, in->data, 03737 in->timeout, in->context, in->exten, in->priority, &reason, 1, 03738 S_OR(in->cid_num, NULL), 03739 S_OR(in->cid_name, NULL), 03740 in->vars, in->account, &chan); 03741 } 03742 /* Any vars memory was passed to the ast_pbx_outgoing_xxx() calls. */ 03743 in->vars = NULL; 03744 03745 if (!chan) { 03746 snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data); 03747 } 03748 /* Tell the manager what happened with the channel */ 03749 chans[0] = chan; 03750 ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans, 03751 "%s" 03752 "Response: %s\r\n" 03753 "Channel: %s\r\n" 03754 "Context: %s\r\n" 03755 "Exten: %s\r\n" 03756 "Reason: %d\r\n" 03757 "Uniqueid: %s\r\n" 03758 "CallerIDNum: %s\r\n" 03759 "CallerIDName: %s\r\n", 03760 in->idtext, res ? "Failure" : "Success", 03761 chan ? ast_channel_name(chan) : requested_channel, in->context, in->exten, reason, 03762 chan ? ast_channel_uniqueid(chan) : "<null>", 03763 S_OR(in->cid_num, "<unknown>"), 03764 S_OR(in->cid_name, "<unknown>") 03765 ); 03766 03767 /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */ 03768 if (chan) { 03769 ast_channel_unlock(chan); 03770 } 03771 destroy_fast_originate_helper(in); 03772 return NULL; 03773 }
| static void free_channelvars | ( | void | ) | [static] |
Definition at line 7049 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().
07050 { 07051 struct manager_channel_variable *var; 07052 AST_RWLIST_WRLOCK(&channelvars); 07053 while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) { 07054 ast_free(var); 07055 } 07056 AST_RWLIST_UNLOCK(&channelvars); 07057 }
| 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 4840 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, mansession_session::pending_event, mansession::session, mansession_session::sin, ast_frame::src, and mansession_session::waiting_thread.
04841 { 04842 int res, x; 04843 int maxlen = sizeof(s->session->inbuf) - 1; 04844 char *src = s->session->inbuf; 04845 int timeout = -1; 04846 time_t now; 04847 04848 /* 04849 * Look for \r\n within the buffer. If found, copy to the output 04850 * buffer and return, trimming the \r\n (not used afterwards). 04851 */ 04852 for (x = 0; x < s->session->inlen; x++) { 04853 int cr; /* set if we have \r */ 04854 if (src[x] == '\r' && x+1 < s->session->inlen && src[x + 1] == '\n') { 04855 cr = 2; /* Found. Update length to include \r\n */ 04856 } else if (src[x] == '\n') { 04857 cr = 1; /* also accept \n only */ 04858 } else { 04859 continue; 04860 } 04861 memmove(output, src, x); /*... but trim \r\n */ 04862 output[x] = '\0'; /* terminate the string */ 04863 x += cr; /* number of bytes used */ 04864 s->session->inlen -= x; /* remaining size */ 04865 memmove(src, src + x, s->session->inlen); /* remove used bytes */ 04866 return 1; 04867 } 04868 if (s->session->inlen >= maxlen) { 04869 /* no crlf found, and buffer full - sorry, too long for us */ 04870 ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", ast_inet_ntoa(s->session->sin.sin_addr), src); 04871 s->session->inlen = 0; 04872 } 04873 res = 0; 04874 while (res == 0) { 04875 /* calculate a timeout if we are not authenticated */ 04876 if (!s->session->authenticated) { 04877 if(time(&now) == -1) { 04878 ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); 04879 return -1; 04880 } 04881 04882 timeout = (authtimeout - (now - s->session->authstart)) * 1000; 04883 if (timeout < 0) { 04884 /* we have timed out */ 04885 return 0; 04886 } 04887 } 04888 04889 ao2_lock(s->session); 04890 if (s->session->pending_event) { 04891 s->session->pending_event = 0; 04892 ao2_unlock(s->session); 04893 return 0; 04894 } 04895 s->session->waiting_thread = pthread_self(); 04896 ao2_unlock(s->session); 04897 04898 res = ast_wait_for_input(s->session->fd, timeout); 04899 04900 ao2_lock(s->session); 04901 s->session->waiting_thread = AST_PTHREADT_NULL; 04902 ao2_unlock(s->session); 04903 } 04904 if (res < 0) { 04905 /* If we get a signal from some other thread (typically because 04906 * there are new events queued), return 0 to notify the caller. 04907 */ 04908 if (errno == EINTR || errno == EAGAIN) { 04909 return 0; 04910 } 04911 ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno)); 04912 return -1; 04913 } 04914 04915 ao2_lock(s->session); 04916 res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f); 04917 if (res < 1) { 04918 res = -1; /* error return */ 04919 } else { 04920 s->session->inlen += res; 04921 src[s->session->inlen] = '\0'; 04922 res = 0; 04923 } 04924 ao2_unlock(s->session); 04925 return res; 04926 }
| 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 1425 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().
01426 { 01427 struct ast_manager_user *user = NULL; 01428 01429 AST_RWLIST_TRAVERSE(&users, user, list) { 01430 if (!strcasecmp(user->username, name)) { 01431 break; 01432 } 01433 } 01434 01435 return user; 01436 }
| static int get_perm | ( | const char * | instr | ) | [static] |
Definition at line 1267 of file manager.c.
References ARRAY_LEN, ast_instring(), permalias::num, and perms.
Referenced by __init_manager(), and strings_to_mask().
01268 { 01269 int x = 0, ret = 0; 01270 01271 if (!instr) { 01272 return 0; 01273 } 01274 01275 for (x = 0; x < ARRAY_LEN(perms); x++) { 01276 if (ast_instring(instr, perms[x].label, ',')) { 01277 ret |= perms[x].num; 01278 } 01279 } 01280 01281 return ret; 01282 }
| 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 1146 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().
01147 { 01148 struct eventqent *ret; 01149 01150 AST_RWLIST_WRLOCK(&all_events); 01151 ret = AST_RWLIST_LAST(&all_events); 01152 /* the list is never empty now, but may become so when 01153 * we optimize it in the future, so be prepared. 01154 */ 01155 if (ret) { 01156 ast_atomic_fetchadd_int(&ret->usecount, 1); 01157 } 01158 AST_RWLIST_UNLOCK(&all_events); 01159 return ret; 01160 }
| 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 1759 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.
01760 { 01761 switch (cmd) { 01762 case CLI_INIT: 01763 e->command = "manager reload"; 01764 e->usage = 01765 "Usage: manager reload\n" 01766 " Reloads the manager configuration.\n"; 01767 return NULL; 01768 case CLI_GENERATE: 01769 return NULL; 01770 } 01771 if (a->argc > 2) { 01772 return CLI_SHOWUSAGE; 01773 } 01774 reload_manager(); 01775 return CLI_SUCCESS; 01776 }
| static char* handle_mandebug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1533 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.
01534 { 01535 switch (cmd) { 01536 case CLI_INIT: 01537 e->command = "manager set debug [on|off]"; 01538 e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n"; 01539 return NULL; 01540 case CLI_GENERATE: 01541 return NULL; 01542 } 01543 01544 if (a->argc == 3) { 01545 ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off"); 01546 } else if (a->argc == 4) { 01547 if (!strcasecmp(a->argv[3], "on")) { 01548 manager_debug = 1; 01549 } else if (!strcasecmp(a->argv[3], "off")) { 01550 manager_debug = 0; 01551 } else { 01552 return CLI_SHOWUSAGE; 01553 } 01554 } 01555 return CLI_SUCCESS; 01556 }
| static char* handle_showmanager | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1558 of file manager.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_strdup, authority_to_str(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_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, ast_manager_user::username, ast_cli_args::word, and ast_manager_user::writeperm.
01559 { 01560 struct ast_manager_user *user = NULL; 01561 int l, which; 01562 char *ret = NULL; 01563 struct ast_str *rauthority = ast_str_alloca(128); 01564 struct ast_str *wauthority = ast_str_alloca(128); 01565 01566 switch (cmd) { 01567 case CLI_INIT: 01568 e->command = "manager show user"; 01569 e->usage = 01570 " Usage: manager show user <user>\n" 01571 " Display all information related to the manager user specified.\n"; 01572 return NULL; 01573 case CLI_GENERATE: 01574 l = strlen(a->word); 01575 which = 0; 01576 if (a->pos != 3) { 01577 return NULL; 01578 } 01579 AST_RWLIST_RDLOCK(&users); 01580 AST_RWLIST_TRAVERSE(&users, user, list) { 01581 if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) { 01582 ret = ast_strdup(user->username); 01583 break; 01584 } 01585 } 01586 AST_RWLIST_UNLOCK(&users); 01587 return ret; 01588 } 01589 01590 if (a->argc != 4) { 01591 return CLI_SHOWUSAGE; 01592 } 01593 01594 AST_RWLIST_RDLOCK(&users); 01595 01596 if (!(user = get_manager_by_name_locked(a->argv[3]))) { 01597 ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]); 01598 AST_RWLIST_UNLOCK(&users); 01599 return CLI_SUCCESS; 01600 } 01601 01602 ast_cli(a->fd, "\n"); 01603 ast_cli(a->fd, 01604 " username: %s\n" 01605 " secret: %s\n" 01606 " acl: %s\n" 01607 " read perm: %s\n" 01608 " write perm: %s\n" 01609 "displayconnects: %s\n", 01610 (user->username ? user->username : "(N/A)"), 01611 (user->secret ? "<Set>" : "(N/A)"), 01612 (user->ha ? "yes" : "no"), 01613 authority_to_str(user->readperm, &rauthority), 01614 authority_to_str(user->writeperm, &wauthority), 01615 (user->displayconnects ? "yes" : "no")); 01616 01617 AST_RWLIST_UNLOCK(&users); 01618 01619 return CLI_SUCCESS; 01620 }
| static char* handle_showmanagers | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1622 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.
01623 { 01624 struct ast_manager_user *user = NULL; 01625 int count_amu = 0; 01626 switch (cmd) { 01627 case CLI_INIT: 01628 e->command = "manager show users"; 01629 e->usage = 01630 "Usage: manager show users\n" 01631 " Prints a listing of all managers that are currently configured on that\n" 01632 " system.\n"; 01633 return NULL; 01634 case CLI_GENERATE: 01635 return NULL; 01636 } 01637 if (a->argc != 3) { 01638 return CLI_SHOWUSAGE; 01639 } 01640 01641 AST_RWLIST_RDLOCK(&users); 01642 01643 /* If there are no users, print out something along those lines */ 01644 if (AST_RWLIST_EMPTY(&users)) { 01645 ast_cli(a->fd, "There are no manager users.\n"); 01646 AST_RWLIST_UNLOCK(&users); 01647 return CLI_SUCCESS; 01648 } 01649 01650 ast_cli(a->fd, "\nusername\n--------\n"); 01651 01652 AST_RWLIST_TRAVERSE(&users, user, list) { 01653 ast_cli(a->fd, "%s\n", user->username); 01654 count_amu++; 01655 } 01656 01657 AST_RWLIST_UNLOCK(&users); 01658 01659 ast_cli(a->fd,"-------------------\n" 01660 "%d manager users configured.\n", count_amu); 01661 return CLI_SUCCESS; 01662 }
| static char* handle_showmancmd | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1456 of file manager.c.
References manager_action::action, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_strdup, AST_XML_DOC, manager_action::authority, authority_to_str(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_MAGENTA, ast_cli_entry::command, manager_action::docsrc, ast_cli_args::fd, ast_cli_args::n, S_OR, term_color(), ast_cli_entry::usage, and ast_cli_args::word.
01457 { 01458 struct manager_action *cur; 01459 struct ast_str *authority; 01460 int num, l, which; 01461 char *ret = NULL; 01462 #ifdef AST_XML_DOCS 01463 char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64]; 01464 #endif 01465 01466 switch (cmd) { 01467 case CLI_INIT: 01468 e->command = "manager show command"; 01469 e->usage = 01470 "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n" 01471 " Shows the detailed description for a specific Asterisk manager interface command.\n"; 01472 return NULL; 01473 case CLI_GENERATE: 01474 l = strlen(a->word); 01475 which = 0; 01476 AST_RWLIST_RDLOCK(&actions); 01477 AST_RWLIST_TRAVERSE(&actions, cur, list) { 01478 if (!strncasecmp(a->word, cur->action, l) && ++which > a->n) { 01479 ret = ast_strdup(cur->action); 01480 break; /* make sure we exit even if ast_strdup() returns NULL */ 01481 } 01482 } 01483 AST_RWLIST_UNLOCK(&actions); 01484 return ret; 01485 } 01486 authority = ast_str_alloca(80); 01487 if (a->argc < 4) { 01488 return CLI_SHOWUSAGE; 01489 } 01490 01491 #ifdef AST_XML_DOCS 01492 /* setup the titles */ 01493 term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01494 term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40); 01495 term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01496 term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40); 01497 term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 01498 #endif 01499 01500 AST_RWLIST_RDLOCK(&actions); 01501 AST_RWLIST_TRAVERSE(&actions, cur, list) { 01502 for (num = 3; num < a->argc; num++) { 01503 if (!strcasecmp(cur->action, a->argv[num])) { 01504 #ifdef AST_XML_DOCS 01505 if (cur->docsrc == AST_XML_DOC) { 01506 ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n", 01507 syntax_title, 01508 ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1), 01509 synopsis_title, 01510 ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1), 01511 description_title, 01512 ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1), 01513 arguments_title, 01514 ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1), 01515 seealso_title, 01516 ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1)); 01517 } else 01518 #endif 01519 { 01520 ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n", 01521 cur->action, cur->synopsis, 01522 authority_to_str(cur->authority, &authority), 01523 S_OR(cur->description, "")); 01524 } 01525 } 01526 } 01527 } 01528 AST_RWLIST_UNLOCK(&actions); 01529 01530 return CLI_SUCCESS; 01531 }
| 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 1665 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.
01666 { 01667 struct manager_action *cur; 01668 struct ast_str *authority; 01669 #define HSMC_FORMAT " %-15.15s %-15.15s %-55.55s\n" 01670 switch (cmd) { 01671 case CLI_INIT: 01672 e->command = "manager show commands"; 01673 e->usage = 01674 "Usage: manager show commands\n" 01675 " Prints a listing of all the available Asterisk manager interface commands.\n"; 01676 return NULL; 01677 case CLI_GENERATE: 01678 return NULL; 01679 } 01680 authority = ast_str_alloca(80); 01681 ast_cli(a->fd, HSMC_FORMAT, "Action", "Privilege", "Synopsis"); 01682 ast_cli(a->fd, HSMC_FORMAT, "------", "---------", "--------"); 01683 01684 AST_RWLIST_RDLOCK(&actions); 01685 AST_RWLIST_TRAVERSE(&actions, cur, list) { 01686 ast_cli(a->fd, HSMC_FORMAT, cur->action, authority_to_str(cur->authority, &authority), cur->synopsis); 01687 } 01688 AST_RWLIST_UNLOCK(&actions); 01689 01690 return CLI_SUCCESS; 01691 }
| 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 1694 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, mansession_session::sessionstart, mansession_session::sin, unref_mansession(), ast_cli_entry::usage, mansession_session::username, and mansession_session::writeperm.
01695 { 01696 struct mansession_session *session; 01697 time_t now = time(NULL); 01698 #define HSMCONN_FORMAT1 " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n" 01699 #define HSMCONN_FORMAT2 " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n" 01700 int count = 0; 01701 struct ao2_iterator i; 01702 01703 switch (cmd) { 01704 case CLI_INIT: 01705 e->command = "manager show connected"; 01706 e->usage = 01707 "Usage: manager show connected\n" 01708 " Prints a listing of the users that are currently connected to the\n" 01709 "Asterisk manager interface.\n"; 01710 return NULL; 01711 case CLI_GENERATE: 01712 return NULL; 01713 } 01714 01715 ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write"); 01716 01717 i = ao2_iterator_init(sessions, 0); 01718 while ((session = ao2_iterator_next(&i))) { 01719 ao2_lock(session); 01720 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); 01721 count++; 01722 ao2_unlock(session); 01723 unref_mansession(session); 01724 } 01725 ao2_iterator_destroy(&i); 01726 ast_cli(a->fd, "%d users connected.\n", count); 01727 01728 return CLI_SUCCESS; 01729 }
| 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 1733 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.
01734 { 01735 struct eventqent *s; 01736 switch (cmd) { 01737 case CLI_INIT: 01738 e->command = "manager show eventq"; 01739 e->usage = 01740 "Usage: manager show eventq\n" 01741 " Prints a listing of all events pending in the Asterisk manger\n" 01742 "event queue.\n"; 01743 return NULL; 01744 case CLI_GENERATE: 01745 return NULL; 01746 } 01747 AST_RWLIST_RDLOCK(&all_events); 01748 AST_RWLIST_TRAVERSE(&all_events, s, eq_next) { 01749 ast_cli(a->fd, "Usecount: %d\n", s->usecount); 01750 ast_cli(a->fd, "Category: %d\n", s->category); 01751 ast_cli(a->fd, "Event:\n%s", s->eventdata); 01752 } 01753 AST_RWLIST_UNLOCK(&all_events); 01754 01755 return CLI_SUCCESS; 01756 }
| static enum error_type handle_updates | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| struct ast_config * | cfg, | |||
| const char * | dfn | |||
| ) | [static] |
helper function for action_updateconfig
Definition at line 2665 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().
02666 { 02667 int x; 02668 char hdr[40]; 02669 const char *action, *cat, *var, *value, *match, *line; 02670 struct ast_category *category; 02671 struct ast_variable *v; 02672 struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16); 02673 enum error_type result = 0; 02674 02675 for (x = 0; x < 100000; x++) { /* 100000 = the max number of allowed updates + 1 */ 02676 unsigned int object = 0; 02677 02678 snprintf(hdr, sizeof(hdr), "Action-%06d", x); 02679 action = astman_get_header(m, hdr); 02680 if (ast_strlen_zero(action)) /* breaks the for loop if no action header */ 02681 break; /* this could cause problems if actions come in misnumbered */ 02682 02683 snprintf(hdr, sizeof(hdr), "Cat-%06d", x); 02684 cat = astman_get_header(m, hdr); 02685 if (ast_strlen_zero(cat)) { /* every action needs a category */ 02686 result = UNSPECIFIED_CATEGORY; 02687 break; 02688 } 02689 02690 snprintf(hdr, sizeof(hdr), "Var-%06d", x); 02691 var = astman_get_header(m, hdr); 02692 02693 snprintf(hdr, sizeof(hdr), "Value-%06d", x); 02694 value = astman_get_header(m, hdr); 02695 02696 if (!ast_strlen_zero(value) && *value == '>') { 02697 object = 1; 02698 value++; 02699 } 02700 02701 snprintf(hdr, sizeof(hdr), "Match-%06d", x); 02702 match = astman_get_header(m, hdr); 02703 02704 snprintf(hdr, sizeof(hdr), "Line-%06d", x); 02705 line = astman_get_header(m, hdr); 02706 02707 if (!strcasecmp(action, "newcat")) { 02708 if (ast_category_get(cfg,cat)) { /* check to make sure the cat doesn't */ 02709 result = FAILURE_NEWCAT; /* already exist */ 02710 break; 02711 } 02712 if (!(category = ast_category_new(cat, dfn, -1))) { 02713 result = FAILURE_ALLOCATION; 02714 break; 02715 } 02716 if (ast_strlen_zero(match)) { 02717 ast_category_append(cfg, category); 02718 } else { 02719 ast_category_insert(cfg, category, match); 02720 } 02721 } else if (!strcasecmp(action, "renamecat")) { 02722 if (ast_strlen_zero(value)) { 02723 result = UNSPECIFIED_ARGUMENT; 02724 break; 02725 } 02726 if (!(category = ast_category_get(cfg, cat))) { 02727 result = UNKNOWN_CATEGORY; 02728 break; 02729 } 02730 ast_category_rename(category, value); 02731 } else if (!strcasecmp(action, "delcat")) { 02732 if (ast_category_delete(cfg, cat)) { 02733 result = FAILURE_DELCAT; 02734 break; 02735 } 02736 } else if (!strcasecmp(action, "emptycat")) { 02737 if (ast_category_empty(cfg, cat)) { 02738 result = FAILURE_EMPTYCAT; 02739 break; 02740 } 02741 } else if (!strcasecmp(action, "update")) { 02742 if (ast_strlen_zero(var)) { 02743 result = UNSPECIFIED_ARGUMENT; 02744 break; 02745 } 02746 if (!(category = ast_category_get(cfg,cat))) { 02747 result = UNKNOWN_CATEGORY; 02748 break; 02749 } 02750 if (ast_variable_update(category, var, value, match, object)) { 02751 result = FAILURE_UPDATE; 02752 break; 02753 } 02754 } else if (!strcasecmp(action, "delete")) { 02755 if ((ast_strlen_zero(var) && ast_strlen_zero(line))) { 02756 result = UNSPECIFIED_ARGUMENT; 02757 break; 02758 } 02759 if (!(category = ast_category_get(cfg, cat))) { 02760 result = UNKNOWN_CATEGORY; 02761 break; 02762 } 02763 if (ast_variable_delete(category, var, match, line)) { 02764 result = FAILURE_DELETE; 02765 break; 02766 } 02767 } else if (!strcasecmp(action, "append")) { 02768 if (ast_strlen_zero(var)) { 02769 result = UNSPECIFIED_ARGUMENT; 02770 break; 02771 } 02772 if (!(category = ast_category_get(cfg, cat))) { 02773 result = UNKNOWN_CATEGORY; 02774 break; 02775 } 02776 if (!(v = ast_variable_new(var, value, dfn))) { 02777 result = FAILURE_ALLOCATION; 02778 break; 02779 } 02780 if (object || (match && !strcasecmp(match, "object"))) { 02781 v->object = 1; 02782 } 02783 ast_variable_append(category, v); 02784 } else if (!strcasecmp(action, "insert")) { 02785 if (ast_strlen_zero(var) || ast_strlen_zero(line)) { 02786 result = UNSPECIFIED_ARGUMENT; 02787 break; 02788 } 02789 if (!(category = ast_category_get(cfg, cat))) { 02790 result = UNKNOWN_CATEGORY; 02791 break; 02792 } 02793 if (!(v = ast_variable_new(var, value, dfn))) { 02794 result = FAILURE_ALLOCATION; 02795 break; 02796 } 02797 ast_variable_insert(category, v, line); 02798 } 02799 else { 02800 ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action); 02801 result = UNKNOWN_ACTION; 02802 break; 02803 } 02804 } 02805 ast_free(str1); 02806 ast_free(str2); 02807 return result; 02808 }
| 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 2587 of file manager.c.
Referenced by astman_append_json().
02588 { 02589 for (; *in; in++) { 02590 if (*in == '\\' || *in == '\"') { 02591 *out++ = '\\'; 02592 } 02593 *out++ = *in; 02594 } 02595 *out = '\0'; 02596 }
| static struct ast_variable* man_do_variable_value | ( | struct ast_variable * | head, | |
| const char * | hdr_val | |||
| ) | [static, read] |
Definition at line 1855 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(), strsep(), and var.
Referenced by astman_get_variables().
01856 { 01857 char *parse; 01858 AST_DECLARE_APP_ARGS(args, 01859 AST_APP_ARG(vars)[64]; 01860 ); 01861 01862 hdr_val = ast_skip_blanks(hdr_val); /* ignore leading spaces in the value */ 01863 parse = ast_strdupa(hdr_val); 01864 01865 /* Break the header value string into name=val pair items. */ 01866 AST_STANDARD_APP_ARGS(args, parse); 01867 if (args.argc) { 01868 int y; 01869 01870 /* Process each name=val pair item. */ 01871 for (y = 0; y < args.argc; y++) { 01872 struct ast_variable *cur; 01873 char *var; 01874 char *val; 01875 01876 if (!args.vars[y]) { 01877 continue; 01878 } 01879 var = val = args.vars[y]; 01880 strsep(&val, "="); 01881 01882 /* XXX We may wish to trim whitespace from the strings. */ 01883 if (!val || ast_strlen_zero(var)) { 01884 continue; 01885 } 01886 01887 /* Create new variable list node and prepend it to the list. */ 01888 cur = ast_variable_new(var, val, ""); 01889 if (cur) { 01890 cur->next = head; 01891 head = cur; 01892 } 01893 } 01894 } 01895 01896 return head; 01897 }
| static enum add_filter_result manager_add_filter | ( | const char * | filter_pattern, | |
| struct ao2_container * | whitefilters, | |||
| struct ao2_container * | blackfilters | |||
| ) | [static] |
Definition at line 4351 of file manager.c.
References ao2_t_alloc, ao2_t_link, ao2_t_ref, event_filter_destructor(), FILTER_ALLOC_FAILED, FILTER_COMPILE_FAIL, and FILTER_SUCCESS.
Referenced by __init_manager(), and action_filter().
04351 { 04352 regex_t *new_filter = ao2_t_alloc(sizeof(*new_filter), event_filter_destructor, "event_filter allocation"); 04353 int is_blackfilter; 04354 04355 if (!new_filter) { 04356 return FILTER_ALLOC_FAILED; 04357 } 04358 04359 if (filter_pattern[0] == '!') { 04360 is_blackfilter = 1; 04361 filter_pattern++; 04362 } else { 04363 is_blackfilter = 0; 04364 } 04365 04366 if (regcomp(new_filter, filter_pattern, 0)) { 04367 ao2_t_ref(new_filter, -1, "failed to make regx"); 04368 return FILTER_COMPILE_FAIL; 04369 } 04370 04371 if (is_blackfilter) { 04372 ao2_t_link(blackfilters, new_filter, "link new filter into black user container"); 04373 } else { 04374 ao2_t_link(whitefilters, new_filter, "link new filter into white user container"); 04375 } 04376 04377 return FILTER_SUCCESS; 04378 }
| static int manager_displayconnects | ( | struct mansession_session * | session | ) | [static] |
Get displayconnects config option.
| session | manager session to get parameter from. |
Definition at line 1442 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().
01443 { 01444 struct ast_manager_user *user = NULL; 01445 int ret = 0; 01446 01447 AST_RWLIST_RDLOCK(&users); 01448 if ((user = get_manager_by_name_locked (session->username))) { 01449 ret = user->displayconnects; 01450 } 01451 AST_RWLIST_UNLOCK(&users); 01452 01453 return ret; 01454 }
| static int manager_modulecheck | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Manager function to check if module is loaded.
Definition at line 4634 of file manager.c.
References ast_copy_string(), ast_debug, ast_file_version_find(), ast_module_check(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), and version.
Referenced by __init_manager().
04635 { 04636 int res; 04637 const char *module = astman_get_header(m, "Module"); 04638 const char *id = astman_get_header(m, "ActionID"); 04639 char idText[256]; 04640 #if !defined(LOW_MEMORY) 04641 const char *version; 04642 #endif 04643 char filename[PATH_MAX]; 04644 char *cut; 04645 04646 ast_copy_string(filename, module, sizeof(filename)); 04647 if ((cut = strchr(filename, '.'))) { 04648 *cut = '\0'; 04649 } else { 04650 cut = filename + strlen(filename); 04651 } 04652 snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".so"); 04653 ast_debug(1, "**** ModuleCheck .so file %s\n", filename); 04654 res = ast_module_check(filename); 04655 if (!res) { 04656 astman_send_error(s, m, "Module not loaded"); 04657 return 0; 04658 } 04659 snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".c"); 04660 ast_debug(1, "**** ModuleCheck .c file %s\n", filename); 04661 #if !defined(LOW_MEMORY) 04662 version = ast_file_version_find(filename); 04663 #endif 04664 04665 if (!ast_strlen_zero(id)) { 04666 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 04667 } else { 04668 idText[0] = '\0'; 04669 } 04670 astman_append(s, "Response: Success\r\n%s", idText); 04671 #if !defined(LOW_MEMORY) 04672 astman_append(s, "Version: %s\r\n\r\n", version ? version : ""); 04673 #endif 04674 return 0; 04675 }
| static int manager_moduleload | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 4677 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().
04678 { 04679 int res; 04680 const char *module = astman_get_header(m, "Module"); 04681 const char *loadtype = astman_get_header(m, "LoadType"); 04682 04683 if (!loadtype || strlen(loadtype) == 0) { 04684 astman_send_error(s, m, "Incomplete ModuleLoad action."); 04685 } 04686 if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0) { 04687 astman_send_error(s, m, "Need module name"); 04688 } 04689 04690 if (!strcasecmp(loadtype, "load")) { 04691 res = ast_load_resource(module); 04692 if (res) { 04693 astman_send_error(s, m, "Could not load module."); 04694 } else { 04695 astman_send_ack(s, m, "Module loaded."); 04696 } 04697 } else if (!strcasecmp(loadtype, "unload")) { 04698 res = ast_unload_resource(module, AST_FORCE_SOFT); 04699 if (res) { 04700 astman_send_error(s, m, "Could not unload module."); 04701 } else { 04702 astman_send_ack(s, m, "Module unloaded."); 04703 } 04704 } else if (!strcasecmp(loadtype, "reload")) { 04705 if (!ast_strlen_zero(module)) { 04706 res = ast_module_reload(module); 04707 if (res == 0) { 04708 astman_send_error(s, m, "No such module."); 04709 } else if (res == 1) { 04710 astman_send_error(s, m, "Module does not support reload action."); 04711 } else { 04712 astman_send_ack(s, m, "Module reloaded."); 04713 } 04714 } else { 04715 ast_module_reload(NULL); /* Reload all modules */ 04716 astman_send_ack(s, m, "All modules reloaded"); 04717 } 04718 } else 04719 astman_send_error(s, m, "Incomplete ModuleLoad action."); 04720 return 0; 04721 }
| static int manager_state_cb | ( | const char * | context, | |
| const char * | exten, | |||
| enum ast_extension_states | state, | |||
| void * | data | |||
| ) | [static] |
Definition at line 5316 of file manager.c.
References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.
Referenced by __init_manager().
05317 { 05318 /* Notify managers of change */ 05319 char hint[512]; 05320 ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten); 05321 05322 manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state); 05323 return 0; 05324 }
| static int mansession_cmp_fn | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Definition at line 1394 of file manager.c.
References CMP_MATCH, str, and mansession_session::username.
Referenced by __init_manager().
01395 { 01396 struct mansession_session *s = obj; 01397 char *str = arg; 01398 return !strcasecmp(s->username, str) ? CMP_MATCH : 0; 01399 }
| static struct sockaddr_in* mansession_encode_sin_local | ( | const struct mansession * | s, | |
| struct sockaddr_in * | sin_local | |||
| ) | [static, read] |
Definition at line 2154 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().
02156 { 02157 ast_sockaddr_to_sin(&s->tcptls_session->parent->local_address, 02158 sin_local); 02159 02160 return sin_local; 02161 }
| static enum ast_security_event_transport_type mansession_get_transport | ( | const struct mansession * | s | ) | [static] |
Definition at line 2148 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().
02149 { 02150 return s->tcptls_session->parent->tls_cfg ? AST_SECURITY_EVENT_TRANSPORT_TLS : 02151 AST_SECURITY_EVENT_TRANSPORT_TCP; 02152 }
| static void mansession_lock | ( | struct mansession * | s | ) | [static] |
Lock the 'mansession' structure.
Definition at line 2120 of file manager.c.
References ast_mutex_lock, and mansession::lock.
Referenced by action_challenge(), do_message(), and process_message().
02121 { 02122 ast_mutex_lock(&s->lock); 02123 }
| static void mansession_unlock | ( | struct mansession * | s | ) | [static] |
Unlock the 'mansession' structure.
Definition at line 2126 of file manager.c.
References ast_mutex_unlock, and mansession::lock.
Referenced by action_challenge(), do_message(), and process_message().
02127 { 02128 ast_mutex_unlock(&s->lock); 02129 }
| static int match_filter | ( | struct mansession * | s, | |
| char * | eventdata | |||
| ) | [static] |
Definition at line 4380 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().
04381 { 04382 int result = 0; 04383 04384 ast_debug(3, "Examining event:\n%s\n", eventdata); 04385 if (!ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) { 04386 return 1; /* no filtering means match all */ 04387 } else if (ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) { 04388 /* white filters only: implied black all filter processed first, then white filters */ 04389 ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04390 } else if (!ao2_container_count(s->session->whitefilters) && ao2_container_count(s->session->blackfilters)) { 04391 /* black filters only: implied white all filter processed first, then black filters */ 04392 ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04393 } else { 04394 /* white and black filters: implied black all filter processed first, then white filters, and lastly black filters */ 04395 ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04396 if (result) { 04397 result = 0; 04398 ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04399 } 04400 } 04401 04402 return result; 04403 }
| 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 4410 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().
04411 { 04412 int ret = 0; 04413 04414 ao2_lock(s->session); 04415 if (s->session->f != NULL) { 04416 struct eventqent *eqe = s->session->last_ev; 04417 04418 while ((eqe = advance_event(eqe))) { 04419 if (!ret && s->session->authenticated && 04420 (s->session->readperm & eqe->category) == eqe->category && 04421 (s->session->send_events & eqe->category) == eqe->category) { 04422 if (match_filter(s, eqe->eventdata)) { 04423 if (send_string(s, eqe->eventdata) < 0) 04424 ret = -1; /* don't send more */ 04425 } 04426 } 04427 s->session->last_ev = eqe; 04428 } 04429 } 04430 ao2_unlock(s->session); 04431 return ret; 04432 }
| static int process_message | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Process an AMI message, performing desired action. Return 0 on success, -1 on error that require the session to be destroyed.
Definition at line 4736 of file manager.c.
References __astman_get_header(), manager_action::action, action_find(), 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(), generic_http_callback(), and http_post_callback().
04737 { 04738 int ret = 0; 04739 struct manager_action *act_found; 04740 const char *user; 04741 const char *action; 04742 04743 action = __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY); 04744 if (ast_strlen_zero(action)) { 04745 report_req_bad_format(s, "NONE"); 04746 mansession_lock(s); 04747 astman_send_error(s, m, "Missing action in request"); 04748 mansession_unlock(s); 04749 return 0; 04750 } 04751 04752 if (!s->session->authenticated 04753 && strcasecmp(action, "Login") 04754 && strcasecmp(action, "Logoff") 04755 && strcasecmp(action, "Challenge")) { 04756 if (!s->session->authenticated) { 04757 report_req_not_allowed(s, action); 04758 } 04759 mansession_lock(s); 04760 astman_send_error(s, m, "Permission denied"); 04761 mansession_unlock(s); 04762 return 0; 04763 } 04764 04765 if (!allowmultiplelogin 04766 && !s->session->authenticated 04767 && (!strcasecmp(action, "Login") 04768 || !strcasecmp(action, "Challenge"))) { 04769 user = astman_get_header(m, "Username"); 04770 04771 if (check_manager_session_inuse(user)) { 04772 report_session_limit(s); 04773 sleep(1); 04774 mansession_lock(s); 04775 astman_send_error(s, m, "Login Already In Use"); 04776 mansession_unlock(s); 04777 return -1; 04778 } 04779 } 04780 04781 act_found = action_find(action); 04782 if (act_found) { 04783 /* Found the requested AMI action. */ 04784 int acted = 0; 04785 04786 if ((s->session->writeperm & act_found->authority) 04787 || act_found->authority == 0) { 04788 /* We have the authority to execute the action. */ 04789 ao2_lock(act_found); 04790 if (act_found->registered && act_found->func) { 04791 ast_debug(1, "Running action '%s'\n", act_found->action); 04792 ret = act_found->func(s, m); 04793 acted = 1; 04794 } 04795 ao2_unlock(act_found); 04796 } 04797 if (!acted) { 04798 /* 04799 * We did not execute the action because access was denied, it 04800 * was no longer registered, or no action was really registered. 04801 * Complain about it and leave. 04802 */ 04803 report_req_not_allowed(s, action); 04804 mansession_lock(s); 04805 astman_send_error(s, m, "Permission denied"); 04806 mansession_unlock(s); 04807 } 04808 ao2_t_ref(act_found, -1, "done with found action object"); 04809 } else { 04810 char buf[512]; 04811 04812 report_req_bad_format(s, action); 04813 snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action); 04814 mansession_lock(s); 04815 astman_send_error(s, m, buf); 04816 mansession_unlock(s); 04817 } 04818 if (ret) { 04819 return ret; 04820 } 04821 /* Once done with our message, deliver any pending events unless the 04822 requester doesn't want them as part of this response. 04823 */ 04824 if (ast_strlen_zero(astman_get_header(m, "SuppressEvents"))) { 04825 return process_events(s); 04826 } else { 04827 return ret; 04828 } 04829 }
| 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 1166 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().
01167 { 01168 struct eventqent *ev; 01169 struct timeval now = ast_tvnow(); 01170 01171 AST_RWLIST_WRLOCK(&all_events); 01172 while ( (ev = AST_RWLIST_FIRST(&all_events)) && 01173 ev->usecount == 0 && AST_RWLIST_NEXT(ev, eq_next)) { 01174 AST_RWLIST_REMOVE_HEAD(&all_events, eq_next); 01175 ast_free(ev); 01176 } 01177 01178 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&all_events, ev, eq_next) { 01179 /* Never release the last event */ 01180 if (!AST_RWLIST_NEXT(ev, eq_next)) { 01181 break; 01182 } 01183 01184 /* 2.5 times whatever the HTTP timeout is (maximum 2.5 hours) is the maximum time that we will definitely cache an event */ 01185 if (ev->usecount == 0 && ast_tvdiff_sec(now, ev->tv) > (httptimeout > 3600 ? 3600 : httptimeout) * 2.5) { 01186 AST_RWLIST_REMOVE_CURRENT(eq_next); 01187 ast_free(ev); 01188 } 01189 } 01190 AST_RWLIST_TRAVERSE_SAFE_END; 01191 AST_RWLIST_UNLOCK(&all_events); 01192 }
| static void purge_sessions | ( | int | n_max | ) | [static] |
remove at most n_max stale session from the list.
Definition at line 5116 of file manager.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_inet_ntoa(), ast_verb, mansession_session::authenticated, mansession_session::inuse, manager_displayconnects(), session_destroy(), mansession_session::sessiontimeout, mansession_session::sin, unref_mansession(), mansession_session::username, and VERBOSITY_ATLEAST.
Referenced by purge_old_stuff().
05117 { 05118 struct mansession_session *session; 05119 time_t now = time(NULL); 05120 struct ao2_iterator i; 05121 05122 i = ao2_iterator_init(sessions, 0); 05123 while ((session = ao2_iterator_next(&i)) && n_max > 0) { 05124 ao2_lock(session); 05125 if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) { 05126 if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) { 05127 ast_verb(2, "HTTP Manager '%s' timed out from %s\n", 05128 session->username, ast_inet_ntoa(session->sin.sin_addr)); 05129 } 05130 ao2_unlock(session); 05131 session_destroy(session); 05132 n_max--; 05133 } else { 05134 ao2_unlock(session); 05135 unref_mansession(session); 05136 } 05137 } 05138 ao2_iterator_destroy(&i); 05139 }
| static void report_auth_success | ( | const struct mansession * | s | ) | [static] |
Definition at line 2241 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().
02242 { 02243 struct sockaddr_in sin_local; 02244 char session_id[32]; 02245 struct ast_security_event_successful_auth successful_auth = { 02246 .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH, 02247 .common.version = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION, 02248 .common.service = "AMI", 02249 .common.account_id = s->session->username, 02250 .common.session_tv = &s->session->sessionstart_tv, 02251 .common.local_addr = { 02252 .sin = mansession_encode_sin_local(s, &sin_local), 02253 .transport = mansession_get_transport(s), 02254 }, 02255 .common.remote_addr = { 02256 .sin = &s->session->sin, 02257 .transport = mansession_get_transport(s), 02258 }, 02259 .common.session_id = session_id, 02260 }; 02261 02262 snprintf(session_id, sizeof(session_id), "%p", s->session); 02263 02264 ast_security_event_report(AST_SEC_EVT(&successful_auth)); 02265 }
| static void report_failed_acl | ( | const struct mansession * | s, | |
| const char * | username | |||
| ) | [static] |
Definition at line 2189 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().
02190 { 02191 struct sockaddr_in sin_local; 02192 char session_id[32]; 02193 struct ast_security_event_failed_acl failed_acl_event = { 02194 .common.event_type = AST_SECURITY_EVENT_FAILED_ACL, 02195 .common.version = AST_SECURITY_EVENT_FAILED_ACL_VERSION, 02196 .common.service = "AMI", 02197 .common.account_id = username, 02198 .common.session_tv = &s->session->sessionstart_tv, 02199 .common.local_addr = { 02200 .sin = mansession_encode_sin_local(s, &sin_local), 02201 .transport = mansession_get_transport(s), 02202 }, 02203 .common.remote_addr = { 02204 .sin = &s->session->sin, 02205 .transport = mansession_get_transport(s), 02206 }, 02207 .common.session_id = session_id, 02208 }; 02209 02210 snprintf(session_id, sizeof(session_id), "%p", s->session); 02211 02212 ast_security_event_report(AST_SEC_EVT(&failed_acl_event)); 02213 }
| static void report_failed_challenge_response | ( | const struct mansession * | s, | |
| const char * | response, | |||
| const char * | expected_response | |||
| ) | [static] |
Definition at line 2327 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().
02329 { 02330 struct sockaddr_in sin_local; 02331 char session_id[32]; 02332 struct ast_security_event_chal_resp_failed chal_resp_failed = { 02333 .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED, 02334 .common.version = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION, 02335 .common.service = "AMI", 02336 .common.account_id = s->session->username, 02337 .common.session_tv = &s->session->sessionstart_tv, 02338 .common.local_addr = { 02339 .sin = mansession_encode_sin_local(s, &sin_local), 02340 .transport = mansession_get_transport(s), 02341 }, 02342 .common.remote_addr = { 02343 .sin = &s->session->sin, 02344 .transport = mansession_get_transport(s), 02345 }, 02346 .common.session_id = session_id, 02347 02348 .challenge = s->session->challenge, 02349 .response = response, 02350 .expected_response = expected_response, 02351 }; 02352 02353 snprintf(session_id, sizeof(session_id), "%p", s->session); 02354 02355 ast_security_event_report(AST_SEC_EVT(&chal_resp_failed)); 02356 }
| static void report_inval_password | ( | const struct mansession * | s, | |
| const char * | username | |||
| ) | [static] |
Definition at line 2215 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().
02216 { 02217 struct sockaddr_in sin_local; 02218 char session_id[32]; 02219 struct ast_security_event_inval_password inval_password = { 02220 .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD, 02221 .common.version = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION, 02222 .common.service = "AMI", 02223 .common.account_id = username, 02224 .common.session_tv = &s->session->sessionstart_tv, 02225 .common.local_addr = { 02226 .sin = mansession_encode_sin_local(s, &sin_local), 02227 .transport = mansession_get_transport(s), 02228 }, 02229 .common.remote_addr = { 02230 .sin = &s->session->sin, 02231 .transport = mansession_get_transport(s), 02232 }, 02233 .common.session_id = session_id, 02234 }; 02235 02236 snprintf(session_id, sizeof(session_id), "%p", s->session); 02237 02238 ast_security_event_report(AST_SEC_EVT(&inval_password)); 02239 }
| static void report_invalid_user | ( | const struct mansession * | s, | |
| const char * | username | |||
| ) | [static] |
Definition at line 2163 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().
02164 { 02165 struct sockaddr_in sin_local; 02166 char session_id[32]; 02167 struct ast_security_event_inval_acct_id inval_acct_id = { 02168 .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID, 02169 .common.version = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION, 02170 .common.service = "AMI", 02171 .common.account_id = username, 02172 .common.session_tv = &s->session->sessionstart_tv, 02173 .common.local_addr = { 02174 .sin = mansession_encode_sin_local(s, &sin_local), 02175 .transport = mansession_get_transport(s), 02176 }, 02177 .common.remote_addr = { 02178 .sin = &s->session->sin, 02179 .transport = mansession_get_transport(s), 02180 }, 02181 .common.session_id = session_id, 02182 }; 02183 02184 snprintf(session_id, sizeof(session_id), "%p", s); 02185 02186 ast_security_event_report(AST_SEC_EVT(&inval_acct_id)); 02187 }
| static void report_req_bad_format | ( | const struct mansession * | s, | |
| const char * | action | |||
| ) | [static] |
Definition at line 2297 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().
02298 { 02299 struct sockaddr_in sin_local; 02300 char session_id[32]; 02301 char request_type[64]; 02302 struct ast_security_event_req_bad_format req_bad_format = { 02303 .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT, 02304 .common.version = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION, 02305 .common.service = "AMI", 02306 .common.account_id = s->session->username, 02307 .common.session_tv = &s->session->sessionstart_tv, 02308 .common.local_addr = { 02309 .sin = mansession_encode_sin_local(s, &sin_local), 02310 .transport = mansession_get_transport(s), 02311 }, 02312 .common.remote_addr = { 02313 .sin = &s->session->sin, 02314 .transport = mansession_get_transport(s), 02315 }, 02316 .common.session_id = session_id, 02317 02318 .request_type = request_type, 02319 }; 02320 02321 snprintf(session_id, sizeof(session_id), "%p", s->session); 02322 snprintf(request_type, sizeof(request_type), "Action: %s", action); 02323 02324 ast_security_event_report(AST_SEC_EVT(&req_bad_format)); 02325 }
| static void report_req_not_allowed | ( | const struct mansession * | s, | |
| const char * | action | |||
| ) | [static] |
Definition at line 2267 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().
02268 { 02269 struct sockaddr_in sin_local; 02270 char session_id[32]; 02271 char request_type[64]; 02272 struct ast_security_event_req_not_allowed req_not_allowed = { 02273 .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED, 02274 .common.version = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION, 02275 .common.service = "AMI", 02276 .common.account_id = s->session->username, 02277 .common.session_tv = &s->session->sessionstart_tv, 02278 .common.local_addr = { 02279 .sin = mansession_encode_sin_local(s, &sin_local), 02280 .transport = mansession_get_transport(s), 02281 }, 02282 .common.remote_addr = { 02283 .sin = &s->session->sin, 02284 .transport = mansession_get_transport(s), 02285 }, 02286 .common.session_id = session_id, 02287 02288 .request_type = request_type, 02289 }; 02290 02291 snprintf(session_id, sizeof(session_id), "%p", s->session); 02292 snprintf(request_type, sizeof(request_type), "Action: %s", action); 02293 02294 ast_security_event_report(AST_SEC_EVT(&req_not_allowed)); 02295 }
| static void report_session_limit | ( | const struct mansession * | s | ) | [static] |
Definition at line 2358 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().
02359 { 02360 struct sockaddr_in sin_local; 02361 char session_id[32]; 02362 struct ast_security_event_session_limit session_limit = { 02363 .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT, 02364 .common.version = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION, 02365 .common.service = "AMI", 02366 .common.account_id = s->session->username, 02367 .common.session_tv = &s->session->sessionstart_tv, 02368 .common.local_addr = { 02369 .sin = mansession_encode_sin_local(s, &sin_local), 02370 .transport = mansession_get_transport(s), 02371 }, 02372 .common.remote_addr = { 02373 .sin = &s->session->sin, 02374 .transport = mansession_get_transport(s), 02375 }, 02376 .common.session_id = session_id, 02377 }; 02378 02379 snprintf(session_id, sizeof(session_id), "%p", s->session); 02380 02381 ast_security_event_report(AST_SEC_EVT(&session_limit)); 02382 }
| 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 1995 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().
01996 { 01997 int res; 01998 FILE *f = s->f ? s->f : s->session->f; 01999 int fd = s->f ? s->fd : s->session->fd; 02000 02001 /* It's a result from one of the hook's action invocation */ 02002 if (s->hook) { 02003 /* 02004 * to send responses, we're using the same function 02005 * as for receiving events. We call the event "HookResponse" 02006 */ 02007 s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string); 02008 return 0; 02009 } 02010 02011 if ((res = ast_careful_fwrite(f, fd, string, strlen(string), s->session->writetimeout))) { 02012 s->write_error = 1; 02013 } 02014 02015 return res; 02016 }
| static void session_destroy | ( | struct mansession_session * | s | ) | [static] |
Definition at line 1401 of file manager.c.
References ao2_unlink, and unref_mansession().
Referenced by auth_http_callback(), generic_http_callback(), purge_sessions(), session_do(), and spandsp_fax_destroy().
01402 { 01403 unref_mansession(s); 01404 ao2_unlink(sessions, s); 01405 }
| static void session_destructor | ( | void * | obj | ) | [static] |
Definition at line 1334 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().
01335 { 01336 struct mansession_session *session = obj; 01337 struct eventqent *eqe = session->last_ev; 01338 struct ast_datastore *datastore; 01339 01340 /* Get rid of each of the data stores on the session */ 01341 while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) { 01342 /* Free the data store */ 01343 ast_datastore_free(datastore); 01344 } 01345 01346 if (session->f != NULL) { 01347 fclose(session->f); 01348 } 01349 if (eqe) { 01350 ast_atomic_fetchadd_int(&eqe->usecount, -1); 01351 } 01352 01353 if (session->whitefilters) { 01354 ao2_t_callback(session->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters"); 01355 ao2_t_ref(session->whitefilters, -1 , "decrement ref for white container, should be last one"); 01356 } 01357 01358 if (session->blackfilters) { 01359 ao2_t_callback(session->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters"); 01360 ao2_t_ref(session->blackfilters, -1 , "decrement ref for black container, should be last one"); 01361 } 01362 }
| 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 5017 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.
05018 { 05019 struct ast_tcptls_session_instance *ser = data; 05020 struct mansession_session *session; 05021 struct mansession s = { 05022 .tcptls_session = data, 05023 }; 05024 int flags; 05025 int res; 05026 struct sockaddr_in ser_remote_address_tmp; 05027 struct protoent *p; 05028 05029 if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) { 05030 fclose(ser->f); 05031 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05032 goto done; 05033 } 05034 05035 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 05036 session = build_mansession(ser_remote_address_tmp); 05037 05038 if (session == NULL) { 05039 fclose(ser->f); 05040 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05041 goto done; 05042 } 05043 05044 /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm. 05045 * This is necessary to prevent delays (caused by buffering) as we 05046 * write to the socket in bits and peices. */ 05047 p = getprotobyname("tcp"); 05048 if (p) { 05049 int arg = 1; 05050 if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) { 05051 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)); 05052 } 05053 } else { 05054 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"); 05055 } 05056 05057 flags = fcntl(ser->fd, F_GETFL); 05058 if (!block_sockets) { /* make sure socket is non-blocking */ 05059 flags |= O_NONBLOCK; 05060 } else { 05061 flags &= ~O_NONBLOCK; 05062 } 05063 fcntl(ser->fd, F_SETFL, flags); 05064 05065 ao2_lock(session); 05066 /* Hook to the tail of the event queue */ 05067 session->last_ev = grab_last(); 05068 05069 ast_mutex_init(&s.lock); 05070 05071 /* these fields duplicate those in the 'ser' structure */ 05072 session->fd = s.fd = ser->fd; 05073 session->f = s.f = ser->f; 05074 session->sin = ser_remote_address_tmp; 05075 s.session = session; 05076 05077 AST_LIST_HEAD_INIT_NOLOCK(&session->datastores); 05078 05079 if(time(&session->authstart) == -1) { 05080 ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno)); 05081 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05082 ao2_unlock(session); 05083 session_destroy(session); 05084 goto done; 05085 } 05086 ao2_unlock(session); 05087 05088 astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */ 05089 for (;;) { 05090 if ((res = do_message(&s)) < 0 || s.write_error) { 05091 break; 05092 } 05093 } 05094 /* session is over, explain why and terminate */ 05095 if (session->authenticated) { 05096 if (manager_displayconnects(session)) { 05097 ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 05098 } 05099 } else { 05100 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05101 if (displayconnects) { 05102 ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr)); 05103 } 05104 } 05105 05106 session_destroy(session); 05107 05108 ast_mutex_destroy(&s.lock); 05109 done: 05110 ao2_ref(ser, -1); 05111 ser = NULL; 05112 return NULL; 05113 }
| 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 2135 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().
02136 { 02137 int maskint = strings_to_mask(eventmask); 02138 02139 ao2_lock(s->session); 02140 if (maskint >= 0) { 02141 s->session->send_events = maskint; 02142 } 02143 ao2_unlock(s->session); 02144 02145 return maskint; 02146 }
| 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 1288 of file manager.c.
References ARRAY_LEN, ast_false(), ast_strlen_zero(), ast_true(), get_perm(), permalias::num, and perms.
Referenced by set_eventmask().
01289 { 01290 const char *p; 01291 01292 if (ast_strlen_zero(string)) { 01293 return -1; 01294 } 01295 01296 for (p = string; *p; p++) { 01297 if (*p < '0' || *p > '9') { 01298 break; 01299 } 01300 } 01301 if (!*p) { /* all digits */ 01302 return atoi(string); 01303 } 01304 if (ast_false(string)) { 01305 return 0; 01306 } 01307 if (ast_true(string)) { /* all permissions */ 01308 int x, ret = 0; 01309 for (x = 0; x < ARRAY_LEN(perms); x++) { 01310 ret |= perms[x].num; 01311 } 01312 return ret; 01313 } 01314 return get_perm(string); 01315 }
| 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 1319 of file manager.c.
References ao2_ref, and ast_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().
01320 { 01321 int refcount = ao2_ref(s, -1); 01322 if (manager_debug) { 01323 ast_debug(1, "Mansession: %p refcount now %d\n", s, refcount - 1); 01324 } 01325 return s; 01326 }
| static int whitefilter_cmp_fn | ( | void * | obj, | |
| void * | arg, | |||
| void * | data, | |||
| int | flags | |||
| ) | [static] |
Definition at line 4269 of file manager.c.
References CMP_MATCH, and CMP_STOP.
Referenced by match_filter().
04270 { 04271 regex_t *regex_filter = obj; 04272 const char *eventdata = arg; 04273 int *result = data; 04274 04275 if (!regexec(regex_filter, eventdata, 0, NULL, 0)) { 04276 *result = 1; 04277 return (CMP_MATCH | CMP_STOP); 04278 } 04279 04280 return 0; 04281 }
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 authtimeout [static] |
int block_sockets [static] |
Definition at line 945 of file manager.c.
Referenced by __init_manager(), handle_manager_show_settings(), and session_do().
int broken_events_action = 0 [static] |
struct { ... } command_blacklist[] [static] |
Referenced by check_blacklist().
int displayconnects = 1 [static] |
char global_realm[MAXHOSTNAMELEN] [static] |
Default realm
Definition at line 943 of file manager.c.
Referenced by __init_manager(), and auth_http_callback().
int httptimeout = 60 [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] |
helper functions to convert back and forth between string and numeric representation of set of flags
Referenced by action_events(), authority_to_str(), get_perm(), and strings_to_mask().
struct ao2_container* sessions = NULL [static] |
int timestampevents [static] |
int unauth_sessions = 0 [static] |
struct ast_threadstorage userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , } [static] |
int webmanager_enabled = 0 [static] |
1.5.6