AMI functions

callback to display queues status in manager More...

Data Structures

struct  actions
 list of actions registered More...
struct  all_events
struct  ast_manager_user
 user descriptor, as read from the config file. More...
struct  eventqent
struct  fast_originate_helper
 helper function for originate More...
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...
 STASIS_MESSAGE_TYPE_DEFN (ast_manager_get_generic_type)
 Define AMI message types.

Defines

#define ASTMAN_APPEND_BUF_INITSIZE   256
 initial allocated size for the astman_append_buf and astman_send_*_va
#define DEFAULT_REALM   "asterisk"
#define EVENT_FLAG_SHUTDOWN   -1
 Fake event class used to end sessions at shutdown.
#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_AUTH_PERM_STRING   150
#define MAX_BLACKLIST_CMD_LEN   2
 Descriptor for a manager session, either on the AMI socket or over HTTP.
#define MAX_VARS   128
#define MGR_SHOW_TERMINAL_WIDTH   80
#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, FAILURE_TEMPLATE
}
enum  mansession_message_parsing { MESSAGE_OKAY, MESSAGE_LINE_TOO_LONG }

Functions

int __ast_manager_event_multichan (int category, const char *event, int chancount, struct ast_channel **chans, const char *file, int line, const char *func, const char *fmt,...)
static const char * __astman_get_header (const struct message *m, char *var, int mode)
 Return a matching header value.
static void __fini_actions (void)
static void __fini_all_events (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_manager_event_buf (void)
static void __init_manager_hooks (void)
static void __init_userevent_buf (void)
static void __init_users (void)
static void acl_change_stasis_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void acl_change_stasis_subscribe (void)
static void acl_change_stasis_unsubscribe (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_blind_transfer (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)
 Manager command to add an event filter to a manager session.
static struct manager_actionaction_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_loggerrotate (struct mansession *s, const struct message *m)
 Manager command "LoggerRotate" - reloads and rotates the logger in the same manner as the CLI command 'logger rotate'.
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_presencestate (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 eventqentadvance_event (struct eventqent *e)
static AO2_GLOBAL_OBJ_STATIC (event_docs)
 A container of event documentation nodes.
static AO2_GLOBAL_OBJ_STATIC (mgr_sessions)
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)
struct stasis_message_routerast_manager_get_message_router (void)
 Get the stasis_message_router for AMI.
struct stasis_topicast_manager_get_topic (void)
 Get the Stasis Message Bus API topic for AMI.
void ast_manager_publish_event (const char *type, int class_type, struct ast_json *obj)
 Publish an event to AMI.
int ast_manager_register2 (const char *action, int auth, int(*func)(struct mansession *s, const struct message *m), struct ast_module *module, 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)
struct ast_strast_manager_str_from_json_object (struct ast_json *blob, key_exclusion_cb exclusion_cb)
 Convert a JSON object into an AMI compatible string.
int ast_manager_unregister (const 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_variableastman_get_variables (const struct message *m)
 Get a linked list of the Variable: headers.
struct ast_variableastman_get_variables_order (const struct message *m, enum variable_orders order)
 Get a linked list of the Variable: headers with order specified.
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_error_va (struct mansession *s, const struct message *m, const char *fmt,...)
 Send error in manager transaction (with va_args support).
void astman_send_list_complete_end (struct mansession *s)
 End the list complete event.
void astman_send_list_complete_start (struct mansession *s, const struct message *m, const char *event_name, int count)
 Start the list complete event.
void astman_send_listack (struct mansession *s, const struct message *m, char *msg, char *listflag)
 Send ack in manager transaction to begin a list.
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. Note that the EVENT_FLAG_ALL authority will always be returned.
static int blackfilter_cmp_fn (void *obj, void *arg, void *data, int flags)
static struct mansession_sessionbuild_mansession (const struct ast_sockaddr *addr)
 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 int function_capable_string_allowed_with_auths (const char *evaluating, int writepermlist)
 Checks to see if a string which can be used to evaluate functions should be rejected.
static void generate_status (struct mansession *s, struct ast_channel *chan, char **vars, int varc, int all_variables, char *id_text, int *count)
static int get_input (struct mansession *s, char *output)
static struct ast_manager_userget_manager_by_name_locked (const char *name)
static int get_perm (const char *instr)
static struct eventqentgrab_last (void)
static char * handle_manager_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager reload.
static char * handle_mandebug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void handle_parse_error (struct mansession *s, struct message *m, char *error)
static char * handle_showmanager (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmanagers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmancmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmancmds (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list commands.
static char * handle_showmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list connected.
static char * handle_showmaneventq (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list eventq.
static enum error_type handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn)
 helper function for action_updateconfig
static void json_escape (char *out, const char *in)
static struct ast_variableman_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)
 Add an event filter to a manager session.
static void manager_default_msg_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
static int manager_displayconnects (struct mansession_session *session)
 Get displayconnects config option.
static void manager_generic_msg_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void manager_json_array_with_key (struct ast_json *obj, const char *key, size_t index, struct ast_str **res, key_exclusion_cb exclusion_cb)
static void manager_json_obj_with_key (struct ast_json *obj, const char *key, const char *parent_key, struct ast_str **res, key_exclusion_cb exclusion_cb)
static void manager_json_to_ast_str (struct ast_json *obj, const char *key, struct ast_str **res, key_exclusion_cb exclusion_cb)
static void manager_json_value_str_append (struct ast_json *value, const char *key, struct ast_str **res)
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 (char *context, char *exten, struct ast_state_cb_info *info, void *data)
static int mansession_cmp_fn (void *obj, void *arg, int flags)
static enum ast_transport 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 void print_event_instance (struct ast_cli_args *a, struct ast_xml_doc_item *instance)
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_sessionunref_mansession (struct mansession_session *s)
 Unreference manager session object. If no more references, then go ahead and delete it.
static const char * user_authority_to_str (int authority, struct ast_str **res)
 Convert authority code to a list of options for a user. This will only display those authority codes that have an explicit match on authority.
static int whitefilter_cmp_fn (void *obj, void *arg, void *data, int flags)

Variables

static struct stasis_subscriptionacl_change_sub
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 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 stasis_topicmanager_topic
 A stasis_topic that all topics AMI cares about will be forwarded to.
static struct permalias perms []
static struct stasis_forwardrtp_topic_forwarder
 The stasis_subscription for forwarding the RTP topic to the AMI topic.
static struct stasis_forwardsecurity_topic_forwarder
 The stasis_subscription for forwarding the Security topic to the AMI topic.
static struct
stasis_message_router
stasis_router
 The stasis_message_router for all Stasis Message Bus API messages.
static int subscribed = 0
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

Detailed Description

callback to display queues status in manager


Define Documentation

#define ASTMAN_APPEND_BUF_INITSIZE   256

initial allocated size for the astman_append_buf and astman_send_*_va

Definition at line 2815 of file manager.c.

Referenced by astman_append(), and astman_send_error_va().

#define DEFAULT_REALM   "asterisk"

Definition at line 1361 of file manager.c.

#define EVENT_FLAG_SHUTDOWN   -1

Fake event class used to end sessions at shutdown.

Definition at line 1389 of file manager.c.

Referenced by __ast_manager_event_multichan(), authority_to_str(), manager_shutdown(), and process_events().

#define GET_HEADER_FIRST_MATCH   0

Definition at line 2554 of file manager.c.

Referenced by astman_get_header().

#define GET_HEADER_LAST_MATCH   1

Definition at line 2555 of file manager.c.

Referenced by __astman_get_header().

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 2556 of file manager.c.

Referenced by __astman_get_header(), and process_message().

#define MANAGER_EVENT_BUF_INITSIZE   256

Definition at line 6603 of file manager.c.

Referenced by __ast_manager_event_multichan().

#define MAX_AUTH_PERM_STRING   150

Maximum string length of the AMI authority permission string buildable from perms[].

Definition at line 1861 of file manager.c.

Referenced by __ast_manager_event_multichan(), action_listcommands(), action_login(), handle_showmanager(), and handle_showmancmd().

#define MAX_BLACKLIST_CMD_LEN   2

Descriptor for a manager session, either on the AMI socket or over HTTP.

Note:
AMI session have managerid == 0; the entry is created upon a connect, and destroyed with the socket. HTTP sessions have managerid != 0, the value is used as a search key to lookup sessions (using the mansession_id cookie, or nonce key from Digest Authentication http header).

Definition at line 1401 of file manager.c.

Referenced by check_blacklist().

#define MAX_VARS   128

Definition at line 1386 of file manager.c.

Referenced by load_channelvars().

#define MGR_SHOW_TERMINAL_WIDTH   80

Definition at line 1384 of file manager.c.

Referenced by handle_showmancmds().

#define MSG_MOREDATA   ((char *)astman_send_response)

Note:
NOTE: XXX this comment is unclear and possibly wrong. Callers of astman_send_error(), astman_send_response() or astman_send_ack() must EITHER hold the session lock _or_ be running in an action callback (in which case s->session->busy will be non-zero). In either of these cases, there is no need to lock-protect the session's fd, since no other output will be sent (events will be queued), and no input will be read until either the current action finishes or get_input() obtains the session lock.
Todo:
XXX MSG_MOREDATA should go to a header file.

Definition at line 2850 of file manager.c.

Referenced by astman_send_response_full(), and astman_start_ack().


Enumeration Type Documentation

Enumerator:
FILTER_SUCCESS 
FILTER_ALLOC_FAILED 
FILTER_COMPILE_FAIL 

Definition at line 1312 of file manager.c.

01312                        {
01313    FILTER_SUCCESS,
01314    FILTER_ALLOC_FAILED,
01315    FILTER_COMPILE_FAIL,
01316 };

enum error_type

Doxygen group

Enumerator:
UNKNOWN_ACTION 
UNKNOWN_CATEGORY 
UNSPECIFIED_CATEGORY 
UNSPECIFIED_ARGUMENT 
FAILURE_ALLOCATION 
FAILURE_NEWCAT 
FAILURE_DELCAT 
FAILURE_EMPTYCAT 
FAILURE_UPDATE 
FAILURE_DELETE 
FAILURE_APPEND 
FAILURE_TEMPLATE 

Definition at line 1297 of file manager.c.

Enumerator:
MESSAGE_OKAY 
MESSAGE_LINE_TOO_LONG 

Definition at line 1491 of file manager.c.

01491                                 {
01492    MESSAGE_OKAY,
01493    MESSAGE_LINE_TOO_LONG
01494 };


Function Documentation

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

Parameters:
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
file,line,func 
contents Format string describing event
... 
Since:
1.8

Definition at line 6605 of file manager.c.

References ao2_cleanup, ao2_container_count(), ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, append_channel_vars(), append_event(), ast_atomic_fetchadd_int(), ast_config_AST_SYSTEM_NAME, 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_strlen_zero, ast_tvnow(), authority_to_str(), buf, EVENT_FLAG_SHUTDOWN, manager_custom_hook::helper, manager_event_buf, MANAGER_EVENT_BUF_INITSIZE, MAX_AUTH_PERM_STRING, mansession_session::pending_event, RAII_VAR, eventqent::seq, session, unref_mansession(), and mansession_session::waiting_thread.

06608 {
06609    RAII_VAR(struct ao2_container *, sessions, ao2_global_obj_ref(mgr_sessions), ao2_cleanup);
06610    struct mansession_session *session;
06611    struct manager_custom_hook *hook;
06612    struct ast_str *auth = ast_str_alloca(MAX_AUTH_PERM_STRING);
06613    const char *cat_str;
06614    va_list ap;
06615    struct timeval now;
06616    struct ast_str *buf;
06617    int i;
06618 
06619    if (!(sessions && ao2_container_count(sessions)) && AST_RWLIST_EMPTY(&manager_hooks)) {
06620       return 0;
06621    }
06622 
06623    if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) {
06624       return -1;
06625    }
06626 
06627    cat_str = authority_to_str(category, &auth);
06628    ast_str_set(&buf, 0,
06629          "Event: %s\r\nPrivilege: %s\r\n",
06630           event, cat_str);
06631 
06632    if (timestampevents) {
06633       now = ast_tvnow();
06634       ast_str_append(&buf, 0,
06635             "Timestamp: %ld.%06lu\r\n",
06636              (long)now.tv_sec, (unsigned long) now.tv_usec);
06637    }
06638    if (manager_debug) {
06639       static int seq;
06640       ast_str_append(&buf, 0,
06641             "SequenceNumber: %d\r\n",
06642              ast_atomic_fetchadd_int(&seq, 1));
06643       ast_str_append(&buf, 0,
06644             "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func);
06645    }
06646    if (!ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) {
06647       ast_str_append(&buf, 0,
06648             "SystemName: %s\r\n",
06649              ast_config_AST_SYSTEM_NAME);
06650    }
06651 
06652    va_start(ap, fmt);
06653    ast_str_append_va(&buf, 0, fmt, ap);
06654    va_end(ap);
06655    for (i = 0; i < chancount; i++) {
06656       append_channel_vars(&buf, chans[i]);
06657    }
06658 
06659    ast_str_append(&buf, 0, "\r\n");
06660 
06661    append_event(ast_str_buffer(buf), category);
06662 
06663    /* Wake up any sleeping sessions */
06664    if (sessions) {
06665       struct ao2_iterator i;
06666       i = ao2_iterator_init(sessions, 0);
06667       while ((session = ao2_iterator_next(&i))) {
06668          ao2_lock(session);
06669          if (session->waiting_thread != AST_PTHREADT_NULL) {
06670             pthread_kill(session->waiting_thread, SIGURG);
06671          } else {
06672             /* We have an event to process, but the mansession is
06673              * not waiting for it. We still need to indicate that there
06674              * is an event waiting so that get_input processes the pending
06675              * event instead of polling.
06676              */
06677             session->pending_event = 1;
06678          }
06679          ao2_unlock(session);
06680          unref_mansession(session);
06681       }
06682       ao2_iterator_destroy(&i);
06683    }
06684 
06685    if (category != EVENT_FLAG_SHUTDOWN && !AST_RWLIST_EMPTY(&manager_hooks)) {
06686       AST_RWLIST_RDLOCK(&manager_hooks);
06687       AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) {
06688          hook->helper(category, event, ast_str_buffer(buf));
06689       }
06690       AST_RWLIST_UNLOCK(&manager_hooks);
06691    }
06692 
06693    return 0;
06694 }

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.

Note:
At the moment there is only one use of this function in this file, so we make it static.

Never returns NULL.

Definition at line 2571 of file manager.c.

References ast_skip_blanks(), ast_strlen_zero, GET_HEADER_LAST_MATCH, GET_HEADER_SKIP_EMPTY, h, message::hdrcount, message::headers, result, and value.

Referenced by astman_get_header(), and process_message().

02572 {
02573    int x, l = strlen(var);
02574    const char *result = "";
02575 
02576    if (!m) {
02577       return result;
02578    }
02579 
02580    for (x = 0; x < m->hdrcount; x++) {
02581       const char *h = m->headers[x];
02582       if (!strncasecmp(var, h, l) && h[l] == ':') {
02583          const char *value = h + l + 1;
02584          value = ast_skip_blanks(value); /* ignore leading spaces in the value */
02585          /* found a potential candidate */
02586          if ((mode & GET_HEADER_SKIP_EMPTY) && ast_strlen_zero(value)) {
02587             continue;   /* not interesting */
02588          }
02589          if (mode & GET_HEADER_LAST_MATCH) {
02590             result = value;   /* record the last match so far */
02591          } else {
02592             return value;
02593          }
02594       }
02595    }
02596 
02597    return result;
02598 }

static void __fini_actions ( void   )  [static]

Definition at line 1542 of file manager.c.

01555 { \brief Define AMI message types.

static void __fini_all_events ( void   )  [static]

Definition at line 1346 of file manager.c.

01402 {

static void __fini_manager_hooks ( void   )  [static]

Definition at line 1545 of file manager.c.

01555 { \brief Define AMI message types.

static void __fini_users ( void   )  [static]

Definition at line 1539 of file manager.c.

01555 { \brief Define AMI message types.

static void __init_actions ( void   )  [static]

Definition at line 1542 of file manager.c.

01555 { \brief Define AMI message types.

static void __init_all_events ( void   )  [static]

Definition at line 1346 of file manager.c.

01402 {

static void __init_astman_append_buf ( void   )  [static]

thread local buffer for astman_append

Note:
This can not be defined within the astman_append() function because it declares a couple of functions that get used to initialize the thread local storage key.

Definition at line 2810 of file manager.c.

02821 {

static void __init_manager_event_buf ( void   )  [static]

Definition at line 6602 of file manager.c.

06608 {

static void __init_manager_hooks ( void   )  [static]

Definition at line 1545 of file manager.c.

01555 { \brief Define AMI message types.

static void __init_userevent_buf ( void   )  [static]

Definition at line 2812 of file manager.c.

02821 {

static void __init_users ( void   )  [static]

Definition at line 1539 of file manager.c.

01555 { \brief Define AMI message types.

static void acl_change_stasis_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
) [static]

Definition at line 9088 of file manager.c.

References __init_manager(), ast_log, ast_named_acl_change_type(), LOG_NOTICE, and stasis_message_type().

09090 {
09091    if (stasis_message_type(message) != ast_named_acl_change_type()) {
09092       return;
09093    }
09094 
09095    /* For now, this is going to be performed simply and just execute a forced reload. */
09096    ast_log(LOG_NOTICE, "Reloading manager in response to ACL change event.\n");
09097    __init_manager(1, 1);
09098 }

static void acl_change_stasis_subscribe ( void   )  [static]

Definition at line 1412 of file manager.c.

References acl_change_stasis_cb(), acl_change_sub, ast_security_topic(), NULL, and stasis_subscribe().

01413 {
01414    if (!acl_change_sub) {
01415       acl_change_sub = stasis_subscribe(ast_security_topic(),
01416          acl_change_stasis_cb, NULL);
01417    }
01418 }

static void acl_change_stasis_unsubscribe ( void   )  [static]

Definition at line 1420 of file manager.c.

References acl_change_sub, and stasis_unsubscribe_and_join().

static int action_aocmessage ( struct mansession s,
const struct message m 
) [static]

Definition at line 5033 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(), NULL, ast_aoc_unit_entry::type, ast_aoc_unit_entry::valid_amount, and ast_aoc_unit_entry::valid_type.

Referenced by __init_manager().

05034 {
05035    const char *channel = astman_get_header(m, "Channel");
05036    const char *pchannel = astman_get_header(m, "ChannelPrefix");
05037    const char *msgtype = astman_get_header(m, "MsgType");
05038    const char *chargetype = astman_get_header(m, "ChargeType");
05039    const char *currencyname = astman_get_header(m, "CurrencyName");
05040    const char *currencyamount = astman_get_header(m, "CurrencyAmount");
05041    const char *mult = astman_get_header(m, "CurrencyMultiplier");
05042    const char *totaltype = astman_get_header(m, "TotalType");
05043    const char *aocbillingid = astman_get_header(m, "AOCBillingId");
05044    const char *association_id= astman_get_header(m, "ChargingAssociationId");
05045    const char *association_num = astman_get_header(m, "ChargingAssociationNumber");
05046    const char *association_plan = astman_get_header(m, "ChargingAssociationPlan");
05047 
05048    enum ast_aoc_type _msgtype;
05049    enum ast_aoc_charge_type _chargetype;
05050    enum ast_aoc_currency_multiplier _mult = AST_AOC_MULT_ONE;
05051    enum ast_aoc_total_type _totaltype = AST_AOC_TOTAL;
05052    enum ast_aoc_billing_id _billingid = AST_AOC_BILLING_NA;
05053    unsigned int _currencyamount = 0;
05054    int _association_id = 0;
05055    unsigned int _association_plan = 0;
05056    struct ast_channel *chan = NULL;
05057 
05058    struct ast_aoc_decoded *decoded = NULL;
05059    struct ast_aoc_encoded *encoded = NULL;
05060    size_t encoded_size = 0;
05061 
05062    if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) {
05063       astman_send_error(s, m, "Channel and PartialChannel are not specified. Specify at least one of these.");
05064       goto aocmessage_cleanup;
05065    }
05066 
05067    if (!(chan = ast_channel_get_by_name(channel)) && !ast_strlen_zero(pchannel)) {
05068       chan = ast_channel_get_by_name_prefix(pchannel, strlen(pchannel));
05069    }
05070 
05071    if (!chan) {
05072       astman_send_error(s, m, "No such channel");
05073       goto aocmessage_cleanup;
05074    }
05075 
05076    if (ast_strlen_zero(msgtype) || (strcasecmp(msgtype, "d") && strcasecmp(msgtype, "e"))) {
05077       astman_send_error(s, m, "Invalid MsgType");
05078       goto aocmessage_cleanup;
05079    }
05080 
05081    if (ast_strlen_zero(chargetype)) {
05082       astman_send_error(s, m, "ChargeType not specified");
05083       goto aocmessage_cleanup;
05084    }
05085 
05086    _msgtype = strcasecmp(msgtype, "d") ? AST_AOC_E : AST_AOC_D;
05087 
05088    if (!strcasecmp(chargetype, "NA")) {
05089       _chargetype = AST_AOC_CHARGE_NA;
05090    } else if (!strcasecmp(chargetype, "Free")) {
05091       _chargetype = AST_AOC_CHARGE_FREE;
05092    } else if (!strcasecmp(chargetype, "Currency")) {
05093       _chargetype = AST_AOC_CHARGE_CURRENCY;
05094    } else if (!strcasecmp(chargetype, "Unit")) {
05095       _chargetype = AST_AOC_CHARGE_UNIT;
05096    } else {
05097       astman_send_error(s, m, "Invalid ChargeType");
05098       goto aocmessage_cleanup;
05099    }
05100 
05101    if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
05102 
05103       if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u", &_currencyamount) != 1)) {
05104          astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency");
05105          goto aocmessage_cleanup;
05106       }
05107 
05108       if (ast_strlen_zero(mult)) {
05109          astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency.");
05110          goto aocmessage_cleanup;
05111       } else if (!strcasecmp(mult, "onethousandth")) {
05112          _mult = AST_AOC_MULT_ONETHOUSANDTH;
05113       } else if (!strcasecmp(mult, "onehundredth")) {
05114          _mult = AST_AOC_MULT_ONEHUNDREDTH;
05115       } else if (!strcasecmp(mult, "onetenth")) {
05116          _mult = AST_AOC_MULT_ONETENTH;
05117       } else if (!strcasecmp(mult, "one")) {
05118          _mult = AST_AOC_MULT_ONE;
05119       } else if (!strcasecmp(mult, "ten")) {
05120          _mult = AST_AOC_MULT_TEN;
05121       } else if (!strcasecmp(mult, "hundred")) {
05122          _mult = AST_AOC_MULT_HUNDRED;
05123       } else if (!strcasecmp(mult, "thousand")) {
05124          _mult = AST_AOC_MULT_THOUSAND;
05125       } else {
05126          astman_send_error(s, m, "Invalid ChargeMultiplier");
05127          goto aocmessage_cleanup;
05128       }
05129    }
05130 
05131    /* create decoded object and start setting values */
05132    if (!(decoded = ast_aoc_create(_msgtype, _chargetype, 0))) {
05133          astman_send_error(s, m, "Message Creation Failed");
05134          goto aocmessage_cleanup;
05135    }
05136 
05137    if (_msgtype == AST_AOC_D) {
05138       if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype, "subtotal")) {
05139          _totaltype = AST_AOC_SUBTOTAL;
05140       }
05141 
05142       if (ast_strlen_zero(aocbillingid)) {
05143          /* ignore this is optional */
05144       } else if (!strcasecmp(aocbillingid, "Normal")) {
05145          _billingid = AST_AOC_BILLING_NORMAL;
05146       } else if (!strcasecmp(aocbillingid, "ReverseCharge")) {
05147          _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
05148       } else if (!strcasecmp(aocbillingid, "CreditCard")) {
05149          _billingid = AST_AOC_BILLING_CREDIT_CARD;
05150       } else {
05151          astman_send_error(s, m, "Invalid AOC-D AOCBillingId");
05152          goto aocmessage_cleanup;
05153       }
05154    } else {
05155       if (ast_strlen_zero(aocbillingid)) {
05156          /* ignore this is optional */
05157       } else if (!strcasecmp(aocbillingid, "Normal")) {
05158          _billingid = AST_AOC_BILLING_NORMAL;
05159       } else if (!strcasecmp(aocbillingid, "ReverseCharge")) {
05160          _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
05161       } else if (!strcasecmp(aocbillingid, "CreditCard")) {
05162          _billingid = AST_AOC_BILLING_CREDIT_CARD;
05163       } else if (!strcasecmp(aocbillingid, "CallFwdUnconditional")) {
05164          _billingid = AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL;
05165       } else if (!strcasecmp(aocbillingid, "CallFwdBusy")) {
05166          _billingid = AST_AOC_BILLING_CALL_FWD_BUSY;
05167       } else if (!strcasecmp(aocbillingid, "CallFwdNoReply")) {
05168          _billingid = AST_AOC_BILLING_CALL_FWD_NO_REPLY;
05169       } else if (!strcasecmp(aocbillingid, "CallDeflection")) {
05170          _billingid = AST_AOC_BILLING_CALL_DEFLECTION;
05171       } else if (!strcasecmp(aocbillingid, "CallTransfer")) {
05172          _billingid = AST_AOC_BILLING_CALL_TRANSFER;
05173       } else {
05174          astman_send_error(s, m, "Invalid AOC-E AOCBillingId");
05175          goto aocmessage_cleanup;
05176       }
05177 
05178       if (!ast_strlen_zero(association_id) && (sscanf(association_id, "%30d", &_association_id) != 1)) {
05179          astman_send_error(s, m, "Invalid ChargingAssociationId");
05180          goto aocmessage_cleanup;
05181       }
05182       if (!ast_strlen_zero(association_plan) && (sscanf(association_plan, "%30u", &_association_plan) != 1)) {
05183          astman_send_error(s, m, "Invalid ChargingAssociationPlan");
05184          goto aocmessage_cleanup;
05185       }
05186 
05187       if (_association_id) {
05188          ast_aoc_set_association_id(decoded, _association_id);
05189       } else if (!ast_strlen_zero(association_num)) {
05190          ast_aoc_set_association_number(decoded, association_num, _association_plan);
05191       }
05192    }
05193 
05194    if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
05195       ast_aoc_set_currency_info(decoded, _currencyamount, _mult, ast_strlen_zero(currencyname) ? NULL : currencyname);
05196    } else if (_chargetype == AST_AOC_CHARGE_UNIT) {
05197       struct ast_aoc_unit_entry entry;
05198       int i;
05199 
05200       /* multiple unit entries are possible, lets get them all */
05201       for (i = 0; i < 32; i++) {
05202          if (aocmessage_get_unit_entry(m, &entry, i)) {
05203             break; /* that's the end then */
05204          }
05205 
05206          ast_aoc_add_unit_entry(decoded, entry.valid_amount, entry.amount, entry.valid_type, entry.type);
05207       }
05208 
05209       /* at least one unit entry is required */
05210       if (!i) {
05211          astman_send_error(s, m, "Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit");
05212          goto aocmessage_cleanup;
05213       }
05214 
05215    }
05216 
05217    ast_aoc_set_billing_id(decoded, _billingid);
05218    ast_aoc_set_total_type(decoded, _totaltype);
05219 
05220 
05221    if ((encoded = ast_aoc_encode(decoded, &encoded_size, NULL)) && !ast_indicate_data(chan, AST_CONTROL_AOC, encoded, encoded_size)) {
05222       astman_send_ack(s, m, "AOC Message successfully queued on channel");
05223    } else {
05224       astman_send_error(s, m, "Error encoding AOC message, could not queue onto channel");
05225    }
05226 
05227 aocmessage_cleanup:
05228 
05229    ast_aoc_destroy_decoded(decoded);
05230    ast_aoc_destroy_encoded(encoded);
05231 
05232    if (chan) {
05233       chan = ast_channel_unref(chan);
05234    }
05235    return 0;
05236 }

static int action_atxfer ( struct mansession s,
const struct message m 
) [static]

Definition at line 4749 of file manager.c.

References ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, AST_FEATURE_MAX_LEN, AST_FRAME_DTMF, ast_get_builtin_feature(), ast_queue_frame(), ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), context, digit, exten, f, name, NULL, and pbx_builtin_setvar_helper().

Referenced by __init_manager().

04750 {
04751    const char *name = astman_get_header(m, "Channel");
04752    const char *exten = astman_get_header(m, "Exten");
04753    const char *context = astman_get_header(m, "Context");
04754    struct ast_channel *chan = NULL;
04755    char feature_code[AST_FEATURE_MAX_LEN];
04756    const char *digit;
04757 
04758    if (ast_strlen_zero(name)) {
04759       astman_send_error(s, m, "No channel specified");
04760       return 0;
04761    }
04762    if (ast_strlen_zero(exten)) {
04763       astman_send_error(s, m, "No extension specified");
04764       return 0;
04765    }
04766 
04767    if (!(chan = ast_channel_get_by_name(name))) {
04768       astman_send_error(s, m, "Channel specified does not exist");
04769       return 0;
04770    }
04771 
04772    ast_channel_lock(chan);
04773    if (ast_get_builtin_feature(chan, "atxfer", feature_code, sizeof(feature_code)) ||
04774          ast_strlen_zero(feature_code)) {
04775       ast_channel_unlock(chan);
04776       astman_send_error(s, m, "No attended transfer feature code found");
04777       ast_channel_unref(chan);
04778       return 0;
04779    }
04780    ast_channel_unlock(chan);
04781 
04782    if (!ast_strlen_zero(context)) {
04783       pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context);
04784    }
04785 
04786    for (digit = feature_code; *digit; ++digit) {
04787       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *digit };
04788       ast_queue_frame(chan, &f);
04789    }
04790 
04791    for (digit = exten; *digit; ++digit) {
04792       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *digit };
04793       ast_queue_frame(chan, &f);
04794    }
04795 
04796    chan = ast_channel_unref(chan);
04797 
04798    astman_send_ack(s, m, "Atxfer successfully queued");
04799 
04800    return 0;
04801 }

static int action_blind_transfer ( struct mansession s,
const struct message m 
) [static]

Definition at line 4704 of file manager.c.

References ao2_cleanup, ast_bridge_transfer_blind(), AST_BRIDGE_TRANSFER_FAIL, AST_BRIDGE_TRANSFER_INVALID, AST_BRIDGE_TRANSFER_NOT_PERMITTED, AST_BRIDGE_TRANSFER_SUCCESS, ast_channel_context(), ast_channel_get_by_name(), ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), context, exten, name, NULL, and RAII_VAR.

Referenced by __init_manager().

04705 {
04706    const char *name = astman_get_header(m, "Channel");
04707    const char *exten = astman_get_header(m, "Exten");
04708    const char *context = astman_get_header(m, "Context");
04709    RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
04710 
04711    if (ast_strlen_zero(name)) {
04712       astman_send_error(s, m, "No channel specified");
04713       return 0;
04714    }
04715 
04716    if (ast_strlen_zero(exten)) {
04717       astman_send_error(s, m, "No extension specified");
04718       return 0;
04719    }
04720 
04721    chan = ast_channel_get_by_name(name);
04722    if (!chan) {
04723       astman_send_error(s, m, "Channel specified does not exist");
04724       return 0;
04725    }
04726 
04727    if (ast_strlen_zero(context)) {
04728       context = ast_channel_context(chan);
04729    }
04730 
04731    switch (ast_bridge_transfer_blind(1, chan, exten, context, NULL, NULL)) {
04732    case AST_BRIDGE_TRANSFER_NOT_PERMITTED:
04733       astman_send_error(s, m, "Transfer not permitted");
04734       break;
04735    case AST_BRIDGE_TRANSFER_INVALID:
04736       astman_send_error(s, m, "Transfer invalid");
04737       break;
04738    case AST_BRIDGE_TRANSFER_FAIL:
04739       astman_send_error(s, m, "Transfer failed");
04740       break;
04741    case AST_BRIDGE_TRANSFER_SUCCESS:
04742       astman_send_ack(s, m, "Transfer succeeded");
04743       break;
04744    }
04745 
04746    return 0;
04747 }

static int action_challenge ( struct mansession s,
const struct message m 
) [static]

Definition at line 4109 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().

04110 {
04111    const char *authtype = astman_get_header(m, "AuthType");
04112 
04113    if (!strcasecmp(authtype, "MD5")) {
04114       if (ast_strlen_zero(s->session->challenge)) {
04115          snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
04116       }
04117       mansession_lock(s);
04118       astman_start_ack(s, m);
04119       astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
04120       mansession_unlock(s);
04121    } else {
04122       astman_send_error(s, m, "Must specify AuthType");
04123    }
04124    return 0;
04125 }

static int action_command ( struct mansession s,
const struct message m 
) [static]

Manager command "command" - execute CLI command.

Definition at line 4839 of file manager.c.

References ast_cli_command, ast_free, ast_log, AST_LOG_WARNING, ast_malloc, ast_strlen_zero, astman_append(), astman_get_header(), astman_send_error(), buf, check_blacklist(), errno, LOG_WARNING, NULL, and term_strip().

Referenced by __init_manager().

04840 {
04841    const char *cmd = astman_get_header(m, "Command");
04842    const char *id = astman_get_header(m, "ActionID");
04843    char *buf = NULL, *final_buf = NULL;
04844    char template[] = "/tmp/ast-ami-XXXXXX";  /* template for temporary file */
04845    int fd;
04846    off_t l;
04847 
04848    if (ast_strlen_zero(cmd)) {
04849       astman_send_error(s, m, "No command provided");
04850       return 0;
04851    }
04852 
04853    if (check_blacklist(cmd)) {
04854       astman_send_error(s, m, "Command blacklisted");
04855       return 0;
04856    }
04857 
04858    if ((fd = mkstemp(template)) < 0) {
04859       ast_log(AST_LOG_WARNING, "Failed to create temporary file for command: %s\n", strerror(errno));
04860       astman_send_error(s, m, "Command response construction error");
04861       return 0;
04862    }
04863 
04864    astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
04865    if (!ast_strlen_zero(id)) {
04866       astman_append(s, "ActionID: %s\r\n", id);
04867    }
04868    /* FIXME: Wedge a ActionID response in here, waiting for later changes */
04869    ast_cli_command(fd, cmd);  /* XXX need to change this to use a FILE * */
04870    /* Determine number of characters available */
04871    if ((l = lseek(fd, 0, SEEK_END)) < 0) {
04872       ast_log(LOG_WARNING, "Failed to determine number of characters for command: %s\n", strerror(errno));
04873       goto action_command_cleanup;
04874    }
04875 
04876    /* This has a potential to overflow the stack.  Hence, use the heap. */
04877    buf = ast_malloc(l + 1);
04878    final_buf = ast_malloc(l + 1);
04879 
04880    if (!buf || !final_buf) {
04881       ast_log(LOG_WARNING, "Failed to allocate memory for temporary buffer\n");
04882       goto action_command_cleanup;
04883    }
04884 
04885    if (lseek(fd, 0, SEEK_SET) < 0) {
04886       ast_log(LOG_WARNING, "Failed to set position on temporary file for command: %s\n", strerror(errno));
04887       goto action_command_cleanup;
04888    }
04889 
04890    if (read(fd, buf, l) < 0) {
04891       ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
04892       goto action_command_cleanup;
04893    }
04894 
04895    buf[l] = '\0';
04896    term_strip(final_buf, buf, l);
04897    final_buf[l] = '\0';
04898    astman_append(s, "%s", final_buf);
04899 
04900 action_command_cleanup:
04901 
04902    close(fd);
04903    unlink(template);
04904    astman_append(s, "--END COMMAND--\r\n\r\n");
04905 
04906    ast_free(buf);
04907    ast_free(final_buf);
04908 
04909    return 0;
04910 }

static int action_coresettings ( struct mansession s,
const struct message m 
) [static]

Show PBX core settings information.

Definition at line 5778 of file manager.c.

References AMI_VERSION, ast_cdr_is_enabled(), AST_CLI_YESNO, ast_config_AST_RUN_GROUP, ast_config_AST_RUN_USER, ast_config_AST_SYSTEM_NAME, ast_get_version(), ast_option_maxcalls, ast_option_maxfiles, ast_option_maxload, ast_realtime_enabled(), ast_strlen_zero, astman_append(), astman_get_header(), and check_webmanager_enabled().

Referenced by __init_manager().

05779 {
05780    const char *actionid = astman_get_header(m, "ActionID");
05781    char idText[150];
05782 
05783    if (!ast_strlen_zero(actionid)) {
05784       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
05785    } else {
05786       idText[0] = '\0';
05787    }
05788 
05789    astman_append(s, "Response: Success\r\n"
05790          "%s"
05791          "AMIversion: %s\r\n"
05792          "AsteriskVersion: %s\r\n"
05793          "SystemName: %s\r\n"
05794          "CoreMaxCalls: %d\r\n"
05795          "CoreMaxLoadAvg: %f\r\n"
05796          "CoreRunUser: %s\r\n"
05797          "CoreRunGroup: %s\r\n"
05798          "CoreMaxFilehandles: %d\r\n"
05799          "CoreRealTimeEnabled: %s\r\n"
05800          "CoreCDRenabled: %s\r\n"
05801          "CoreHTTPenabled: %s\r\n"
05802          "\r\n",
05803          idText,
05804          AMI_VERSION,
05805          ast_get_version(),
05806          ast_config_AST_SYSTEM_NAME,
05807          ast_option_maxcalls,
05808          ast_option_maxload,
05809          ast_config_AST_RUN_USER,
05810          ast_config_AST_RUN_GROUP,
05811          ast_option_maxfiles,
05812          AST_CLI_YESNO(ast_realtime_enabled()),
05813          AST_CLI_YESNO(ast_cdr_is_enabled()),
05814          AST_CLI_YESNO(check_webmanager_enabled())
05815          );
05816    return 0;
05817 }

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 5892 of file manager.c.

References ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_channel_snapshot::appl, ast_channel_cache_by_name(), ast_channel_snapshot_type(), ast_free, ast_manager_build_channel_state_string_prefix(), ast_str_buffer(), ast_strlen_zero, ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), astman_append(), astman_get_header(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), ast_channel_snapshot::bridgeid, channels, ast_channel_snapshot::creationtime, ast_channel_snapshot::data, NULL, RAII_VAR, stasis_cache_dump(), and stasis_message_data().

Referenced by __init_manager().

05893 {
05894    const char *actionid = astman_get_header(m, "ActionID");
05895    char idText[256];
05896    int numchans = 0;
05897    RAII_VAR(struct ao2_container *, channels, NULL, ao2_cleanup);
05898    struct ao2_iterator it_chans;
05899    struct stasis_message *msg;
05900 
05901    if (!ast_strlen_zero(actionid)) {
05902       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
05903    } else {
05904       idText[0] = '\0';
05905    }
05906 
05907    if (!(channels = stasis_cache_dump(ast_channel_cache_by_name(), ast_channel_snapshot_type()))) {
05908       astman_send_error(s, m, "Could not get cached channels");
05909       return 0;
05910    }
05911 
05912    astman_send_listack(s, m, "Channels will follow", "start");
05913 
05914    it_chans = ao2_iterator_init(channels, 0);
05915    for (; (msg = ao2_iterator_next(&it_chans)); ao2_ref(msg, -1)) {
05916       struct ast_channel_snapshot *cs = stasis_message_data(msg);
05917       struct ast_str *built = ast_manager_build_channel_state_string_prefix(cs, "");
05918       char durbuf[10] = "";
05919 
05920       if (!built) {
05921          continue;
05922       }
05923 
05924       if (!ast_tvzero(cs->creationtime)) {
05925          int duration, durh, durm, durs;
05926 
05927          duration = (int)(ast_tvdiff_ms(ast_tvnow(), cs->creationtime) / 1000);
05928          durh = duration / 3600;
05929          durm = (duration % 3600) / 60;
05930          durs = duration % 60;
05931          snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
05932       }
05933 
05934       astman_append(s,
05935          "Event: CoreShowChannel\r\n"
05936          "%s"
05937          "%s"
05938          "Application: %s\r\n"
05939          "ApplicationData: %s\r\n"
05940          "Duration: %s\r\n"
05941          "BridgeId: %s\r\n"
05942          "\r\n",
05943          idText,
05944          ast_str_buffer(built),
05945          cs->appl,
05946          cs->data,
05947          durbuf,
05948          cs->bridgeid);
05949 
05950       numchans++;
05951 
05952       ast_free(built);
05953    }
05954    ao2_iterator_destroy(&it_chans);
05955 
05956    astman_send_list_complete_start(s, m, "CoreShowChannelsComplete", numchans);
05957    astman_send_list_complete_end(s);
05958 
05959    return 0;
05960 }

static int action_corestatus ( struct mansession s,
const struct message m 
) [static]

Show PBX core status information.

Definition at line 5820 of file manager.c.

References ast_active_channels(), ast_lastreloadtime, ast_localtime(), ast_startuptime, ast_strftime(), ast_strlen_zero, astman_append(), astman_get_header(), and NULL.

Referenced by __init_manager().

05821 {
05822    const char *actionid = astman_get_header(m, "ActionID");
05823    char idText[150];
05824    char startuptime[150], startupdate[150];
05825    char reloadtime[150], reloaddate[150];
05826    struct ast_tm tm;
05827 
05828    if (!ast_strlen_zero(actionid)) {
05829       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
05830    } else {
05831       idText[0] = '\0';
05832    }
05833 
05834    ast_localtime(&ast_startuptime, &tm, NULL);
05835    ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm);
05836    ast_strftime(startupdate, sizeof(startupdate), "%Y-%m-%d", &tm);
05837    ast_localtime(&ast_lastreloadtime, &tm, NULL);
05838    ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm);
05839    ast_strftime(reloaddate, sizeof(reloaddate), "%Y-%m-%d", &tm);
05840 
05841    astman_append(s, "Response: Success\r\n"
05842          "%s"
05843          "CoreStartupDate: %s\r\n"
05844          "CoreStartupTime: %s\r\n"
05845          "CoreReloadDate: %s\r\n"
05846          "CoreReloadTime: %s\r\n"
05847          "CoreCurrentCalls: %d\r\n"
05848          "\r\n",
05849          idText,
05850          startupdate,
05851          startuptime,
05852          reloaddate,
05853          reloadtime,
05854          ast_active_channels()
05855          );
05856    return 0;
05857 }

static int action_createconfig ( struct mansession s,
const struct message m 
) [static]

Definition at line 3882 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().

03883 {
03884    int fd;
03885    const char *fn = astman_get_header(m, "Filename");
03886    struct ast_str *filepath = ast_str_alloca(PATH_MAX);
03887    ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR);
03888    ast_str_append(&filepath, 0, "%s", fn);
03889 
03890    if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
03891       close(fd);
03892       astman_send_ack(s, m, "New configuration file created successfully");
03893    } else {
03894       astman_send_error(s, m, strerror(errno));
03895    }
03896 
03897    return 0;
03898 }

static void action_destroy ( void *  obj  )  [static]

Definition at line 6812 of file manager.c.

References ao2_cleanup, ast_string_field_free_memory, manager_action::final_response, manager_action::list_responses, and manager_action::synopsis.

Referenced by ast_manager_register2().

06813 {
06814    struct manager_action *doomed = obj;
06815 
06816    if (doomed->synopsis) {
06817       /* The string fields were initialized. */
06818       ast_string_field_free_memory(doomed);
06819    }
06820    ao2_cleanup(doomed->final_response);
06821    ao2_cleanup(doomed->list_responses);
06822 }

static int action_events ( struct mansession s,
const struct message m 
) [static]

Definition at line 4026 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().

04027 {
04028    const char *mask = astman_get_header(m, "EventMask");
04029    int res, x;
04030    const char *id = astman_get_header(m, "ActionID");
04031    char id_text[256];
04032 
04033    if (!ast_strlen_zero(id)) {
04034       snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
04035    } else {
04036       id_text[0] = '\0';
04037    }
04038 
04039    res = set_eventmask(s, mask);
04040    if (broken_events_action) {
04041       /* if this option is set we should not return a response on
04042        * error, or when all events are set */
04043 
04044       if (res > 0) {
04045          for (x = 0; x < ARRAY_LEN(perms); x++) {
04046             if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) {
04047                return 0;
04048             }
04049          }
04050          astman_append(s, "Response: Success\r\n%s"
04051                 "Events: On\r\n\r\n", id_text);
04052       } else if (res == 0)
04053          astman_append(s, "Response: Success\r\n%s"
04054                 "Events: Off\r\n\r\n", id_text);
04055       return 0;
04056    }
04057 
04058    if (res > 0)
04059       astman_append(s, "Response: Success\r\n%s"
04060              "Events: On\r\n\r\n", id_text);
04061    else if (res == 0)
04062       astman_append(s, "Response: Success\r\n%s"
04063              "Events: Off\r\n\r\n", id_text);
04064    else
04065       astman_send_error(s, m, "Invalid event mask");
04066 
04067    return 0;
04068 }

static int action_extensionstate ( struct mansession s,
const struct message m 
) [static]

Definition at line 5483 of file manager.c.

References ast_extension_state(), ast_extension_state2str(), ast_get_hint(), ast_strlen_zero, astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), context, exten, NULL, and status.

Referenced by __init_manager().

05484 {
05485    const char *exten = astman_get_header(m, "Exten");
05486    const char *context = astman_get_header(m, "Context");
05487    char hint[256] = "";
05488    int status;
05489    if (ast_strlen_zero(exten)) {
05490       astman_send_error(s, m, "Extension not specified");
05491       return 0;
05492    }
05493    if (ast_strlen_zero(context)) {
05494       context = "default";
05495    }
05496    status = ast_extension_state(NULL, context, exten);
05497    ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
05498    astman_start_ack(s, m);
05499    astman_append(s,   "Message: Extension Status\r\n"
05500             "Exten: %s\r\n"
05501             "Context: %s\r\n"
05502             "Hint: %s\r\n"
05503             "Status: %d\r\n"
05504                  "StatusText: %s\r\n\r\n",
05505             exten, context, hint, status,
05506             ast_extension_state2str(status));
05507    return 0;
05508 }

static int action_filter ( struct mansession s,
const struct message m 
) [static]

Manager command to add an event filter to a manager session.

See also:
For more details look at manager_add_filter

Definition at line 5617 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().

05618 {
05619    const char *filter = astman_get_header(m, "Filter");
05620    const char *operation = astman_get_header(m, "Operation");
05621    int res;
05622 
05623    if (!strcasecmp(operation, "Add")) {
05624       res = manager_add_filter(filter, s->session->whitefilters, s->session->blackfilters);
05625 
05626            if (res != FILTER_SUCCESS) {
05627               if (res == FILTER_ALLOC_FAILED) {
05628             astman_send_error(s, m, "Internal Error. Failed to allocate regex for filter");
05629                       return 0;
05630               } else if (res == FILTER_COMPILE_FAIL) {
05631             astman_send_error(s, m, "Filter did not compile.  Check the syntax of the filter given.");
05632                       return 0;
05633               } else {
05634             astman_send_error(s, m, "Internal Error. Failed adding filter.");
05635                       return 0;
05636                    }
05637       }
05638 
05639       astman_send_ack(s, m, "Success");
05640       return 0;
05641    }
05642 
05643    astman_send_error(s, m, "Unknown operation");
05644    return 0;
05645 }

static struct manager_action* action_find ( const char *  name  )  [static, read]

Definition at line 1568 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().

01569 {
01570    struct manager_action *act;
01571 
01572    AST_RWLIST_RDLOCK(&actions);
01573    AST_RWLIST_TRAVERSE(&actions, act, list) {
01574       if (!strcasecmp(name, act->action)) {
01575          ao2_t_ref(act, +1, "found action object");
01576          break;
01577       }
01578    }
01579    AST_RWLIST_UNLOCK(&actions);
01580 
01581    return act;
01582 }

static int action_getconfig ( struct mansession s,
const struct message m 
) [static]

Definition at line 3316 of file manager.c.

References ast_category_browse_filtered(), ast_category_first(), ast_category_get_name(), ast_category_get_templates(), ast_category_is_template(), ast_config_destroy(), ast_config_load2(), ast_free, ast_str_buffer(), ast_str_strlen(), ast_strlen_zero, 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, filter(), ast_variable::name, ast_variable::next, NULL, and ast_variable::value.

Referenced by __init_manager().

03317 {
03318    struct ast_config *cfg;
03319    const char *fn = astman_get_header(m, "Filename");
03320    const char *category = astman_get_header(m, "Category");
03321    const char *filter = astman_get_header(m, "Filter");
03322    const char *category_name;
03323    int catcount = 0;
03324    int lineno = 0;
03325    struct ast_category *cur_category = NULL;
03326    struct ast_variable *v;
03327    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
03328 
03329    if (ast_strlen_zero(fn)) {
03330       astman_send_error(s, m, "Filename not specified");
03331       return 0;
03332    }
03333 
03334    cfg = ast_config_load2(fn, "manager", config_flags);
03335    if (cfg == CONFIG_STATUS_FILEMISSING) {
03336       astman_send_error(s, m, "Config file not found");
03337       return 0;
03338    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
03339       astman_send_error(s, m, "Config file has invalid format");
03340       return 0;
03341    }
03342 
03343    astman_start_ack(s, m);
03344    while ((cur_category = ast_category_browse_filtered(cfg, category, cur_category, filter))) {
03345       struct ast_str *templates;
03346 
03347       category_name = ast_category_get_name(cur_category);
03348       lineno = 0;
03349       astman_append(s, "Category-%06d: %s\r\n", catcount, category_name);
03350 
03351       if (ast_category_is_template(cur_category)) {
03352          astman_append(s, "IsTemplate-%06d: %d\r\n", catcount, 1);
03353       }
03354 
03355       if ((templates = ast_category_get_templates(cur_category))
03356          && ast_str_strlen(templates) > 0) {
03357          astman_append(s, "Templates-%06d: %s\r\n", catcount, ast_str_buffer(templates));
03358          ast_free(templates);
03359       }
03360 
03361       for (v = ast_category_first(cur_category); v; v = v->next) {
03362          astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value);
03363       }
03364 
03365       catcount++;
03366    }
03367 
03368    if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
03369       astman_append(s, "No categories found\r\n");
03370    }
03371 
03372    ast_config_destroy(cfg);
03373    astman_append(s, "\r\n");
03374 
03375    return 0;
03376 }

static int action_getconfigjson ( struct mansession s,
const struct message m 
) [static]

Definition at line 3446 of file manager.c.

References ast_category_browse_filtered(), ast_category_first(), ast_category_get_name(), ast_category_get_templates(), ast_category_is_template(), ast_config_destroy(), ast_config_load2(), ast_free, ast_str_buffer(), ast_str_strlen(), ast_strlen_zero, 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, filter(), ast_variable::name, ast_variable::next, NULL, and ast_variable::value.

Referenced by __init_manager().

03447 {
03448    struct ast_config *cfg;
03449    const char *fn = astman_get_header(m, "Filename");
03450    const char *filter = astman_get_header(m, "Filter");
03451    const char *category = astman_get_header(m, "Category");
03452    struct ast_category *cur_category = NULL;
03453    const char *category_name;
03454    struct ast_variable *v;
03455    int comma1 = 0;
03456    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
03457 
03458    if (ast_strlen_zero(fn)) {
03459       astman_send_error(s, m, "Filename not specified");
03460       return 0;
03461    }
03462 
03463    if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
03464       astman_send_error(s, m, "Config file not found");
03465       return 0;
03466    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
03467       astman_send_error(s, m, "Config file has invalid format");
03468       return 0;
03469    }
03470 
03471    astman_start_ack(s, m);
03472    astman_append(s, "JSON: {");
03473    while ((cur_category = ast_category_browse_filtered(cfg, category, cur_category, filter))) {
03474       int comma2 = 0;
03475       struct ast_str *templates;
03476 
03477       category_name = ast_category_get_name(cur_category);
03478       astman_append(s, "%s\"", comma1 ? "," : "");
03479       astman_append_json(s, category_name);
03480       astman_append(s, "\":[");
03481       comma1 = 1;
03482 
03483       if (ast_category_is_template(cur_category)) {
03484          astman_append(s, "istemplate:1");
03485          comma2 = 1;
03486       }
03487 
03488       if ((templates = ast_category_get_templates(cur_category))
03489          && ast_str_strlen(templates) > 0) {
03490          astman_append(s, "%s", comma2 ? "," : "");
03491          astman_append(s, "templates:\"%s\"", ast_str_buffer(templates));
03492          ast_free(templates);
03493          comma2 = 1;
03494       }
03495 
03496       for (v = ast_category_first(cur_category); v; v = v->next) {
03497          astman_append(s, "%s\"", comma2 ? "," : "");
03498          astman_append_json(s, v->name);
03499          astman_append(s, "\":\"");
03500          astman_append_json(s, v->value);
03501          astman_append(s, "\"");
03502          comma2 = 1;
03503       }
03504 
03505       astman_append(s, "]");
03506    }
03507    astman_append(s, "}\r\n\r\n");
03508 
03509    ast_config_destroy(cfg);
03510 
03511    return 0;
03512 }

static int action_getvar ( struct mansession s,
const struct message m 
) [static]

Definition at line 4278 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(), c, function_capable_string_allowed_with_auths(), LOG_ERROR, name, NULL, pbx_retrieve_variable(), S_OR, mansession::session, and mansession_session::writeperm.

Referenced by __init_manager().

04279 {
04280    struct ast_channel *c = NULL;
04281    const char *name = astman_get_header(m, "Channel");
04282    const char *varname = astman_get_header(m, "Variable");
04283    char *varval;
04284    char workspace[1024];
04285 
04286    if (ast_strlen_zero(varname)) {
04287       astman_send_error(s, m, "No variable specified");
04288       return 0;
04289    }
04290 
04291    /* We don't want users with insufficient permissions using certain functions. */
04292    if (!(function_capable_string_allowed_with_auths(varname, s->session->writeperm))) {
04293       astman_send_error(s, m, "GetVar Access Forbidden: Variable");
04294       return 0;
04295    }
04296 
04297    if (!ast_strlen_zero(name)) {
04298       if (!(c = ast_channel_get_by_name(name))) {
04299          astman_send_error(s, m, "No such channel");
04300          return 0;
04301       }
04302    }
04303 
04304    workspace[0] = '\0';
04305    if (varname[strlen(varname) - 1] == ')') {
04306       if (!c) {
04307          c = ast_dummy_channel_alloc();
04308          if (c) {
04309             ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
04310          } else
04311             ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04312       } else {
04313          ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
04314       }
04315       varval = workspace;
04316    } else {
04317       pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
04318    }
04319 
04320    if (c) {
04321       c = ast_channel_unref(c);
04322    }
04323 
04324    astman_start_ack(s, m);
04325    astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, S_OR(varval, ""));
04326 
04327    return 0;
04328 }

static int action_hangup ( struct mansession s,
const struct message m 
) [static]

Definition at line 4127 of file manager.c.

References mansession_session::addr, ast_channel_get_by_name(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_name(), ast_channel_softhangup_withcause_locked(), ast_channel_unref, ast_free, ast_log, ast_regex_string_to_regex_pattern(), ast_sockaddr_stringify_addr(), ast_str_buffer(), ast_str_create(), ast_strlen_zero, ast_verb, astman_append(), astman_get_header(), astman_send_ack(), astman_send_error(), astman_send_error_va(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), c, LOG_NOTICE, mansession_session::managerid, NULL, mansession::session, and mansession_session::username.

Referenced by __init_manager().

04128 {
04129    struct ast_channel *c = NULL;
04130    int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */
04131    const char *id = astman_get_header(m, "ActionID");
04132    const char *name_or_regex = astman_get_header(m, "Channel");
04133    const char *cause = astman_get_header(m, "Cause");
04134    char idText[256];
04135    regex_t regexbuf;
04136    struct ast_channel_iterator *iter = NULL;
04137    struct ast_str *regex_string;
04138    int channels_matched = 0;
04139 
04140    if (ast_strlen_zero(name_or_regex)) {
04141       astman_send_error(s, m, "No channel specified");
04142       return 0;
04143    }
04144 
04145    if (!ast_strlen_zero(id)) {
04146       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
04147    } else {
04148       idText[0] = '\0';
04149    }
04150 
04151    if (!ast_strlen_zero(cause)) {
04152       char *endptr;
04153       causecode = strtol(cause, &endptr, 10);
04154       if (causecode < 0 || causecode > 127 || *endptr != '\0') {
04155          ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause);
04156          /* keep going, better to hangup without cause than to not hang up at all */
04157          causecode = 0; /* do not set channel's hangupcause */
04158       }
04159    }
04160 
04161    /************************************************/
04162    /* Regular explicit match channel byname hangup */
04163 
04164    if (name_or_regex[0] != '/') {
04165       if (!(c = ast_channel_get_by_name(name_or_regex))) {
04166          ast_log(LOG_NOTICE, "Request to hangup non-existent channel: %s\n",
04167             name_or_regex);
04168          astman_send_error(s, m, "No such channel");
04169          return 0;
04170       }
04171 
04172       ast_verb(3, "%sManager '%s' from %s, hanging up channel: %s\n",
04173          (s->session->managerid ? "HTTP " : ""),
04174          s->session->username,
04175          ast_sockaddr_stringify_addr(&s->session->addr),
04176          ast_channel_name(c));
04177 
04178       ast_channel_softhangup_withcause_locked(c, causecode);
04179       c = ast_channel_unref(c);
04180 
04181       astman_send_ack(s, m, "Channel Hungup");
04182 
04183       return 0;
04184    }
04185 
04186    /***********************************************/
04187    /* find and hangup any channels matching regex */
04188 
04189    regex_string = ast_str_create(strlen(name_or_regex));
04190    if (!regex_string) {
04191       astman_send_error(s, m, "Memory Allocation Failure");
04192       return 0;
04193    }
04194 
04195    /* Make "/regex/" into "regex" */
04196    if (ast_regex_string_to_regex_pattern(name_or_regex, &regex_string) != 0) {
04197       astman_send_error(s, m, "Regex format invalid, Channel param should be /regex/");
04198       ast_free(regex_string);
04199       return 0;
04200    }
04201 
04202    /* if regex compilation fails, hangup fails */
04203    if (regcomp(&regexbuf, ast_str_buffer(regex_string), REG_EXTENDED | REG_NOSUB)) {
04204       astman_send_error_va(s, m, "Regex compile failed on: %s", name_or_regex);
04205       ast_free(regex_string);
04206       return 0;
04207    }
04208 
04209    astman_send_listack(s, m, "Channels hung up will follow", "start");
04210 
04211    iter = ast_channel_iterator_all_new();
04212    if (iter) {
04213       for (; (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) {
04214          if (regexec(&regexbuf, ast_channel_name(c), 0, NULL, 0)) {
04215             continue;
04216          }
04217 
04218          ast_verb(3, "%sManager '%s' from %s, hanging up channel: %s\n",
04219             (s->session->managerid ? "HTTP " : ""),
04220             s->session->username,
04221             ast_sockaddr_stringify_addr(&s->session->addr),
04222             ast_channel_name(c));
04223 
04224          ast_channel_softhangup_withcause_locked(c, causecode);
04225          channels_matched++;
04226 
04227          astman_append(s,
04228             "Event: ChannelHungup\r\n"
04229             "Channel: %s\r\n"
04230             "%s"
04231             "\r\n", ast_channel_name(c), idText);
04232       }
04233       ast_channel_iterator_destroy(iter);
04234    }
04235 
04236    regfree(&regexbuf);
04237    ast_free(regex_string);
04238 
04239    astman_send_list_complete_start(s, m, "ChannelsHungupListComplete", channels_matched);
04240    astman_send_list_complete_end(s);
04241 
04242    return 0;
04243 }

static int action_listcategories ( struct mansession s,
const struct message m 
) [static]

Definition at line 3378 of file manager.c.

References ast_category_browse_filtered(), ast_category_get_name(), 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, CONFIG_STATUS_FILEINVALID, match(), and NULL.

Referenced by __init_manager().

03379 {
03380    struct ast_config *cfg;
03381    const char *fn = astman_get_header(m, "Filename");
03382    const char *match = astman_get_header(m, "Match");
03383    struct ast_category *category = NULL;
03384    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
03385    int catcount = 0;
03386 
03387    if (ast_strlen_zero(fn)) {
03388       astman_send_error(s, m, "Filename not specified");
03389       return 0;
03390    }
03391 
03392    if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
03393       astman_send_error(s, m, "Config file not found");
03394       return 0;
03395    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
03396       astman_send_error(s, m, "Config file has invalid format");
03397       return 0;
03398    }
03399 
03400    astman_start_ack(s, m);
03401    while ((category = ast_category_browse_filtered(cfg, NULL, category, match))) {
03402       astman_append(s, "Category-%06d: %s\r\n", catcount, ast_category_get_name(category));
03403       catcount++;
03404    }
03405 
03406    if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
03407       astman_append(s, "Error: no categories found\r\n");
03408    }
03409 
03410    ast_config_destroy(cfg);
03411    astman_append(s, "\r\n");
03412 
03413    return 0;
03414 }

static int action_listcommands ( struct mansession s,
const struct message m 
) [static]

Definition at line 4007 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(), MAX_AUTH_PERM_STRING, mansession::session, manager_action::synopsis, and mansession_session::writeperm.

Referenced by __init_manager().

04008 {
04009    struct manager_action *cur;
04010    struct ast_str *temp = ast_str_alloca(MAX_AUTH_PERM_STRING);
04011 
04012    astman_start_ack(s, m);
04013    AST_RWLIST_RDLOCK(&actions);
04014    AST_RWLIST_TRAVERSE(&actions, cur, list) {
04015       if ((s->session->writeperm & cur->authority) || cur->authority == 0) {
04016          astman_append(s, "%s: %s (Priv: %s)\r\n",
04017             cur->action, cur->synopsis, authority_to_str(cur->authority, &temp));
04018       }
04019    }
04020    AST_RWLIST_UNLOCK(&actions);
04021    astman_append(s, "\r\n");
04022 
04023    return 0;
04024 }

static int action_loggerrotate ( struct mansession s,
const struct message m 
) [static]

Manager command "LoggerRotate" - reloads and rotates the logger in the same manner as the CLI command 'logger rotate'.

Definition at line 5964 of file manager.c.

References ast_logger_rotate(), astman_send_ack(), and astman_send_error().

Referenced by __init_manager().

05965 {
05966    if (ast_logger_rotate()) {
05967       astman_send_error(s, m, "Failed to reload the logger and rotate log files");
05968       return 0;
05969    }
05970 
05971    astman_send_ack(s, m, "Reloaded the logger and rotated log files");
05972    return 0;
05973 }

static int action_login ( struct mansession s,
const struct message m 
) [static]

Definition at line 4076 of file manager.c.

References mansession_session::addr, ast_atomic_fetchadd_int(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, ast_sockaddr_stringify_addr(), 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, MAX_AUTH_PERM_STRING, mansession_session::readperm, mansession_session::send_events, mansession::session, unauth_sessions, and mansession_session::username.

Referenced by __init_manager().

04077 {
04078 
04079    /* still authenticated - don't process again */
04080    if (s->session->authenticated) {
04081       astman_send_ack(s, m, "Already authenticated");
04082       return 0;
04083    }
04084 
04085    if (authenticate(s, m)) {
04086       sleep(1);
04087       astman_send_error(s, m, "Authentication failed");
04088       return -1;
04089    }
04090    s->session->authenticated = 1;
04091    ast_atomic_fetchadd_int(&unauth_sessions, -1);
04092    if (manager_displayconnects(s->session)) {
04093       ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_sockaddr_stringify_addr(&s->session->addr));
04094    }
04095    astman_send_ack(s, m, "Authentication accepted");
04096    if ((s->session->send_events & EVENT_FLAG_SYSTEM)
04097       && (s->session->readperm & EVENT_FLAG_SYSTEM)
04098       && ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
04099       struct ast_str *auth = ast_str_alloca(MAX_AUTH_PERM_STRING);
04100       const char *cat_str = authority_to_str(EVENT_FLAG_SYSTEM, &auth);
04101 
04102       astman_append(s, "Event: FullyBooted\r\n"
04103          "Privilege: %s\r\n"
04104          "Status: Fully Booted\r\n\r\n", cat_str);
04105    }
04106    return 0;
04107 }

static int action_logoff ( struct mansession s,
const struct message m 
) [static]

Definition at line 4070 of file manager.c.

References astman_send_response().

Referenced by __init_manager().

04071 {
04072    astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
04073    return -1;
04074 }

static int action_mailboxcount ( struct mansession s,
const struct message m 
) [static]

Definition at line 5462 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().

05463 {
05464    const char *mailbox = astman_get_header(m, "Mailbox");
05465    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;;
05466 
05467    if (ast_strlen_zero(mailbox)) {
05468       astman_send_error(s, m, "Mailbox not specified");
05469       return 0;
05470    }
05471    ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs);
05472    astman_start_ack(s, m);
05473    astman_append(s,   "Message: Mailbox Message Count\r\n"
05474             "Mailbox: %s\r\n"
05475             "UrgMessages: %d\r\n"
05476             "NewMessages: %d\r\n"
05477             "OldMessages: %d\r\n"
05478             "\r\n",
05479             mailbox, urgentmsgs, newmsgs, oldmsgs);
05480    return 0;
05481 }

static int action_mailboxstatus ( struct mansession s,
const struct message m 
) [static]

Definition at line 5445 of file manager.c.

References ast_app_has_voicemail(), ast_strlen_zero, astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), mailbox, and NULL.

Referenced by __init_manager().

05446 {
05447    const char *mailbox = astman_get_header(m, "Mailbox");
05448    int ret;
05449 
05450    if (ast_strlen_zero(mailbox)) {
05451       astman_send_error(s, m, "Mailbox not specified");
05452       return 0;
05453    }
05454    ret = ast_app_has_voicemail(mailbox, NULL);
05455    astman_start_ack(s, m);
05456    astman_append(s, "Message: Mailbox Status\r\n"
05457           "Mailbox: %s\r\n"
05458           "Waiting: %d\r\n\r\n", mailbox, ret);
05459    return 0;
05460 }

static int action_originate ( struct mansession s,
const struct message m 
) [static]

Definition at line 5238 of file manager.c.

References ao2_cleanup, app, ast_callerid_parse(), ast_calloc, ast_copy_string(), ast_exists_extension(), ast_findlabel_extension(), ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_remove_by_type(), ast_format_cap_update_by_allow_disallow(), ast_format_slin, ast_free, AST_MAX_PUBLIC_UNIQUEID, AST_MEDIA_TYPE_UNKNOWN, 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(), ast_variables_dup(), astman_get_header(), astman_get_variables(), astman_send_ack(), astman_send_error(), astman_send_error_va(), fast_originate_helper::cap, mansession_session::chanvars, cid_name, cid_num, codecs, context, destroy_fast_originate_helper(), fast_originate_helper::early_media, EVENT_FLAG_SYSTEM, exten, fast_originate(), name, ast_variable::next, NULL, fast_originate_helper::priority, mansession::session, strcasestr(), fast_originate_helper::timeout, tmp(), ast_assigned_ids::uniqueid, ast_assigned_ids::uniqueid2, fast_originate_helper::vars, and mansession_session::writeperm.

Referenced by __init_manager().

05239 {
05240    const char *name = astman_get_header(m, "Channel");
05241    const char *exten = astman_get_header(m, "Exten");
05242    const char *context = astman_get_header(m, "Context");
05243    const char *priority = astman_get_header(m, "Priority");
05244    const char *timeout = astman_get_header(m, "Timeout");
05245    const char *callerid = astman_get_header(m, "CallerID");
05246    const char *account = astman_get_header(m, "Account");
05247    const char *app = astman_get_header(m, "Application");
05248    const char *appdata = astman_get_header(m, "Data");
05249    const char *async = astman_get_header(m, "Async");
05250    const char *id = astman_get_header(m, "ActionID");
05251    const char *codecs = astman_get_header(m, "Codecs");
05252    const char *early_media = astman_get_header(m, "Earlymedia");
05253    struct ast_assigned_ids assignedids = {
05254       .uniqueid = astman_get_header(m, "ChannelId"),
05255       .uniqueid2 = astman_get_header(m, "OtherChannelId"),
05256    };
05257    struct ast_variable *vars = NULL;
05258    char *tech, *data;
05259    char *l = NULL, *n = NULL;
05260    int pi = 0;
05261    int res;
05262    int to = 30000;
05263    int reason = 0;
05264    char tmp[256];
05265    char tmp2[256];
05266    struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
05267    pthread_t th;
05268    int bridge_early = 0;
05269 
05270    if (!cap) {
05271       astman_send_error(s, m, "Internal Error. Memory allocation failure.");
05272       return 0;
05273    }
05274    ast_format_cap_append(cap, ast_format_slin, 0);
05275 
05276    if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
05277       || (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
05278       astman_send_error_va(s, m, "Uniqueid length exceeds maximum of %d\n",
05279          AST_MAX_PUBLIC_UNIQUEID);
05280       res = 0;
05281       goto fast_orig_cleanup;
05282    }
05283 
05284    if (ast_strlen_zero(name)) {
05285       astman_send_error(s, m, "Channel not specified");
05286       res = 0;
05287       goto fast_orig_cleanup;
05288    }
05289    if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) {
05290       if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
05291          astman_send_error(s, m, "Invalid priority");
05292          res = 0;
05293          goto fast_orig_cleanup;
05294       }
05295    }
05296    if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) {
05297       astman_send_error(s, m, "Invalid timeout");
05298       res = 0;
05299       goto fast_orig_cleanup;
05300    }
05301    ast_copy_string(tmp, name, sizeof(tmp));
05302    tech = tmp;
05303    data = strchr(tmp, '/');
05304    if (!data) {
05305       astman_send_error(s, m, "Invalid channel");
05306       res = 0;
05307       goto fast_orig_cleanup;
05308    }
05309    *data++ = '\0';
05310    ast_copy_string(tmp2, callerid, sizeof(tmp2));
05311    ast_callerid_parse(tmp2, &n, &l);
05312    if (n) {
05313       if (ast_strlen_zero(n)) {
05314          n = NULL;
05315       }
05316    }
05317    if (l) {
05318       ast_shrink_phone_number(l);
05319       if (ast_strlen_zero(l)) {
05320          l = NULL;
05321       }
05322    }
05323    if (!ast_strlen_zero(codecs)) {
05324       ast_format_cap_remove_by_type(cap, AST_MEDIA_TYPE_UNKNOWN);
05325       ast_format_cap_update_by_allow_disallow(cap, codecs, 1);
05326    }
05327 
05328    if (!ast_strlen_zero(app) && s->session) {
05329       int bad_appdata = 0;
05330       /* To run the System application (or anything else that goes to
05331        * shell), you must have the additional System privilege */
05332       if (!(s->session->writeperm & EVENT_FLAG_SYSTEM)
05333          && (
05334             strcasestr(app, "system") ||      /* System(rm -rf /)
05335                                                  TrySystem(rm -rf /)       */
05336             strcasestr(app, "exec") ||        /* Exec(System(rm -rf /))
05337                                                  TryExec(System(rm -rf /)) */
05338             strcasestr(app, "agi") ||         /* AGI(/bin/rm,-rf /)
05339                                                  EAGI(/bin/rm,-rf /)       */
05340             strcasestr(app, "mixmonitor") ||  /* MixMonitor(blah,,rm -rf)  */
05341             strcasestr(app, "externalivr") || /* ExternalIVR(rm -rf)       */
05342             (strstr(appdata, "SHELL") && (bad_appdata = 1)) ||       /* NoOp(${SHELL(rm -rf /)})  */
05343             (strstr(appdata, "EVAL") && (bad_appdata = 1))           /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
05344             )) {
05345          char error_buf[64];
05346          snprintf(error_buf, sizeof(error_buf), "Originate Access Forbidden: %s", bad_appdata ? "Data" : "Application");
05347          astman_send_error(s, m, error_buf);
05348          res = 0;
05349          goto fast_orig_cleanup;
05350       }
05351    }
05352 
05353    /* Check early if the extension exists. If not, we need to bail out here. */
05354    if (exten && context && pi) {
05355       if (! ast_exists_extension(NULL, context, exten, pi, l)) {
05356          /* The extension does not exist. */
05357          astman_send_error(s, m, "Extension does not exist.");
05358          res = 0;
05359          goto fast_orig_cleanup;
05360       }
05361    }
05362 
05363    /* Allocate requested channel variables */
05364    vars = astman_get_variables(m);
05365    if (s->session && s->session->chanvars) {
05366       struct ast_variable *v, *old;
05367       old = vars;
05368       vars = NULL;
05369 
05370       /* The variables in the AMI originate action are appended at the end of the list, to override any user variables that apply*/
05371 
05372       vars = ast_variables_dup(s->session->chanvars);
05373       if (old) {
05374          for (v = vars; v->next; v = v->next );
05375          if (v->next) {
05376             v->next = old; /* Append originate variables at end of list */
05377          }
05378       }
05379    }
05380 
05381    /* For originate async - we can bridge in early media stage */
05382    bridge_early = ast_true(early_media);
05383 
05384    if (ast_true(async)) {
05385       struct fast_originate_helper *fast;
05386 
05387       fast = ast_calloc(1, sizeof(*fast));
05388       if (!fast || ast_string_field_init(fast, 252)) {
05389          ast_free(fast);
05390          ast_variables_destroy(vars);
05391          res = -1;
05392       } else {
05393          if (!ast_strlen_zero(id)) {
05394             ast_string_field_build(fast, idtext, "ActionID: %s\r\n", id);
05395          }
05396          ast_string_field_set(fast, tech, tech);
05397          ast_string_field_set(fast, data, data);
05398          ast_string_field_set(fast, app, app);
05399          ast_string_field_set(fast, appdata, appdata);
05400          ast_string_field_set(fast, cid_num, l);
05401          ast_string_field_set(fast, cid_name, n);
05402          ast_string_field_set(fast, context, context);
05403          ast_string_field_set(fast, exten, exten);
05404          ast_string_field_set(fast, account, account);
05405          ast_string_field_set(fast, channelid, assignedids.uniqueid);
05406          ast_string_field_set(fast, otherchannelid, assignedids.uniqueid2);
05407          fast->vars = vars;
05408          fast->cap = cap;
05409          cap = NULL; /* transfered originate helper the capabilities structure.  It is now responsible for freeing it. */
05410          fast->timeout = to;
05411          fast->early_media = bridge_early;
05412          fast->priority = pi;
05413          if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) {
05414             destroy_fast_originate_helper(fast);
05415             res = -1;
05416          } else {
05417             res = 0;
05418          }
05419       }
05420    } else if (!ast_strlen_zero(app)) {
05421       res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL, assignedids.uniqueid ? &assignedids : NULL);
05422       ast_variables_destroy(vars);
05423    } else {
05424       if (exten && context && pi) {
05425          res = ast_pbx_outgoing_exten(tech, cap, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL, bridge_early, assignedids.uniqueid ? &assignedids : NULL);
05426          ast_variables_destroy(vars);
05427       } else {
05428          astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
05429          ast_variables_destroy(vars);
05430          res = 0;
05431          goto fast_orig_cleanup;
05432       }
05433    }
05434    if (!res) {
05435       astman_send_ack(s, m, "Originate successfully queued");
05436    } else {
05437       astman_send_error(s, m, "Originate failed");
05438    }
05439 
05440 fast_orig_cleanup:
05441    ao2_cleanup(cap);
05442    return 0;
05443 }

static int action_ping ( struct mansession s,
const struct message m 
) [static]

Definition at line 3298 of file manager.c.

References ast_strlen_zero, ast_tvnow(), astman_append(), and astman_get_header().

Referenced by __init_manager().

03299 {
03300    const char *actionid = astman_get_header(m, "ActionID");
03301    struct timeval now = ast_tvnow();
03302 
03303    astman_append(s, "Response: Success\r\n");
03304    if (!ast_strlen_zero(actionid)){
03305       astman_append(s, "ActionID: %s\r\n", actionid);
03306    }
03307    astman_append(
03308       s,
03309       "Ping: Pong\r\n"
03310       "Timestamp: %ld.%06lu\r\n"
03311       "\r\n",
03312       (long) now.tv_sec, (unsigned long) now.tv_usec);
03313    return 0;
03314 }

static int action_presencestate ( struct mansession s,
const struct message m 
) [static]

Definition at line 5510 of file manager.c.

References AST_PRESENCE_INVALID, ast_presence_state2str(), ast_strlen_zero, astman_append(), astman_get_header(), astman_send_error(), astman_send_error_va(), and astman_start_ack().

Referenced by __init_manager().

05511 {
05512    const char *provider = astman_get_header(m, "Provider");
05513    enum ast_presence_state state;
05514    char *subtype;
05515    char *message;
05516 
05517    if (ast_strlen_zero(provider)) {
05518       astman_send_error(s, m, "No provider specified");
05519       return 0;
05520    }
05521 
05522    state = ast_presence_state(provider, &subtype, &message);
05523    if (state == AST_PRESENCE_INVALID) {
05524       astman_send_error_va(s, m, "Invalid provider %s or provider in invalid state", provider);
05525       return 0;
05526    }
05527 
05528    astman_start_ack(s, m);
05529    astman_append(s, "Message: Presence State\r\n"
05530                     "State: %s\r\n", ast_presence_state2str(state));
05531 
05532    if (!ast_strlen_zero(subtype)) {
05533       astman_append(s, "Subtype: %s\r\n", subtype);
05534    }
05535 
05536    if (!ast_strlen_zero(message)) {
05537       /* XXX The Message header here is deprecated as it
05538        * duplicates the action response header 'Message'.
05539        * Remove it in the next major revision of AMI.
05540        */
05541       astman_append(s, "Message: %s\r\n"
05542                        "PresenceMessage: %s\r\n",
05543                        message, message);
05544    }
05545    astman_append(s, "\r\n");
05546 
05547    return 0;
05548 }

static int action_redirect ( struct mansession s,
const struct message m 
) [static]

action_redirect: The redirect manager command

Definition at line 4555 of file manager.c.

References ast_async_goto(), ast_channel_flags(), ast_channel_get_by_name(), ast_channel_is_bridged(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_check_hangup_locked(), ast_clear_flag, ast_findlabel_extension(), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT, ast_set_flag, ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), buf, context, exten, name, and NULL.

Referenced by __init_manager().

04556 {
04557    char buf[256];
04558    const char *name = astman_get_header(m, "Channel");
04559    const char *name2 = astman_get_header(m, "ExtraChannel");
04560    const char *exten = astman_get_header(m, "Exten");
04561    const char *exten2 = astman_get_header(m, "ExtraExten");
04562    const char *context = astman_get_header(m, "Context");
04563    const char *context2 = astman_get_header(m, "ExtraContext");
04564    const char *priority = astman_get_header(m, "Priority");
04565    const char *priority2 = astman_get_header(m, "ExtraPriority");
04566    struct ast_channel *chan;
04567    struct ast_channel *chan2;
04568    int pi = 0;
04569    int pi2 = 0;
04570    int res;
04571    int chan1_wait = 0;
04572    int chan2_wait = 0;
04573 
04574    if (ast_strlen_zero(name)) {
04575       astman_send_error(s, m, "Channel not specified");
04576       return 0;
04577    }
04578 
04579    if (ast_strlen_zero(context)) {
04580       astman_send_error(s, m, "Context not specified");
04581       return 0;
04582    }
04583    if (ast_strlen_zero(exten)) {
04584       astman_send_error(s, m, "Exten not specified");
04585       return 0;
04586    }
04587    if (ast_strlen_zero(priority)) {
04588       astman_send_error(s, m, "Priority not specified");
04589       return 0;
04590    }
04591    if (sscanf(priority, "%30d", &pi) != 1) {
04592       pi = ast_findlabel_extension(NULL, context, exten, priority, NULL);
04593    }
04594    if (pi < 1) {
04595       astman_send_error(s, m, "Priority is invalid");
04596       return 0;
04597    }
04598 
04599    if (!ast_strlen_zero(name2) && !ast_strlen_zero(context2)) {
04600       /* We have an ExtraChannel and an ExtraContext */
04601       if (ast_strlen_zero(exten2)) {
04602          astman_send_error(s, m, "ExtraExten not specified");
04603          return 0;
04604       }
04605       if (ast_strlen_zero(priority2)) {
04606          astman_send_error(s, m, "ExtraPriority not specified");
04607          return 0;
04608       }
04609       if (sscanf(priority2, "%30d", &pi2) != 1) {
04610          pi2 = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL);
04611       }
04612       if (pi2 < 1) {
04613          astman_send_error(s, m, "ExtraPriority is invalid");
04614          return 0;
04615       }
04616    }
04617 
04618    chan = ast_channel_get_by_name(name);
04619    if (!chan) {
04620       snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
04621       astman_send_error(s, m, buf);
04622       return 0;
04623    }
04624    if (ast_check_hangup_locked(chan)) {
04625       astman_send_error(s, m, "Redirect failed, channel not up.");
04626       chan = ast_channel_unref(chan);
04627       return 0;
04628    }
04629 
04630    if (ast_strlen_zero(name2)) {
04631       /* Single channel redirect in progress. */
04632       res = ast_async_goto(chan, context, exten, pi);
04633       if (!res) {
04634          astman_send_ack(s, m, "Redirect successful");
04635       } else {
04636          astman_send_error(s, m, "Redirect failed");
04637       }
04638       chan = ast_channel_unref(chan);
04639       return 0;
04640    }
04641 
04642    chan2 = ast_channel_get_by_name(name2);
04643    if (!chan2) {
04644       snprintf(buf, sizeof(buf), "ExtraChannel does not exist: %s", name2);
04645       astman_send_error(s, m, buf);
04646       chan = ast_channel_unref(chan);
04647       return 0;
04648    }
04649    if (ast_check_hangup_locked(chan2)) {
04650       astman_send_error(s, m, "Redirect failed, extra channel not up.");
04651       chan2 = ast_channel_unref(chan2);
04652       chan = ast_channel_unref(chan);
04653       return 0;
04654    }
04655 
04656    /* Dual channel redirect in progress. */
04657    ast_channel_lock(chan);
04658    if (ast_channel_is_bridged(chan)) {
04659       ast_set_flag(ast_channel_flags(chan), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT);
04660       chan1_wait = 1;
04661    }
04662    ast_channel_unlock(chan);
04663 
04664    ast_channel_lock(chan2);
04665    if (ast_channel_is_bridged(chan2)) {
04666       ast_set_flag(ast_channel_flags(chan2), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT);
04667       chan2_wait = 1;
04668    }
04669    ast_channel_unlock(chan2);
04670 
04671    res = ast_async_goto(chan, context, exten, pi);
04672    if (!res) {
04673       if (!ast_strlen_zero(context2)) {
04674          res = ast_async_goto(chan2, context2, exten2, pi2);
04675       } else {
04676          res = ast_async_goto(chan2, context, exten, pi);
04677       }
04678       if (!res) {
04679          astman_send_ack(s, m, "Dual Redirect successful");
04680       } else {
04681          astman_send_error(s, m, "Secondary redirect failed");
04682       }
04683    } else {
04684       astman_send_error(s, m, "Redirect failed");
04685    }
04686 
04687    /* Release the bridge wait. */
04688    if (chan1_wait) {
04689       ast_channel_lock(chan);
04690       ast_clear_flag(ast_channel_flags(chan), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT);
04691       ast_channel_unlock(chan);
04692    }
04693    if (chan2_wait) {
04694       ast_channel_lock(chan2);
04695       ast_clear_flag(ast_channel_flags(chan2), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT);
04696       ast_channel_unlock(chan2);
04697    }
04698 
04699    chan2 = ast_channel_unref(chan2);
04700    chan = ast_channel_unref(chan);
04701    return 0;
04702 }

static int action_reload ( struct mansession s,
const struct message m 
) [static]

Send a reload event.

Definition at line 5860 of file manager.c.

References ast_module_reload(), AST_MODULE_RELOAD_ERROR, AST_MODULE_RELOAD_IN_PROGRESS, AST_MODULE_RELOAD_NOT_FOUND, AST_MODULE_RELOAD_NOT_IMPLEMENTED, AST_MODULE_RELOAD_QUEUED, AST_MODULE_RELOAD_SUCCESS, AST_MODULE_RELOAD_UNINITIALIZED, astman_get_header(), astman_send_ack(), astman_send_error(), NULL, and S_OR.

Referenced by __init_manager().

05861 {
05862    const char *module = astman_get_header(m, "Module");
05863    enum ast_module_reload_result res = ast_module_reload(S_OR(module, NULL));
05864 
05865    switch (res) {
05866    case AST_MODULE_RELOAD_NOT_FOUND:
05867       astman_send_error(s, m, "No such module");
05868       break;
05869    case AST_MODULE_RELOAD_NOT_IMPLEMENTED:
05870       astman_send_error(s, m, "Module does not support reload");
05871       break;
05872    case AST_MODULE_RELOAD_ERROR:
05873       astman_send_error(s, m, "An unknown error occurred");
05874       break;
05875    case AST_MODULE_RELOAD_IN_PROGRESS:
05876       astman_send_error(s, m, "A reload is in progress");
05877       break;
05878    case AST_MODULE_RELOAD_UNINITIALIZED:
05879       astman_send_error(s, m, "Module not initialized");
05880       break;
05881    case AST_MODULE_RELOAD_QUEUED:
05882    case AST_MODULE_RELOAD_SUCCESS:
05883       /* Treat a queued request as success */
05884       astman_send_ack(s, m, "Module Reloaded");
05885       break;
05886    }
05887    return 0;
05888 }

static int action_sendtext ( struct mansession s,
const struct message m 
) [static]

Definition at line 4520 of file manager.c.

References ast_channel_get_by_name(), ast_channel_unref, ast_sendtext(), ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), c, name, and NULL.

Referenced by __init_manager().

04521 {
04522    struct ast_channel *c = NULL;
04523    const char *name = astman_get_header(m, "Channel");
04524    const char *textmsg = astman_get_header(m, "Message");
04525    int res = 0;
04526 
04527    if (ast_strlen_zero(name)) {
04528       astman_send_error(s, m, "No channel specified");
04529       return 0;
04530    }
04531 
04532    if (ast_strlen_zero(textmsg)) {
04533       astman_send_error(s, m, "No Message specified");
04534       return 0;
04535    }
04536 
04537    if (!(c = ast_channel_get_by_name(name))) {
04538       astman_send_error(s, m, "No such channel");
04539       return 0;
04540    }
04541 
04542    res = ast_sendtext(c, textmsg);
04543    c = ast_channel_unref(c);
04544 
04545    if (res >= 0) {
04546       astman_send_ack(s, m, "Success");
04547    } else {
04548       astman_send_error(s, m, "Failure");
04549    }
04550 
04551    return 0;
04552 }

static int action_setvar ( struct mansession s,
const struct message m 
) [static]

Definition at line 4245 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(), c, name, NULL, pbx_builtin_setvar_helper(), and S_OR.

Referenced by __init_manager().

04246 {
04247    struct ast_channel *c = NULL;
04248    const char *name = astman_get_header(m, "Channel");
04249    const char *varname = astman_get_header(m, "Variable");
04250    const char *varval = astman_get_header(m, "Value");
04251    int res = 0;
04252 
04253    if (ast_strlen_zero(varname)) {
04254       astman_send_error(s, m, "No variable specified");
04255       return 0;
04256    }
04257 
04258    if (!ast_strlen_zero(name)) {
04259       if (!(c = ast_channel_get_by_name(name))) {
04260          astman_send_error(s, m, "No such channel");
04261          return 0;
04262       }
04263    }
04264 
04265    res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
04266 
04267    if (c) {
04268       c = ast_channel_unref(c);
04269    }
04270    if (res == 0) {
04271       astman_send_ack(s, m, "Variable Set");
04272    } else {
04273       astman_send_error(s, m, "Variable not set");
04274    }
04275    return 0;
04276 }

static int action_status ( struct mansession s,
const struct message m 
) [static]

Manager "status" command to show channels.

Definition at line 4447 of file manager.c.

References AST_APP_ARG, ast_channel_get_by_name(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, AST_DECLARE_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, ast_true(), astman_append(), astman_get_header(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), channels, function_capable_string_allowed_with_auths(), generate_status(), name, NULL, S_OR, mansession::session, and mansession_session::writeperm.

Referenced by __init_manager().

04448 {
04449    const char *name = astman_get_header(m, "Channel");
04450    const char *chan_variables = astman_get_header(m, "Variables");
04451    const char *all_chan_variables = astman_get_header(m, "AllVariables");
04452    int all_variables = 0;
04453    const char *id = astman_get_header(m, "ActionID");
04454    char *variables = ast_strdupa(S_OR(chan_variables, ""));
04455    struct ast_channel *chan;
04456    int channels = 0;
04457    int all = ast_strlen_zero(name); /* set if we want all channels */
04458    char id_text[256];
04459    struct ast_channel_iterator *it_chans = NULL;
04460    AST_DECLARE_APP_ARGS(vars,
04461       AST_APP_ARG(name)[100];
04462    );
04463 
04464    if (!ast_strlen_zero(all_chan_variables)) {
04465       all_variables = ast_true(all_chan_variables);
04466    }
04467 
04468    if (!(function_capable_string_allowed_with_auths(variables, s->session->writeperm))) {
04469       astman_send_error(s, m, "Status Access Forbidden: Variables");
04470       return 0;
04471    }
04472 
04473    if (all) {
04474       if (!(it_chans = ast_channel_iterator_all_new())) {
04475          astman_send_error(s, m, "Memory Allocation Failure");
04476          return 1;
04477       }
04478       chan = ast_channel_iterator_next(it_chans);
04479    } else {
04480       chan = ast_channel_get_by_name(name);
04481       if (!chan) {
04482          astman_send_error(s, m, "No such channel");
04483          return 0;
04484       }
04485    }
04486 
04487    astman_send_listack(s, m, "Channel status will follow", "start");
04488 
04489    if (!ast_strlen_zero(id)) {
04490       snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
04491    } else {
04492       id_text[0] = '\0';
04493    }
04494 
04495    if (!ast_strlen_zero(chan_variables)) {
04496       AST_STANDARD_APP_ARGS(vars, variables);
04497    }
04498 
04499    /* if we look by name, we break after the first iteration */
04500    for (; chan; all ? chan = ast_channel_iterator_next(it_chans) : 0) {
04501       ast_channel_lock(chan);
04502 
04503       generate_status(s, chan, vars.name, vars.argc, all_variables, id_text, &channels);
04504 
04505       ast_channel_unlock(chan);
04506       chan = ast_channel_unref(chan);
04507    }
04508 
04509    if (it_chans) {
04510       ast_channel_iterator_destroy(it_chans);
04511    }
04512 
04513    astman_send_list_complete_start(s, m, "StatusComplete", channels);
04514    astman_append(s, "Items: %d\r\n", channels);
04515    astman_send_list_complete_end(s);
04516 
04517    return 0;
04518 }

static int action_timeout ( struct mansession s,
const struct message m 
) [static]

Definition at line 5550 of file manager.c.

References ast_channel_get_by_name(), ast_channel_lock, ast_channel_setwhentohangup_tv(), ast_channel_unlock, ast_channel_unref, ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), c, and name.

Referenced by __init_manager().

05551 {
05552    struct ast_channel *c;
05553    const char *name = astman_get_header(m, "Channel");
05554    double timeout = atof(astman_get_header(m, "Timeout"));
05555    struct timeval when = { timeout, 0 };
05556 
05557    if (ast_strlen_zero(name)) {
05558       astman_send_error(s, m, "No channel specified");
05559       return 0;
05560    }
05561 
05562    if (!timeout || timeout < 0) {
05563       astman_send_error(s, m, "No timeout specified");
05564       return 0;
05565    }
05566 
05567    if (!(c = ast_channel_get_by_name(name))) {
05568       astman_send_error(s, m, "No such channel");
05569       return 0;
05570    }
05571 
05572    when.tv_usec = (timeout - when.tv_sec) * 1000000.0;
05573 
05574    ast_channel_lock(c);
05575    ast_channel_setwhentohangup_tv(c, when);
05576    ast_channel_unlock(c);
05577    c = ast_channel_unref(c);
05578 
05579    astman_send_ack(s, m, "Timeout Set");
05580 
05581    return 0;
05582 }

static int action_updateconfig ( struct mansession s,
const struct message m 
) [static]

Definition at line 3796 of file manager.c.

References ast_config_destroy(), ast_config_load2(), ast_config_text_file_save2(), 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_SAVE_FLAG_NONE, CONFIG_SAVE_FLAG_PRESERVE_EFFECTIVE_CONTEXT, CONFIG_STATUS_FILEINVALID, FAILURE_ALLOCATION, FAILURE_APPEND, FAILURE_DELCAT, FAILURE_DELETE, FAILURE_EMPTYCAT, FAILURE_NEWCAT, FAILURE_TEMPLATE, FAILURE_UPDATE, handle_updates(), NULL, result, UNKNOWN_ACTION, UNKNOWN_CATEGORY, UNSPECIFIED_ARGUMENT, and UNSPECIFIED_CATEGORY.

Referenced by __init_manager().

03797 {
03798    struct ast_config *cfg;
03799    const char *sfn = astman_get_header(m, "SrcFilename");
03800    const char *dfn = astman_get_header(m, "DstFilename");
03801    int res;
03802    const char *rld = astman_get_header(m, "Reload");
03803    int preserve_effective_context = CONFIG_SAVE_FLAG_PRESERVE_EFFECTIVE_CONTEXT;
03804    const char *preserve_effective_context_string = astman_get_header(m, "PreserveEffectiveContext");
03805    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
03806    enum error_type result;
03807 
03808    if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) {
03809       astman_send_error(s, m, "Filename not specified");
03810       return 0;
03811    }
03812    if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) {
03813       astman_send_error(s, m, "Config file not found");
03814       return 0;
03815    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
03816       astman_send_error(s, m, "Config file has invalid format");
03817       return 0;
03818    }
03819    result = handle_updates(s, m, cfg, dfn);
03820    if (!result) {
03821       ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */
03822       if (!ast_strlen_zero(preserve_effective_context_string) && !ast_true(preserve_effective_context_string)) {
03823          preserve_effective_context = CONFIG_SAVE_FLAG_NONE;
03824       }
03825       res = ast_config_text_file_save2(dfn, cfg, "Manager", preserve_effective_context);
03826       ast_config_destroy(cfg);
03827       if (res) {
03828          astman_send_error(s, m, "Save of config failed");
03829          return 0;
03830       }
03831       astman_send_ack(s, m, NULL);
03832       if (!ast_strlen_zero(rld)) {
03833          if (ast_true(rld)) {
03834             rld = NULL;
03835          }
03836          ast_module_reload(rld);
03837       }
03838    } else {
03839       ast_config_destroy(cfg);
03840       switch(result) {
03841       case UNKNOWN_ACTION:
03842          astman_send_error(s, m, "Unknown action command");
03843          break;
03844       case UNKNOWN_CATEGORY:
03845          astman_send_error(s, m, "Given category does not exist");
03846          break;
03847       case UNSPECIFIED_CATEGORY:
03848          astman_send_error(s, m, "Category not specified");
03849          break;
03850       case UNSPECIFIED_ARGUMENT:
03851          astman_send_error(s, m, "Problem with category, value, or line (if required)");
03852          break;
03853       case FAILURE_ALLOCATION:
03854          astman_send_error(s, m, "Memory allocation failure, this should not happen");
03855          break;
03856       case FAILURE_NEWCAT:
03857          astman_send_error(s, m, "Create category did not complete successfully");
03858          break;
03859       case FAILURE_DELCAT:
03860          astman_send_error(s, m, "Delete category did not complete successfully");
03861          break;
03862       case FAILURE_EMPTYCAT:
03863          astman_send_error(s, m, "Empty category did not complete successfully");
03864          break;
03865       case FAILURE_UPDATE:
03866          astman_send_error(s, m, "Update did not complete successfully");
03867          break;
03868       case FAILURE_DELETE:
03869          astman_send_error(s, m, "Delete did not complete successfully");
03870          break;
03871       case FAILURE_APPEND:
03872          astman_send_error(s, m, "Append did not complete successfully");
03873          break;
03874       case FAILURE_TEMPLATE:
03875          astman_send_error(s, m, "Template category not found");
03876          break;
03877       }
03878    }
03879    return 0;
03880 }

static int action_userevent ( struct mansession s,
const struct message m 
) [static]

Definition at line 5757 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().

05758 {
05759    const char *event = astman_get_header(m, "UserEvent");
05760    struct ast_str *body = ast_str_thread_get(&userevent_buf, 16);
05761    int x;
05762 
05763    ast_str_reset(body);
05764 
05765    for (x = 0; x < m->hdrcount; x++) {
05766       if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:")) &&
05767             strncasecmp("Action:", m->headers[x], strlen("Action:"))) {
05768          ast_str_append(&body, 0, "%s\r\n", m->headers[x]);
05769       }
05770    }
05771 
05772    astman_send_ack(s, m, "Event Sent");
05773    manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, ast_str_buffer(body));
05774    return 0;
05775 }

static int action_waitevent ( struct mansession s,
const struct message m 
) [static]

Definition at line 3900 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, match_filter(), max, mansession_session::needdestroy, NULL, mansession_session::readperm, mansession_session::send_events, mansession::session, mansession_session::sessiontimeout, timeout, and mansession_session::waiting_thread.

Referenced by __init_manager().

03901 {
03902    const char *timeouts = astman_get_header(m, "Timeout");
03903    int timeout = -1;
03904    int x;
03905    int needexit = 0;
03906    const char *id = astman_get_header(m, "ActionID");
03907    char idText[256];
03908 
03909    if (!ast_strlen_zero(id)) {
03910       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
03911    } else {
03912       idText[0] = '\0';
03913    }
03914 
03915    if (!ast_strlen_zero(timeouts)) {
03916       sscanf(timeouts, "%30i", &timeout);
03917       if (timeout < -1) {
03918          timeout = -1;
03919       }
03920       /* XXX maybe put an upper bound, or prevent the use of 0 ? */
03921    }
03922 
03923    ao2_lock(s->session);
03924    if (s->session->waiting_thread != AST_PTHREADT_NULL) {
03925       pthread_kill(s->session->waiting_thread, SIGURG);
03926    }
03927 
03928    if (s->session->managerid) { /* AMI-over-HTTP session */
03929       /*
03930        * Make sure the timeout is within the expire time of the session,
03931        * as the client will likely abort the request if it does not see
03932        * data coming after some amount of time.
03933        */
03934       time_t now = time(NULL);
03935       int max = s->session->sessiontimeout - now - 10;
03936 
03937       if (max < 0) { /* We are already late. Strange but possible. */
03938          max = 0;
03939       }
03940       if (timeout < 0 || timeout > max) {
03941          timeout = max;
03942       }
03943       if (!s->session->send_events) {  /* make sure we record events */
03944          s->session->send_events = -1;
03945       }
03946    }
03947    ao2_unlock(s->session);
03948 
03949    /* XXX should this go inside the lock ? */
03950    s->session->waiting_thread = pthread_self(); /* let new events wake up this thread */
03951    ast_debug(1, "Starting waiting for an event!\n");
03952 
03953    for (x = 0; x < timeout || timeout < 0; x++) {
03954       ao2_lock(s->session);
03955       if (AST_RWLIST_NEXT(s->session->last_ev, eq_next)) {
03956          needexit = 1;
03957       }
03958       /* We can have multiple HTTP session point to the same mansession entry.
03959        * The way we deal with it is not very nice: newcomers kick out the previous
03960        * HTTP session. XXX this needs to be improved.
03961        */
03962       if (s->session->waiting_thread != pthread_self()) {
03963          needexit = 1;
03964       }
03965       if (s->session->needdestroy) {
03966          needexit = 1;
03967       }
03968       ao2_unlock(s->session);
03969       if (needexit) {
03970          break;
03971       }
03972       if (s->session->managerid == 0) {   /* AMI session */
03973          if (ast_wait_for_input(s->session->fd, 1000)) {
03974             break;
03975          }
03976       } else { /* HTTP session */
03977          sleep(1);
03978       }
03979    }
03980    ast_debug(1, "Finished waiting for an event!\n");
03981 
03982    ao2_lock(s->session);
03983    if (s->session->waiting_thread == pthread_self()) {
03984       struct eventqent *eqe = s->session->last_ev;
03985       astman_send_response(s, m, "Success", "Waiting for Event completed.");
03986       while ((eqe = advance_event(eqe))) {
03987          if (((s->session->readperm & eqe->category) == eqe->category)
03988             && ((s->session->send_events & eqe->category) == eqe->category)
03989             && match_filter(s, eqe->eventdata)) {
03990             astman_append(s, "%s", eqe->eventdata);
03991          }
03992          s->session->last_ev = eqe;
03993       }
03994       astman_append(s,
03995          "Event: WaitEventComplete\r\n"
03996          "%s"
03997          "\r\n", idText);
03998       s->session->waiting_thread = AST_PTHREADT_NULL;
03999    } else {
04000       ast_debug(1, "Abandoning event request!\n");
04001    }
04002    ao2_unlock(s->session);
04003 
04004    return 0;
04005 }

static struct eventqent* advance_event ( struct eventqent e  )  [static, read]

Definition at line 2541 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().

02542 {
02543    struct eventqent *next;
02544 
02545    AST_RWLIST_RDLOCK(&all_events);
02546    if ((next = AST_RWLIST_NEXT(e, eq_next))) {
02547       ast_atomic_fetchadd_int(&next->usecount, 1);
02548       ast_atomic_fetchadd_int(&e->usecount, -1);
02549    }
02550    AST_RWLIST_UNLOCK(&all_events);
02551    return next;
02552 }

static AO2_GLOBAL_OBJ_STATIC ( event_docs   )  [static]

A container of event documentation nodes.

static AO2_GLOBAL_OBJ_STATIC ( mgr_sessions   )  [static]

Active manager connection sessions container.

static int aocmessage_get_unit_entry ( const struct message m,
struct ast_aoc_unit_entry entry,
unsigned int  entry_num 
) [static]

Definition at line 5008 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().

05009 {
05010    const char *unitamount;
05011    const char *unittype;
05012    struct ast_str *str = ast_str_alloca(32);
05013 
05014    memset(entry, 0, sizeof(*entry));
05015 
05016    ast_str_set(&str, 0, "UnitAmount(%u)", entry_num);
05017    unitamount = astman_get_header(m, ast_str_buffer(str));
05018 
05019    ast_str_set(&str, 0, "UnitType(%u)", entry_num);
05020    unittype = astman_get_header(m, ast_str_buffer(str));
05021 
05022    if (!ast_strlen_zero(unitamount) && (sscanf(unitamount, "%30u", &entry->amount) == 1)) {
05023       entry->valid_amount = 1;
05024    }
05025 
05026    if (!ast_strlen_zero(unittype) && sscanf(unittype, "%30u", &entry->type) == 1) {
05027       entry->valid_type = 1;
05028    }
05029 
05030    return 0;
05031 }

static void append_channel_vars ( struct ast_str **  pbuf,
struct ast_channel chan 
) [static]

Definition at line 6585 of file manager.c.

References ao2_cleanup, ast_channel_get_manager_vars(), ast_channel_name(), AST_LIST_TRAVERSE, ast_str_append(), ast_var_t::name, NULL, RAII_VAR, ast_var_t::value, and var.

Referenced by __ast_manager_event_multichan().

06586 {
06587    RAII_VAR(struct varshead *, vars, NULL, ao2_cleanup);
06588    struct ast_var_t *var;
06589 
06590    vars = ast_channel_get_manager_vars(chan);
06591 
06592    if (!vars) {
06593       return;
06594    }
06595 
06596    AST_LIST_TRAVERSE(vars, var, entries) {
06597       ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", ast_channel_name(chan), var->name, var->value);
06598    }
06599 }

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 6561 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, NULL, eventqent::seq, tmp(), eventqent::tv, and eventqent::usecount.

Referenced by __ast_manager_event_multichan(), __init_manager(), and append_expected_event_snapshot().

06562 {
06563    struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str));
06564    static int seq;   /* sequence number */
06565 
06566    if (!tmp) {
06567       return -1;
06568    }
06569 
06570    /* need to init all fields, because ast_malloc() does not */
06571    tmp->usecount = 0;
06572    tmp->category = category;
06573    tmp->seq = ast_atomic_fetchadd_int(&seq, 1);
06574    tmp->tv = ast_tvnow();
06575    AST_RWLIST_NEXT(tmp, eq_next) = NULL;
06576    strcpy(tmp->eventdata, str);
06577 
06578    AST_RWLIST_WRLOCK(&all_events);
06579    AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next);
06580    AST_RWLIST_UNLOCK(&all_events);
06581 
06582    return 0;
06583 }

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 2697 of file manager.c.

References action_find(), ao2_lock, ao2_t_ref, ao2_unlock, ARRAY_LEN, ast_free, ast_module_ref, ast_module_unref, ast_strdup, astman_get_header(), mansession::f, manager_action::func, message::hdrcount, message::headers, mansession::hook, manager_action::module, NULL, manager_action::registered, and mansession::session.

Referenced by hook_send().

02698 {
02699    const char *action;
02700    int ret = 0;
02701    struct manager_action *act_found;
02702    struct mansession s = {.session = NULL, };
02703    struct message m = { 0 };
02704    char *dup_str;
02705    char *src;
02706    int x = 0;
02707    int curlen;
02708 
02709    if (hook == NULL) {
02710       return -1;
02711    }
02712 
02713    /* Create our own copy of the AMI action msg string. */
02714    src = dup_str = ast_strdup(msg);
02715    if (!dup_str) {
02716       return -1;
02717    }
02718 
02719    /* convert msg string to message struct */
02720    curlen = strlen(src);
02721    for (x = 0; x < curlen; x++) {
02722       int cr;  /* set if we have \r */
02723       if (src[x] == '\r' && x+1 < curlen && src[x+1] == '\n')
02724          cr = 2;  /* Found. Update length to include \r\n */
02725       else if (src[x] == '\n')
02726          cr = 1;  /* also accept \n only */
02727       else
02728          continue;
02729       /* don't keep empty lines */
02730       if (x && m.hdrcount < ARRAY_LEN(m.headers)) {
02731          /* ... but trim \r\n and terminate the header string */
02732          src[x] = '\0';
02733          m.headers[m.hdrcount++] = src;
02734       }
02735       x += cr;
02736       curlen -= x;      /* remaining size */
02737       src += x;      /* update pointer */
02738       x = -1;        /* reset loop */
02739    }
02740 
02741    action = astman_get_header(&m, "Action");
02742    if (strcasecmp(action, "login")) {
02743       act_found = action_find(action);
02744       if (act_found) {
02745          /*
02746           * we have to simulate a session for this action request
02747           * to be able to pass it down for processing
02748           * This is necessary to meet the previous design of manager.c
02749           */
02750          s.hook = hook;
02751          s.f = (void*)1; /* set this to something so our request will make it through all functions that test it*/
02752 
02753          ao2_lock(act_found);
02754          if (act_found->registered && act_found->func) {
02755             if (act_found->module) {
02756                ast_module_ref(act_found->module);
02757             }
02758             ao2_unlock(act_found);
02759             ret = act_found->func(&s, &m);
02760             ao2_lock(act_found);
02761             if (act_found->module) {
02762                ast_module_unref(act_found->module);
02763             }
02764          } else {
02765             ret = -1;
02766          }
02767          ao2_unlock(act_found);
02768          ao2_t_ref(act_found, -1, "done with found action object");
02769       }
02770    }
02771    ast_free(dup_str);
02772    return ret;
02773 }

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 1930 of file manager.c.

References eventqent::next.

Referenced by get_perm().

01931 {
01932    const char *val = bigstr, *next;
01933 
01934    do {
01935       if ((next = strchr(val, delim))) {
01936          if (!strncmp(val, smallstr, (next - val))) {
01937             return 1;
01938          } else {
01939             continue;
01940          }
01941       } else {
01942          return !strcmp(smallstr, val);
01943       }
01944    } while (*(val = (next + 1)));
01945 
01946    return 0;
01947 }

struct stasis_message_router* ast_manager_get_message_router ( void   )  [read]

Get the stasis_message_router for AMI.

Since:
12
Return values:
The stasis_message_router for AMI
NULL on error

Definition at line 1589 of file manager.c.

References stasis_router.

Referenced by manager_bridging_init(), manager_channels_init(), manager_mwi_init(), and manager_system_init().

01590 {
01591    return stasis_router;
01592 }

struct stasis_topic* ast_manager_get_topic ( void   )  [read]

void ast_manager_publish_event ( const char *  type,
int  class_type,
struct ast_json obj 
)

Publish an event to AMI.

Since:
12
Parameters:
type The type of AMI event to publish
class_type The class on which to publish the event
obj The event data to be published.
Publishes a message to the Stasis Message Bus API message bus solely for the consumption of AMI. The message will be of the type provided by ast_manager_get_type, and will be published to the topic provided by ast_manager_get_topic. As such, the JSON must be constructed as defined by the ast_manager_get_type message.

Definition at line 1721 of file manager.c.

References ao2_cleanup, ast_json_pack(), ast_json_payload_create(), ast_json_ref(), ast_json_unref(), ast_manager_get_generic_type(), ast_manager_get_topic(), NULL, RAII_VAR, stasis_message_create(), and stasis_publish().

Referenced by analog_publish_channel_alarm_clear(), analog_publish_dnd_state(), publish_channel_alarm(), publish_channel_alarm_clear(), publish_dnd_state(), publish_fully_booted(), publish_qualify_peer_done(), publish_span_alarm(), publish_span_alarm_clear(), and really_quit().

01722 {
01723    RAII_VAR(struct ast_json *, event_info, NULL, ast_json_unref);
01724    RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
01725    RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
01726 
01727    if (!obj || !ast_manager_get_generic_type()) {
01728       return;
01729    }
01730 
01731    ast_json_ref(obj);
01732    event_info = ast_json_pack("{s: s, s: i, s: o}",
01733          "type", type,
01734          "class_type", class_type,
01735          "event", obj);
01736    if (!event_info) {
01737       return;
01738    }
01739 
01740    payload = ast_json_payload_create(event_info);
01741    if (!payload) {
01742       return;
01743    }
01744    message = stasis_message_create(ast_manager_get_generic_type(), payload);
01745    if (!message) {
01746       return;
01747    }
01748    stasis_publish(ast_manager_get_topic(), message);
01749 }

int ast_manager_register2 ( const char *  action,
int  auth,
int(*)(struct mansession *s, const struct message *m)  func,
struct ast_module module,
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 6826 of file manager.c.

References manager_action::action, action_destroy(), ao2_t_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, manager_action::final_response, func, manager_action::func, manager_action::list_responses, manager_action::module, and NULL.

Referenced by ast_res_pjsip_init_options_handling(), and load_parking_manager().

06827 {
06828    struct manager_action *cur;
06829 
06830    cur = ao2_t_alloc(sizeof(*cur), action_destroy, action);
06831    if (!cur) {
06832       return -1;
06833    }
06834    if (ast_string_field_init(cur, 128)) {
06835       ao2_t_ref(cur, -1, "action object creation failed");
06836       return -1;
06837    }
06838 
06839    cur->action = action;
06840    cur->authority = auth;
06841    cur->func = func;
06842    cur->module = module;
06843 #ifdef AST_XML_DOCS
06844    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
06845       char *tmpxml;
06846 
06847       tmpxml = ast_xmldoc_build_synopsis("manager", action, NULL);
06848       ast_string_field_set(cur, synopsis, tmpxml);
06849       ast_free(tmpxml);
06850 
06851       tmpxml = ast_xmldoc_build_syntax("manager", action, NULL);
06852       ast_string_field_set(cur, syntax, tmpxml);
06853       ast_free(tmpxml);
06854 
06855       tmpxml = ast_xmldoc_build_description("manager", action, NULL);
06856       ast_string_field_set(cur, description, tmpxml);
06857       ast_free(tmpxml);
06858 
06859       tmpxml = ast_xmldoc_build_seealso("manager", action, NULL);
06860       ast_string_field_set(cur, seealso, tmpxml);
06861       ast_free(tmpxml);
06862 
06863       tmpxml = ast_xmldoc_build_arguments("manager", action, NULL);
06864       ast_string_field_set(cur, arguments, tmpxml);
06865       ast_free(tmpxml);
06866 
06867       cur->final_response = ast_xmldoc_build_final_response("manager", action, NULL);
06868       cur->list_responses = ast_xmldoc_build_list_responses("manager", action, NULL);
06869 
06870       cur->docsrc = AST_XML_DOC;
06871    } else
06872 #endif
06873    {
06874       ast_string_field_set(cur, synopsis, synopsis);
06875       ast_string_field_set(cur, description, description);
06876 #ifdef AST_XML_DOCS
06877       cur->docsrc = AST_STATIC_DOC;
06878 #endif
06879    }
06880    if (ast_manager_register_struct(cur)) {
06881       ao2_t_ref(cur, -1, "action object registration failed");
06882       return -1;
06883    }
06884 
06885    ao2_t_ref(cur, -1, "action object registration successful");
06886    return 0;
06887 }

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

Parameters:
hook struct manager_custom_hook object to add

Definition at line 1752 of file manager.c.

References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by create_test_dialplan(), and register_hook().

static int ast_manager_register_struct ( struct manager_action act  )  [static]

Definition at line 6769 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, NULL, ast_category::prev, and manager_action::registered.

Referenced by ast_manager_register2().

06770 {
06771    struct manager_action *cur, *prev = NULL;
06772 
06773    AST_RWLIST_WRLOCK(&actions);
06774    AST_RWLIST_TRAVERSE(&actions, cur, list) {
06775       int ret;
06776 
06777       ret = strcasecmp(cur->action, act->action);
06778       if (ret == 0) {
06779          ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action);
06780          AST_RWLIST_UNLOCK(&actions);
06781          return -1;
06782       }
06783       if (ret > 0) { /* Insert these alphabetically */
06784          prev = cur;
06785          break;
06786       }
06787    }
06788 
06789    ao2_t_ref(act, +1, "action object added to list");
06790    act->registered = 1;
06791    if (prev) {
06792       AST_RWLIST_INSERT_AFTER(&actions, prev, act, list);
06793    } else {
06794       AST_RWLIST_INSERT_HEAD(&actions, act, list);
06795    }
06796 
06797    ast_verb(2, "Manager registered action %s\n", act->action);
06798 
06799    AST_RWLIST_UNLOCK(&actions);
06800 
06801    return 0;
06802 }

struct ast_str* ast_manager_str_from_json_object ( struct ast_json blob,
key_exclusion_cb  exclusion_cb 
) [read]

Convert a JSON object into an AMI compatible string.

Since:
12
Parameters:
blob The JSON blob containing key/value pairs to convert
exclusion_cb A key_exclusion_cb pointer to a function that will exclude keys from the final AMI string
Return values:
A malloc'd ast_str object. Callers of this function should free the returned ast_str object
NULL on error

Definition at line 1681 of file manager.c.

References ast_str_create(), manager_json_to_ast_str(), and NULL.

Referenced by agi_channel_to_ami(), aoc_to_ami(), manager_generic_msg_cb(), multi_user_event_to_ami(), mwi_app_event_cb(), queue_channel_to_ami(), queue_member_to_ami(), and queue_multi_channel_to_ami().

01682 {
01683    struct ast_str *res = ast_str_create(1024);
01684    manager_json_to_ast_str(blob, NULL, &res, exclusion_cb);
01685    return res;
01686 }

int ast_manager_unregister ( const char *  action  ) 

support functions to register/unregister AMI action handlers,

Unregister a registered manager command.

Definition at line 6699 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(), ast_res_pjsip_cleanup_options_handling(), ast_res_pjsip_destroy_configuration(), astdb_atexit(), bridge_cleanup(), data_shutdown(), features_shutdown(), load_module(), local_shutdown(), manager_bridging_cleanup(), manager_shutdown(), message_shutdown(), unload_module(), unload_parking_manager(), and unload_pbx().

06700 {
06701    struct manager_action *cur;
06702 
06703    AST_RWLIST_WRLOCK(&actions);
06704    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) {
06705       if (!strcasecmp(action, cur->action)) {
06706          AST_RWLIST_REMOVE_CURRENT(list);
06707          break;
06708       }
06709    }
06710    AST_RWLIST_TRAVERSE_SAFE_END;
06711    AST_RWLIST_UNLOCK(&actions);
06712 
06713    if (cur) {
06714       /*
06715        * We have removed the action object from the container so we
06716        * are no longer in a hurry.
06717        */
06718       ao2_lock(cur);
06719       cur->registered = 0;
06720       ao2_unlock(cur);
06721 
06722       ao2_t_ref(cur, -1, "action object removed from list");
06723       ast_verb(2, "Manager unregistered action %s\n", action);
06724    }
06725 
06726    return 0;
06727 }

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

Parameters:
hook struct manager_custom_hook object to delete

Definition at line 1760 of file manager.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by register_hook(), unload_module(), and unregister_hook().

void astman_append ( struct mansession s,
const char *  fmt,
  ... 
)

utility functions for creating AMI replies

Definition at line 2820 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, buf, mansession_session::f, mansession::f, NULL, send_string(), and mansession::session.

Referenced by _iax2_show_peers_one(), _sip_show_peer(), _sip_show_peers_one(), _skinny_show_device(), _skinny_show_devices(), _skinny_show_line(), _skinny_show_lines(), action_agents(), action_challenge(), action_command(), action_confbridgelist_item(), action_confbridgelistrooms(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_dahdishowchannels(), action_devicestatelist(), action_events(), action_extensionstate(), action_extensionstatelist(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_listcommands(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_meetmelistrooms(), action_ping(), action_presencestate(), action_presencestatelist(), action_status(), action_waitevent(), ami_outbound_registration_task(), ami_registrations_aor(), ami_show_outbound_registrations(), ami_subscription_detail(), ast_cli_netstats(), astman_append_json(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_response_full(), data_result_manager_output(), do_print(), format_ami_aor_handler(), format_ami_auth_handler(), format_ami_endpoint(), format_ami_endpoint_identify(), format_ami_endpoint_transport(), format_ami_endpoints(), format_ami_resource_lists(), format_contact_status(), generate_status(), manager_append_event_parking_lot_data_cb(), manager_bridge_info(), manager_bridge_tech_list(), manager_data_get(), manager_dbget(), manager_fax_sessions(), manager_fax_sessions_entry(), manager_fax_stats(), manager_iax2_show_netstats(), manager_iax2_show_registry(), manager_jabber_send(), manager_list_voicemail_users(), manager_mixmonitor(), manager_modulecheck(), manager_mute_mixmonitor(), manager_mutestream(), manager_parking_status_all_lots(), manager_parking_status_single_lot(), manager_queue_rule_show(), manager_queues_show(), manager_queues_status(), manager_queues_summary(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_show_registry(), manager_sip_show_peer(), manager_skinny_show_device(), manager_skinny_show_line(), manager_stop_mixmonitor(), mwi_mailbox_get(), send_bridge_info_item_cb(), send_bridge_list_item_cb(), send_manager_peer_status(), session_do(), and spandsp_manager_fax_session().

02821 {
02822    va_list ap;
02823    struct ast_str *buf;
02824 
02825    if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
02826       return;
02827    }
02828 
02829    va_start(ap, fmt);
02830    ast_str_set_va(&buf, 0, fmt, ap);
02831    va_end(ap);
02832 
02833    if (s->f != NULL || s->session->f != NULL) {
02834       send_string(s, ast_str_buffer(buf));
02835    } else {
02836       ast_verbose("fd == -1 in astman_append, should not happen\n");
02837    }
02838 }

static void astman_append_json ( struct mansession s,
const char *  str 
) [static]

Definition at line 3437 of file manager.c.

References ast_alloca, astman_append(), buf, and json_escape().

Referenced by action_getconfigjson().

03438 {
03439    char *buf;
03440 
03441    buf = ast_alloca(2 * strlen(str) + 1);
03442    json_escape(buf, str);
03443    astman_append(s, "%s", buf);
03444 }

const char* astman_get_header ( const struct message m,
char *  var 
)

Return the first matching variable from an array.

Get header from mananger transaction.

Note:
This is the legacy function and is implemented in therms of __astman_get_header().

Never returns NULL.

Definition at line 2608 of file manager.c.

References __astman_get_header(), and GET_HEADER_FIRST_MATCH.

Referenced by _sip_qualify_peer(), _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_blind_transfer(), 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_devicestatelist(), action_events(), action_extensionstate(), action_extensionstatelist(), 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_messagesend(), action_mute_unmute_helper(), action_originate(), action_ping(), action_presencestate(), action_presencestatelist(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), action_waitevent(), ami_register(), ami_show_endpoint(), ami_show_endpoints(), ami_show_outbound_registrations(), ami_show_registrations(), ami_show_resource_lists(), ami_show_subscriptions_inbound(), ami_show_subscriptions_outbound(), ami_sip_qualify(), ami_unregister(), aocmessage_get_unit_entry(), ast_hook_send_action(), astman_send_list_complete_start(), astman_send_response_full(), authenticate(), change_monitor_action(), controlplayback_manager(), do_pause_or_unpause(), handle_manager_bridge_tech_suspend(), handle_updates(), manager_add_queue_member(), manager_bridge_destroy(), manager_bridge_info(), manager_bridge_kick(), manager_bridge_tech_list(), manager_bridges_list(), manager_data_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_dialplan_extension_add(), manager_dialplan_extension_remove(), manager_fax_session(), manager_fax_sessions(), manager_fax_stats(), 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_notify(), manager_optimize_away(), manager_park(), manager_parking_lot_list(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_member_ringinuse(), manager_queue_reload(), manager_queue_reset(), manager_queue_rule_show(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), manager_show_dialplan(), manager_show_registry(), manager_sip_peer_status(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_line(), manager_stop_mixmonitor(), manager_voicemail_refresh(), meetmemute(), mwi_mailbox_delete(), mwi_mailbox_get(), mwi_mailbox_update(), process_message(), start_monitor_action(), and stop_monitor_action().

02609 {
02610    return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH);
02611 }

struct ast_variable* astman_get_variables ( const struct message m  )  [read]

Get a linked list of the Variable: headers.

Note:
Order of variables is reversed from the order they are specified in the manager message

Definition at line 2666 of file manager.c.

References astman_get_variables_order(), and ORDER_REVERSE.

Referenced by action_originate().

02667 {
02668    return astman_get_variables_order(m, ORDER_REVERSE);
02669 }

struct ast_variable* astman_get_variables_order ( const struct message m,
enum variable_orders  order 
) [read]

Get a linked list of the Variable: headers with order specified.

Definition at line 2671 of file manager.c.

References ast_variables_reverse(), message::hdrcount, message::headers, man_do_variable_value(), NULL, and ORDER_NATURAL.

Referenced by action_messagesend(), astman_get_variables(), manager_notify_endpoint(), manager_notify_uri(), and manager_sipnotify().

02673 {
02674    int varlen;
02675    int x;
02676    struct ast_variable *head = NULL;
02677 
02678    static const char var_hdr[] = "Variable:";
02679 
02680    /* Process all "Variable:" headers. */
02681    varlen = strlen(var_hdr);
02682    for (x = 0; x < m->hdrcount; x++) {
02683       if (strncasecmp(var_hdr, m->headers[x], varlen)) {
02684          continue;
02685       }
02686       head = man_do_variable_value(head, m->headers[x] + varlen);
02687    }
02688 
02689    if (order == ORDER_NATURAL) {
02690       head = ast_variables_reverse(head);
02691    }
02692 
02693    return head;
02694 }

void astman_send_ack ( struct mansession s,
const struct message m,
char *  msg 
)

Send ack in manager transaction.

Definition at line 2912 of file manager.c.

References astman_send_response_full(), and NULL.

Referenced by _sip_qualify_peer(), action_add_agi_cmd(), action_agent_logoff(), action_aocmessage(), action_atxfer(), action_blind_transfer(), action_bridge(), action_confbridgekick(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_filter(), action_hangup(), action_lock_unlock_helper(), action_loggerrotate(), action_login(), action_messagesend(), action_mute_unmute_helper(), action_originate(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), ami_register(), ami_sip_qualify(), ami_unregister(), change_monitor_action(), controlplayback_manager(), do_pause_or_unpause(), handle_manager_bridge_tech_suspend(), manager_add_queue_member(), manager_bridge_destroy(), manager_bridge_kick(), manager_dbdel(), manager_dbdeltree(), manager_dbput(), manager_dialplan_extension_add(), manager_dialplan_extension_remove(), manager_fax_session(), manager_fax_stats(), manager_jabber_send(), manager_list_voicemail_users(), manager_moduleload(), manager_notify_endpoint(), manager_notify_uri(), manager_optimize_away(), manager_park_bridged(), manager_park_unbridged(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_member_ringinuse(), manager_queue_reload(), manager_queue_reset(), manager_remove_queue_member(), manager_sipnotify(), manager_voicemail_refresh(), meetmemute(), mwi_mailbox_delete(), mwi_mailbox_update(), start_monitor_action(), and stop_monitor_action().

02913 {
02914    astman_send_response_full(s, m, "Success", msg, NULL);
02915 }

void astman_send_error ( struct mansession s,
const struct message m,
char *  error 
)

Send error in manager transaction.

Definition at line 2884 of file manager.c.

References astman_send_response_full(), and NULL.

Referenced by _sip_qualify_peer(), _sip_show_peer(), action_add_agi_cmd(), action_agent_logoff(), action_aocmessage(), action_atxfer(), action_blind_transfer(), 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_devicestatelist(), action_events(), action_extensionstate(), action_extensionstatelist(), action_filter(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_lock_unlock_helper(), action_loggerrotate(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_meetmelistrooms(), action_messagesend(), action_mute_unmute_helper(), action_originate(), action_presencestate(), action_presencestatelist(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), ami_register(), ami_show_endpoints(), ami_show_outbound_registrations(), ami_show_resource_lists(), ami_sip_qualify(), ami_unregister(), change_monitor_action(), controlplayback_manager(), do_message(), do_pause_or_unpause(), handle_manager_bridge_tech_suspend(), handle_parse_error(), manager_add_queue_member(), manager_bridge_destroy(), manager_bridge_info(), manager_bridge_kick(), manager_bridge_tech_list(), manager_bridges_list(), manager_data_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_dialplan_extension_add(), manager_dialplan_extension_remove(), manager_fax_session(), manager_jabber_send(), manager_mixmonitor(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_notify(), manager_notify_endpoint(), manager_notify_uri(), manager_optimize_away(), manager_park(), manager_park_bridged(), manager_park_unbridged(), manager_parking_lot_list(), manager_parking_status_all_lots(), manager_parking_status_single_lot(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_member_ringinuse(), manager_queue_reload(), manager_queue_reset(), manager_remove_queue_member(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_sip_peer_status(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_line(), manager_stop_mixmonitor(), meetmemute(), mwi_mailbox_delete(), mwi_mailbox_get(), mwi_mailbox_update(), process_message(), start_monitor_action(), and stop_monitor_action().

02885 {
02886    astman_send_response_full(s, m, "Error", error, NULL);
02887 }

void astman_send_error_va ( struct mansession s,
const struct message m,
const char *  fmt,
  ... 
)

Send error in manager transaction (with va_args support).

Definition at line 2889 of file manager.c.

References ast_str_buffer(), ast_str_set_va(), ast_str_thread_get(), ast_strdupa, astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE, astman_send_response_full(), buf, and NULL.

Referenced by action_hangup(), action_originate(), action_presencestate(), ami_show_endpoint(), ast_sip_create_ami_event(), format_ami_endpoint_transport(), manager_notify_endpoint(), mwi_mailbox_delete(), mwi_mailbox_get(), and mwi_mailbox_update().

02890 {
02891    va_list ap;
02892    struct ast_str *buf;
02893    char *msg;
02894 
02895    if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
02896       return;
02897    }
02898 
02899    va_start(ap, fmt);
02900    ast_str_set_va(&buf, 0, fmt, ap);
02901    va_end(ap);
02902 
02903    /* astman_append will use the same underlying buffer, so copy the message out
02904     * before sending the response */
02905    msg = ast_str_buffer(buf);
02906    if (msg) {
02907       msg = ast_strdupa(msg);
02908    }
02909    astman_send_response_full(s, m, "Error", msg, NULL);
02910 }

void astman_send_list_complete_end ( struct mansession s  ) 

End the list complete event.

Since:
13.2.0
Parameters:
s - AMI session control struct.
Note:
You need to call astman_send_list_complete_start() to start the AMI list completion event.

Between calling astman_send_list_complete_start() and astman_send_list_complete_end() you can add additonal headers using astman_append().

Returns:
Nothing

Definition at line 2941 of file manager.c.

References astman_append().

Referenced by action_agents(), action_confbridgelist(), action_confbridgelistrooms(), action_coreshowchannels(), action_dahdishowchannels(), action_devicestatelist(), action_extensionstatelist(), action_hangup(), action_meetmelist(), action_meetmelistrooms(), action_presencestatelist(), action_status(), ami_show_endpoint(), ami_show_endpoints(), ami_show_outbound_registrations(), ami_show_registrations(), ami_show_resource_lists(), ami_show_subscriptions_inbound(), ami_show_subscriptions_outbound(), manager_bridge_info(), manager_bridge_tech_list(), manager_bridges_list(), manager_dbget(), manager_fax_sessions(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_list_voicemail_users(), manager_parking_lot_list(), manager_parking_status_all_lots(), manager_parking_status_single_lot(), manager_queues_status(), manager_queues_summary(), manager_show_dialplan(), manager_show_registry(), manager_sip_peer_status(), manager_sip_show_peers(), manager_skinny_show_devices(), manager_skinny_show_lines(), and mwi_mailbox_get().

02942 {
02943    astman_append(s, "\r\n");
02944 }

void astman_send_list_complete_start ( struct mansession s,
const struct message m,
const char *  event_name,
int  count 
)

Start the list complete event.

Since:
13.2.0
Parameters:
s - AMI session control struct.
m - AMI action request that started the list.
event_name - AMI list complete event name.
count - Number of items in the list.
Note:
You need to call astman_send_list_complete_end() to end the AMI list completion event.

Between calling astman_send_list_complete_start() and astman_send_list_complete_end() you can add additonal headers using astman_append().

Returns:
Nothing

Definition at line 2927 of file manager.c.

References ast_strlen_zero, astman_append(), and astman_get_header().

Referenced by action_agents(), action_confbridgelist(), action_confbridgelistrooms(), action_coreshowchannels(), action_dahdishowchannels(), action_devicestatelist(), action_extensionstatelist(), action_hangup(), action_meetmelist(), action_meetmelistrooms(), action_presencestatelist(), action_status(), ami_show_endpoint(), ami_show_endpoints(), ami_show_outbound_registrations(), ami_show_registrations(), ami_show_resource_lists(), ami_show_subscriptions_inbound(), ami_show_subscriptions_outbound(), manager_bridge_info(), manager_bridge_tech_list(), manager_bridges_list(), manager_dbget(), manager_fax_sessions(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_list_voicemail_users(), manager_parking_lot_list(), manager_parking_status_all_lots(), manager_parking_status_single_lot(), manager_queues_status(), manager_queues_summary(), manager_show_dialplan(), manager_show_registry(), manager_sip_peer_status(), manager_sip_show_peers(), manager_skinny_show_devices(), manager_skinny_show_lines(), and mwi_mailbox_get().

02928 {
02929    const char *id = astman_get_header(m, "ActionID");
02930 
02931    astman_append(s, "Event: %s\r\n", event_name);
02932    if (!ast_strlen_zero(id)) {
02933       astman_append(s, "ActionID: %s\r\n", id);
02934    }
02935    astman_append(s,
02936       "EventList: Complete\r\n"
02937       "ListItems: %d\r\n",
02938       count);
02939 }

void astman_send_listack ( struct mansession s,
const struct message m,
char *  msg,
char *  listflag 
)

Send ack in manager transaction to begin a list.

Parameters:
s - AMI session control struct.
m - AMI action request that started the list.
msg - Message contents describing the list to follow.
listflag - Should always be set to "start".
Note:
You need to call astman_send_list_complete_start() and astman_send_list_complete_end() to send the AMI list completion event.
Returns:
Nothing

Definition at line 2922 of file manager.c.

References astman_send_response_full().

Referenced by action_agents(), action_confbridgelist(), action_confbridgelistrooms(), action_coreshowchannels(), action_dahdishowchannels(), action_devicestatelist(), action_extensionstatelist(), action_hangup(), action_meetmelist(), action_meetmelistrooms(), action_presencestatelist(), action_status(), ami_show_endpoint(), ami_show_endpoints(), ami_show_outbound_registrations(), ami_show_registrations(), ami_show_resource_lists(), ami_show_subscriptions_inbound(), ami_show_subscriptions_outbound(), manager_bridge_info(), manager_bridge_tech_list(), manager_bridges_list(), manager_dbget(), manager_dpsendack(), manager_fax_sessions(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_list_voicemail_users(), manager_parking_lot_list(), manager_parking_status_all_lots(), manager_parking_status_single_lot(), manager_queues_status(), manager_queues_summary(), manager_show_registry(), manager_sip_peer_status(), manager_sip_show_peers(), manager_skinny_show_devices(), manager_skinny_show_lines(), and mwi_mailbox_get().

02923 {
02924    astman_send_response_full(s, m, "Success", msg, listflag);
02925 }

void astman_send_response ( struct mansession s,
const struct message m,
char *  resp,
char *  msg 
)

Send response in manager transaction.

Definition at line 2879 of file manager.c.

References astman_send_response_full(), and NULL.

Referenced by action_logoff(), and action_waitevent().

02880 {
02881    astman_send_response_full(s, m, resp, msg, NULL);
02882 }

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 2859 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_error_va(), astman_send_listack(), astman_send_response(), and astman_start_ack().

02860 {
02861    const char *id = astman_get_header(m, "ActionID");
02862 
02863    astman_append(s, "Response: %s\r\n", resp);
02864    if (!ast_strlen_zero(id)) {
02865       astman_append(s, "ActionID: %s\r\n", id);
02866    }
02867    if (listflag) {
02868       astman_append(s, "EventList: %s\r\n", listflag);   /* Start, complete, cancelled */
02869    }
02870    if (msg == MSG_MOREDATA) {
02871       return;
02872    } else if (msg) {
02873       astman_append(s, "Message: %s\r\n\r\n", msg);
02874    } else {
02875       astman_append(s, "\r\n");
02876    }
02877 }

static void astman_start_ack ( struct mansession s,
const struct message m 
) [static]

static int authenticate ( struct mansession s,
const struct message m 
) [static]

Definition at line 3201 of file manager.c.

References ast_manager_user::acl, mansession_session::addr, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_t_link, ao2_t_ref, ast_apply_acl(), ast_copy_string(), ast_debug, ast_log, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_SENSE_DENY, ast_sockaddr_stringify_addr(), ast_strlen_zero, ast_tvnow(), ast_variables_dup(), astman_get_header(), mansession_session::blackfilters, ast_manager_user::blackfilters, mansession_session::challenge, mansession_session::chanvars, ast_manager_user::chanvars, error(), get_manager_by_name_locked(), len(), LOG_NOTICE, MD5Final(), MD5Init(), MD5Update(), NULL, password, 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::username, mansession_session::whitefilters, ast_manager_user::whitefilters, ast_manager_user::writeperm, mansession_session::writeperm, ast_manager_user::writetimeout, and mansession_session::writetimeout.

03202 {
03203    const char *username = astman_get_header(m, "Username");
03204    const char *password = astman_get_header(m, "Secret");
03205    int error = -1;
03206    struct ast_manager_user *user = NULL;
03207    regex_t *regex_filter;
03208    struct ao2_iterator filter_iter;
03209 
03210    if (ast_strlen_zero(username)) { /* missing username */
03211       return -1;
03212    }
03213 
03214    /* locate user in locked state */
03215    AST_RWLIST_WRLOCK(&users);
03216 
03217    if (!(user = get_manager_by_name_locked(username))) {
03218       report_invalid_user(s, username);
03219       ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_sockaddr_stringify_addr(&s->session->addr), username);
03220    } else if (user->acl && (ast_apply_acl(user->acl, &s->session->addr, "Manager User ACL: ") == AST_SENSE_DENY)) {
03221       report_failed_acl(s, username);
03222       ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_sockaddr_stringify_addr(&s->session->addr), username);
03223    } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) {
03224       const char *key = astman_get_header(m, "Key");
03225       if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) {
03226          int x;
03227          int len = 0;
03228          char md5key[256] = "";
03229          struct MD5Context md5;
03230          unsigned char digest[16];
03231 
03232          MD5Init(&md5);
03233          MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge));
03234          MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret));
03235          MD5Final(digest, &md5);
03236          for (x = 0; x < 16; x++)
03237             len += sprintf(md5key + len, "%02hhx", digest[x]);
03238          if (!strcmp(md5key, key)) {
03239             error = 0;
03240          } else {
03241             report_failed_challenge_response(s, key, md5key);
03242          }
03243       } else {
03244          ast_debug(1, "MD5 authentication is not possible.  challenge: '%s'\n",
03245             S_OR(s->session->challenge, ""));
03246       }
03247    } else if (user->secret) {
03248       if (!strcmp(password, user->secret)) {
03249          error = 0;
03250       } else {
03251          report_inval_password(s, username);
03252       }
03253    }
03254 
03255    if (error) {
03256       ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_sockaddr_stringify_addr(&s->session->addr), username);
03257       AST_RWLIST_UNLOCK(&users);
03258       return -1;
03259    }
03260 
03261    /* auth complete */
03262 
03263    /* All of the user parameters are copied to the session so that in the event
03264    * of a reload and a configuration change, the session parameters are not
03265    * changed. */
03266    ast_copy_string(s->session->username, username, sizeof(s->session->username));
03267    s->session->readperm = user->readperm;
03268    s->session->writeperm = user->writeperm;
03269    s->session->writetimeout = user->writetimeout;
03270    if (user->chanvars) {
03271       s->session->chanvars = ast_variables_dup(user->chanvars);
03272    }
03273 
03274    filter_iter = ao2_iterator_init(user->whitefilters, 0);
03275    while ((regex_filter = ao2_iterator_next(&filter_iter))) {
03276       ao2_t_link(s->session->whitefilters, regex_filter, "add white user filter to session");
03277       ao2_t_ref(regex_filter, -1, "remove iterator ref");
03278    }
03279    ao2_iterator_destroy(&filter_iter);
03280 
03281    filter_iter = ao2_iterator_init(user->blackfilters, 0);
03282    while ((regex_filter = ao2_iterator_next(&filter_iter))) {
03283       ao2_t_link(s->session->blackfilters, regex_filter, "add black user filter to session");
03284       ao2_t_ref(regex_filter, -1, "remove iterator ref");
03285    }
03286    ao2_iterator_destroy(&filter_iter);
03287 
03288    s->session->sessionstart = time(NULL);
03289    s->session->sessionstart_tv = ast_tvnow();
03290    set_eventmask(s, astman_get_header(m, "Events"));
03291 
03292    report_auth_success(s);
03293 
03294    AST_RWLIST_UNLOCK(&users);
03295    return 0;
03296 }

static const char* authority_to_str ( int  authority,
struct ast_str **  res 
) [static]

Convert authority code to a list of options. Note that the EVENT_FLAG_ALL authority will always be returned.

Definition at line 1902 of file manager.c.

References ARRAY_LEN, ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_strlen(), EVENT_FLAG_SHUTDOWN, and perms.

Referenced by __ast_manager_event_multichan(), action_listcommands(), action_login(), and handle_showmancmd().

01903 {
01904    int i;
01905    char *sep = "";
01906 
01907    ast_str_reset(*res);
01908    if (authority != EVENT_FLAG_SHUTDOWN) {
01909       for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
01910          if (authority & perms[i].num) {
01911             ast_str_append(res, 0, "%s%s", sep, perms[i].label);
01912             sep = ",";
01913          }
01914       }
01915    }
01916 
01917    if (ast_str_strlen(*res) == 0) {
01918       /* replace empty string with something sensible */
01919       ast_str_append(res, 0, "<none>");
01920    }
01921 
01922    return ast_str_buffer(*res);
01923 }

static int blackfilter_cmp_fn ( void *  obj,
void *  arg,
void *  data,
int  flags 
) [static]

Definition at line 5598 of file manager.c.

References CMP_MATCH, CMP_STOP, NULL, and result.

Referenced by match_filter().

05599 {
05600    regex_t *regex_filter = obj;
05601    const char *eventdata = arg;
05602    int *result = data;
05603 
05604    if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
05605       *result = 0;
05606       return (CMP_MATCH | CMP_STOP);
05607    }
05608 
05609    *result = 1;
05610    return 0;
05611 }

static struct mansession_session* build_mansession ( const struct ast_sockaddr addr  )  [static, read]

Allocate manager session structure and add it to the list of sessions.

Definition at line 2049 of file manager.c.

References mansession_session::addr, ao2_alloc, ao2_container_alloc, ao2_global_obj_ref, ao2_link, ao2_ref, AST_PTHREADT_NULL, ast_sockaddr_copy(), mansession_session::blackfilters, mansession_session::fd, NULL, mansession_session::send_events, session_destructor(), mansession_session::waiting_thread, mansession_session::whitefilters, and mansession_session::writetimeout.

Referenced by auth_http_callback(), generic_http_callback(), and session_do().

02050 {
02051    struct ao2_container *sessions;
02052    struct mansession_session *newsession;
02053 
02054    newsession = ao2_alloc(sizeof(*newsession), session_destructor);
02055    if (!newsession) {
02056       return NULL;
02057    }
02058 
02059    newsession->whitefilters = ao2_container_alloc(1, NULL, NULL);
02060    newsession->blackfilters = ao2_container_alloc(1, NULL, NULL);
02061    if (!newsession->whitefilters || !newsession->blackfilters) {
02062       ao2_ref(newsession, -1);
02063       return NULL;
02064    }
02065 
02066    newsession->fd = -1;
02067    newsession->waiting_thread = AST_PTHREADT_NULL;
02068    newsession->writetimeout = 100;
02069    newsession->send_events = -1;
02070    ast_sockaddr_copy(&newsession->addr, addr);
02071 
02072    sessions = ao2_global_obj_ref(mgr_sessions);
02073    if (sessions) {
02074       ao2_link(sessions, newsession);
02075       ao2_ref(sessions, -1);
02076    }
02077 
02078    return newsession;
02079 }

static int check_blacklist ( const char *  cmd  )  [static]

Definition at line 4803 of file manager.c.

References ARRAY_LEN, AST_MAX_CMD_LEN, ast_strdupa, ast_strip(), ast_strlen_zero, command_blacklist, match(), MAX_BLACKLIST_CMD_LEN, NULL, strsep(), and words.

Referenced by action_command().

04804 {
04805    char *cmd_copy, *cur_cmd;
04806    char *cmd_words[AST_MAX_CMD_LEN] = { NULL, };
04807    int i;
04808 
04809    cmd_copy = ast_strdupa(cmd);
04810    for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) {
04811       cur_cmd = ast_strip(cur_cmd);
04812       if (ast_strlen_zero(cur_cmd)) {
04813          i--;
04814          continue;
04815       }
04816 
04817       cmd_words[i] = cur_cmd;
04818    }
04819 
04820    for (i = 0; i < ARRAY_LEN(command_blacklist); i++) {
04821       int j, match = 1;
04822 
04823       for (j = 0; command_blacklist[i].words[j]; j++) {
04824          if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) {
04825             match = 0;
04826             break;
04827          }
04828       }
04829 
04830       if (match) {
04831          return 1;
04832       }
04833    }
04834 
04835    return 0;
04836 }

int check_manager_enabled ( void   ) 

Check if AMI is enabled.

Definition at line 1767 of file manager.c.

Referenced by handle_show_settings().

01768 {
01769    return manager_enabled;
01770 }

static int check_manager_session_inuse ( const char *  name  )  [static]

Definition at line 2101 of file manager.c.

References ao2_find, ao2_global_obj_ref, ao2_ref, mansession_session::inuse, session, and unref_mansession().

Referenced by process_message().

02102 {
02103    struct ao2_container *sessions;
02104    struct mansession_session *session;
02105    int inuse = 0;
02106 
02107    sessions = ao2_global_obj_ref(mgr_sessions);
02108    if (sessions) {
02109       session = ao2_find(sessions, (char *) name, 0);
02110       ao2_ref(sessions, -1);
02111       if (session) {
02112          unref_mansession(session);
02113          inuse = 1;
02114       }
02115    }
02116    return inuse;
02117 }

int check_webmanager_enabled ( void   ) 

Check if AMI/HTTP is enabled.

Definition at line 1772 of file manager.c.

Referenced by action_coresettings(), and handle_show_settings().

01773 {
01774    return (webmanager_enabled && manager_enabled);
01775 }

static void destroy_fast_originate_helper ( struct fast_originate_helper doomed  )  [static]

Definition at line 4943 of file manager.c.

References ao2_cleanup, 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().

04944 {
04945    ao2_cleanup(doomed->cap);
04946    ast_variables_destroy(doomed->vars);
04947    ast_string_field_free_memory(doomed);
04948    ast_free(doomed);
04949 }

static int do_message ( struct mansession s  )  [static]

Definition at line 6328 of file manager.c.

References mansession_session::addr, ARRAY_LEN, ast_free, ast_log, ast_sockaddr_stringify_addr(), ast_strdup, ast_strlen_zero, ast_verb, astman_send_error(), mansession_session::authenticated, mansession_session::authstart, errno, get_input(), handle_parse_error(), message::hdrcount, message::headers, mansession_session::inbuf, LOG_ERROR, mansession_lock(), mansession_unlock(), MESSAGE_LINE_TOO_LONG, MESSAGE_OKAY, mansession::parsing, process_events(), process_message(), and mansession::session.

Referenced by session_do().

06329 {
06330    struct message m = { 0 };
06331    char header_buf[sizeof(s->session->inbuf)] = { '\0' };
06332    int res;
06333    int idx;
06334    int hdr_loss;
06335    time_t now;
06336 
06337    hdr_loss = 0;
06338    for (;;) {
06339       /* Check if any events are pending and do them if needed */
06340       if (process_events(s)) {
06341          res = -1;
06342          break;
06343       }
06344       res = get_input(s, header_buf);
06345       if (res == 0) {
06346          /* No input line received. */
06347          if (!s->session->authenticated) {
06348             if (time(&now) == -1) {
06349                ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
06350                res = -1;
06351                break;
06352             }
06353 
06354             if (now - s->session->authstart > authtimeout) {
06355                if (displayconnects) {
06356                   ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_sockaddr_stringify_addr(&s->session->addr), authtimeout);
06357                }
06358                res = -1;
06359                break;
06360             }
06361          }
06362          continue;
06363       } else if (res > 0) {
06364          /* Input line received. */
06365          if (ast_strlen_zero(header_buf)) {
06366             if (hdr_loss) {
06367                mansession_lock(s);
06368                astman_send_error(s, &m, "Too many lines in message or allocation failure");
06369                mansession_unlock(s);
06370                res = 0;
06371             } else {
06372                switch (s->parsing) {
06373                case MESSAGE_OKAY:
06374                   res = process_message(s, &m) ? -1 : 0;
06375                   break;
06376                case MESSAGE_LINE_TOO_LONG:
06377                   handle_parse_error(s, &m, "Failed to parse message: line too long");
06378                   res = 0;
06379                   break;
06380                }
06381             }
06382             break;
06383          } else if (m.hdrcount < ARRAY_LEN(m.headers)) {
06384             m.headers[m.hdrcount] = ast_strdup(header_buf);
06385             if (!m.headers[m.hdrcount]) {
06386                /* Allocation failure. */
06387                hdr_loss = 1;
06388             } else {
06389                ++m.hdrcount;
06390             }
06391          } else {
06392             /* Too many lines in message. */
06393             hdr_loss = 1;
06394          }
06395       } else {
06396          /* Input error. */
06397          break;
06398       }
06399    }
06400 
06401    /* Free AMI request headers. */
06402    for (idx = 0; idx < m.hdrcount; ++idx) {
06403       ast_free((void *) m.headers[idx]);
06404    }
06405    return res;
06406 }

static void event_filter_destructor ( void *  obj  )  [static]

Definition at line 2010 of file manager.c.

Referenced by manager_add_filter().

02011 {
02012    regex_t *regex_filter = obj;
02013    regfree(regex_filter);
02014 }

static void* fast_originate ( void *  data  )  [static]

Definition at line 4951 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_channel_unref, ast_manager_event_multichan, ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_strlen_zero, fast_originate_helper::cap, fast_originate_helper::channelid, fast_originate_helper::cid_name, fast_originate_helper::cid_num, fast_originate_helper::context, fast_originate_helper::data, destroy_fast_originate_helper(), fast_originate_helper::early_media, EVENT_FLAG_CALL, fast_originate_helper::exten, fast_originate_helper::idtext, in, NULL, fast_originate_helper::otherchannelid, fast_originate_helper::priority, S_OR, fast_originate_helper::tech, fast_originate_helper::timeout, and fast_originate_helper::vars.

Referenced by action_originate().

04952 {
04953    struct fast_originate_helper *in = data;
04954    int res;
04955    int reason = 0;
04956    struct ast_channel *chan = NULL, *chans[1];
04957    char requested_channel[AST_CHANNEL_NAME];
04958    struct ast_assigned_ids assignedids = {
04959       .uniqueid = in->channelid,
04960       .uniqueid2 = in->otherchannelid
04961    };
04962 
04963    if (!ast_strlen_zero(in->app)) {
04964       res = ast_pbx_outgoing_app(in->tech, in->cap, in->data,
04965          in->timeout, in->app, in->appdata, &reason, 1,
04966          S_OR(in->cid_num, NULL),
04967          S_OR(in->cid_name, NULL),
04968          in->vars, in->account, &chan, &assignedids);
04969    } else {
04970       res = ast_pbx_outgoing_exten(in->tech, in->cap, in->data,
04971          in->timeout, in->context, in->exten, in->priority, &reason, 1,
04972          S_OR(in->cid_num, NULL),
04973          S_OR(in->cid_name, NULL),
04974          in->vars, in->account, &chan, in->early_media, &assignedids);
04975    }
04976 
04977    if (!chan) {
04978       snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);
04979    }
04980    /* Tell the manager what happened with the channel */
04981    chans[0] = chan;
04982    ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans,
04983       "%s"
04984       "Response: %s\r\n"
04985       "Channel: %s\r\n"
04986       "Context: %s\r\n"
04987       "Exten: %s\r\n"
04988       "Reason: %d\r\n"
04989       "Uniqueid: %s\r\n"
04990       "CallerIDNum: %s\r\n"
04991       "CallerIDName: %s\r\n",
04992       in->idtext, res ? "Failure" : "Success",
04993       chan ? ast_channel_name(chan) : requested_channel, in->context, in->exten, reason,
04994       chan ? ast_channel_uniqueid(chan) : "<null>",
04995       S_OR(in->cid_num, "<unknown>"),
04996       S_OR(in->cid_name, "<unknown>")
04997       );
04998 
04999    /* Locked and ref'd by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
05000    if (chan) {
05001       ast_channel_unlock(chan);
05002       ast_channel_unref(chan);
05003    }
05004    destroy_fast_originate_helper(in);
05005    return NULL;
05006 }

static int function_capable_string_allowed_with_auths ( const char *  evaluating,
int  writepermlist 
) [static]

Checks to see if a string which can be used to evaluate functions should be rejected.

Definition at line 1864 of file manager.c.

References EVENT_FLAG_SYSTEM.

Referenced by action_getvar(), and action_status().

01865 {
01866    if (!(writepermlist & EVENT_FLAG_SYSTEM)
01867       && (
01868          strstr(evaluating, "SHELL") ||       /* NoOp(${SHELL(rm -rf /)})  */
01869          strstr(evaluating, "EVAL")           /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
01870       )) {
01871       return 0;
01872    }
01873    return 1;
01874 }

static void generate_status ( struct mansession s,
struct ast_channel chan,
char **  vars,
int  varc,
int  all_variables,
char *  id_text,
int *  count 
) [static]

Definition at line 4330 of file manager.c.

References ao2_cleanup, ast_channel_appl(), ast_channel_callgroup(), ast_channel_connected_effective_id(), ast_channel_creationtime(), ast_channel_data(), ast_channel_dialed(), ast_channel_get_bridge(), ast_channel_linkedid(), ast_channel_nativeformats(), ast_channel_pickupgroup(), ast_channel_readformat(), ast_channel_readtrans(), ast_channel_snapshot_get_latest(), ast_channel_tech(), ast_channel_uniqueid(), ast_channel_varshead(), ast_channel_whentohangup(), ast_channel_writeformat(), ast_channel_writetrans(), ast_format_cap_get_names(), ast_format_get_name(), ast_free, ast_func_read(), AST_LIST_TRAVERSE, ast_manager_build_channel_state_string(), ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_translate_path_to_str(), ast_tvdiff_sec(), ast_tvnow(), ast_var_name(), ast_var_value(), astman_append(), ast_party_id::name, NULL, ast_party_id::number, pbx_retrieve_variable(), RAII_VAR, S_COR, S_OR, ast_party_name::str, ast_party_number::str, ast_party_dialed::str, type, ast_bridge::uniqueid, ast_party_name::valid, and ast_party_number::valid.

Referenced by action_status().

04331 {
04332    struct timeval now;
04333    long elapsed_seconds;
04334    struct ast_bridge *bridge;
04335    RAII_VAR(struct ast_str *, variable_str, NULL, ast_free);
04336    struct ast_str *write_transpath = ast_str_alloca(256);
04337    struct ast_str *read_transpath = ast_str_alloca(256);
04338    struct ast_str *codec_buf = ast_str_alloca(128);
04339    struct ast_party_id effective_id;
04340    int i;
04341    RAII_VAR(struct ast_channel_snapshot *, snapshot,
04342       ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan)),
04343       ao2_cleanup);
04344    RAII_VAR(struct ast_str *, snapshot_str, NULL, ast_free);
04345 
04346    if (!snapshot) {
04347       return;
04348    }
04349 
04350    snapshot_str = ast_manager_build_channel_state_string(snapshot);
04351    if (!snapshot_str) {
04352       return;
04353    }
04354 
04355    if (all_variables) {
04356       variable_str = ast_str_create(2048);
04357    } else {
04358       variable_str = ast_str_create(1024);
04359    }
04360    if (!variable_str) {
04361       return;
04362    }
04363 
04364    now = ast_tvnow();
04365    elapsed_seconds = ast_tvdiff_sec(now, ast_channel_creationtime(chan));
04366 
04367    /* Even if all_variables has been specified, explicitly requested variables
04368     * may be global variables or dialplan functions */
04369    for (i = 0; i < varc; i++) {
04370       char valbuf[512], *ret = NULL;
04371 
04372       if (vars[i][strlen(vars[i]) - 1] == ')') {
04373          if (ast_func_read(chan, vars[i], valbuf, sizeof(valbuf)) < 0) {
04374             valbuf[0] = '\0';
04375          }
04376          ret = valbuf;
04377       } else {
04378          pbx_retrieve_variable(chan, vars[i], &ret, valbuf, sizeof(valbuf), NULL);
04379       }
04380 
04381       ast_str_append(&variable_str, 0, "Variable: %s=%s\r\n", vars[i], ret);
04382    }
04383 
04384    /* Walk all channel variables and add them */
04385    if (all_variables) {
04386       struct ast_var_t *variables;
04387 
04388       AST_LIST_TRAVERSE(ast_channel_varshead(chan), variables, entries) {
04389          ast_str_append(&variable_str, 0, "Variable: %s=%s\r\n",
04390             ast_var_name(variables), ast_var_value(variables));
04391       }
04392    }
04393 
04394    bridge = ast_channel_get_bridge(chan);
04395    effective_id = ast_channel_connected_effective_id(chan);
04396 
04397    astman_append(s,
04398       "Event: Status\r\n"
04399       "Privilege: Call\r\n"
04400       "%s"
04401       "Type: %s\r\n"
04402       "DNID: %s\r\n"
04403       "EffectiveConnectedLineNum: %s\r\n"
04404       "EffectiveConnectedLineName: %s\r\n"
04405       "TimeToHangup: %ld\r\n"
04406       "BridgeID: %s\r\n"
04407       "Linkedid: %s\r\n"
04408       "Application: %s\r\n"
04409       "Data: %s\r\n"
04410       "Nativeformats: %s\r\n"
04411       "Readformat: %s\r\n"
04412       "Readtrans: %s\r\n"
04413       "Writeformat: %s\r\n"
04414       "Writetrans: %s\r\n"
04415       "Callgroup: %llu\r\n"
04416       "Pickupgroup: %llu\r\n"
04417       "Seconds: %ld\r\n"
04418       "%s"
04419       "%s"
04420       "\r\n",
04421       ast_str_buffer(snapshot_str),
04422       ast_channel_tech(chan)->type,
04423       S_OR(ast_channel_dialed(chan)->number.str, ""),
04424       S_COR(effective_id.number.valid, effective_id.number.str, "<unknown>"),
04425       S_COR(effective_id.name.valid, effective_id.name.str, "<unknown>"),
04426       (long)ast_channel_whentohangup(chan)->tv_sec,
04427       bridge ? bridge->uniqueid : "",
04428       ast_channel_linkedid(chan),
04429       ast_channel_appl(chan),
04430       ast_channel_data(chan),
04431       ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf),
04432       ast_format_get_name(ast_channel_readformat(chan)),
04433       ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath),
04434       ast_format_get_name(ast_channel_writeformat(chan)),
04435       ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath),
04436       ast_channel_callgroup(chan),
04437       ast_channel_pickupgroup(chan),
04438       (long)elapsed_seconds,
04439       ast_str_buffer(variable_str),
04440       id_text);
04441    ++*count;
04442 
04443    ao2_cleanup(bridge);
04444 }

static int get_input ( struct mansession s,
char *  output 
) [static]

Read one full line (including crlf) from the manager socket.

Note:
 * \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 6213 of file manager.c.

References mansession_session::addr, ao2_lock, ao2_unlock, ast_log, AST_PTHREADT_NULL, ast_sockaddr_stringify_addr(), ast_wait_for_input(), mansession_session::authenticated, mansession_session::authstart, errno, mansession_session::f, mansession_session::fd, mansession_session::inbuf, mansession_session::inlen, LOG_ERROR, LOG_WARNING, MESSAGE_LINE_TOO_LONG, mansession::parsing, mansession_session::pending_event, mansession::session, and mansession_session::waiting_thread.

Referenced by do_message(), and input_check().

06214 {
06215    int res, x;
06216    int maxlen = sizeof(s->session->inbuf) - 1;
06217    char *src = s->session->inbuf;
06218    int timeout = -1;
06219    time_t now;
06220 
06221    /*
06222     * Look for \r\n within the buffer. If found, copy to the output
06223     * buffer and return, trimming the \r\n (not used afterwards).
06224     */
06225    for (x = 0; x < s->session->inlen; x++) {
06226       int cr;  /* set if we have \r */
06227       if (src[x] == '\r' && x+1 < s->session->inlen && src[x + 1] == '\n') {
06228          cr = 2;  /* Found. Update length to include \r\n */
06229       } else if (src[x] == '\n') {
06230          cr = 1;  /* also accept \n only */
06231       } else {
06232          continue;
06233       }
06234       memmove(output, src, x);   /*... but trim \r\n */
06235       output[x] = '\0';    /* terminate the string */
06236       x += cr;       /* number of bytes used */
06237       s->session->inlen -= x;       /* remaining size */
06238       memmove(src, src + x, s->session->inlen); /* remove used bytes */
06239       return 1;
06240    }
06241    if (s->session->inlen >= maxlen) {
06242       /* no crlf found, and buffer full - sorry, too long for us */
06243       ast_log(LOG_WARNING, "Discarding message from %s. Line too long: %.25s...\n", ast_sockaddr_stringify_addr(&s->session->addr), src);
06244       s->session->inlen = 0;
06245       s->parsing = MESSAGE_LINE_TOO_LONG;
06246    }
06247    res = 0;
06248    while (res == 0) {
06249       /* calculate a timeout if we are not authenticated */
06250       if (!s->session->authenticated) {
06251          if(time(&now) == -1) {
06252             ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
06253             return -1;
06254          }
06255 
06256          timeout = (authtimeout - (now - s->session->authstart)) * 1000;
06257          if (timeout < 0) {
06258             /* we have timed out */
06259             return 0;
06260          }
06261       }
06262 
06263       ao2_lock(s->session);
06264       if (s->session->pending_event) {
06265          s->session->pending_event = 0;
06266          ao2_unlock(s->session);
06267          return 0;
06268       }
06269       s->session->waiting_thread = pthread_self();
06270       ao2_unlock(s->session);
06271 
06272       res = ast_wait_for_input(s->session->fd, timeout);
06273 
06274       ao2_lock(s->session);
06275       s->session->waiting_thread = AST_PTHREADT_NULL;
06276       ao2_unlock(s->session);
06277    }
06278    if (res < 0) {
06279       /* If we get a signal from some other thread (typically because
06280        * there are new events queued), return 0 to notify the caller.
06281        */
06282       if (errno == EINTR || errno == EAGAIN) {
06283          return 0;
06284       }
06285       ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno));
06286       return -1;
06287    }
06288 
06289    ao2_lock(s->session);
06290    res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f);
06291    if (res < 1) {
06292       res = -1;   /* error return */
06293    } else {
06294       s->session->inlen += res;
06295       src[s->session->inlen] = '\0';
06296       res = 0;
06297    }
06298    ao2_unlock(s->session);
06299    return res;
06300 }

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 2124 of file manager.c.

References AST_RWLIST_TRAVERSE, ast_manager_user::list, NULL, and ast_manager_user::username.

Referenced by __init_manager(), auth_http_callback(), authenticate(), function_amiclient(), handle_showmanager(), manager_displayconnects(), and process_message().

02125 {
02126    struct ast_manager_user *user = NULL;
02127 
02128    AST_RWLIST_TRAVERSE(&users, user, list) {
02129       if (!strcasecmp(user->username, name)) {
02130          break;
02131       }
02132    }
02133 
02134    return user;
02135 }

static int get_perm ( const char *  instr  )  [static]

Definition at line 1949 of file manager.c.

References ARRAY_LEN, ast_instring(), permalias::num, and perms.

Referenced by __init_manager(), and strings_to_mask().

01950 {
01951    int x = 0, ret = 0;
01952 
01953    if (!instr) {
01954       return 0;
01955    }
01956 
01957    for (x = 0; x < ARRAY_LEN(perms); x++) {
01958       if (ast_instring(instr, perms[x].label, ',')) {
01959          ret |= perms[x].num;
01960       }
01961    }
01962 
01963    return ret;
01964 }

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 1781 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().

01782 {
01783    struct eventqent *ret;
01784 
01785    AST_RWLIST_WRLOCK(&all_events);
01786    ret = AST_RWLIST_LAST(&all_events);
01787    /* the list is never empty now, but may become so when
01788     * we optimize it in the future, so be prepared.
01789     */
01790    if (ret) {
01791       ast_atomic_fetchadd_int(&ret->usecount, 1);
01792    }
01793    AST_RWLIST_UNLOCK(&all_events);
01794    return ret;
01795 }

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 2522 of file manager.c.

References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, reload_manager(), and ast_cli_entry::usage.

02523 {
02524    switch (cmd) {
02525    case CLI_INIT:
02526       e->command = "manager reload";
02527       e->usage =
02528          "Usage: manager reload\n"
02529          "       Reloads the manager configuration.\n";
02530       return NULL;
02531    case CLI_GENERATE:
02532       return NULL;
02533    }
02534    if (a->argc > 2) {
02535       return CLI_SHOWUSAGE;
02536    }
02537    reload_manager();
02538    return CLI_SUCCESS;
02539 }

static char* handle_mandebug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2264 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, NULL, and ast_cli_entry::usage.

02265 {
02266    switch (cmd) {
02267    case CLI_INIT:
02268       e->command = "manager set debug [on|off]";
02269       e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n";
02270       return NULL;
02271    case CLI_GENERATE:
02272       return NULL;
02273    }
02274 
02275    if (a->argc == 3) {
02276       ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off");
02277    } else if (a->argc == 4) {
02278       if (!strcasecmp(a->argv[3], "on")) {
02279          manager_debug = 1;
02280       } else if (!strcasecmp(a->argv[3], "off")) {
02281          manager_debug = 0;
02282       } else {
02283          return CLI_SHOWUSAGE;
02284       }
02285    }
02286    return CLI_SUCCESS;
02287 }

static void handle_parse_error ( struct mansession s,
struct message m,
char *  error 
) [static]

Definition at line 6311 of file manager.c.

References astman_send_error(), mansession_lock(), mansession_unlock(), MESSAGE_OKAY, and mansession::parsing.

Referenced by do_message().

06312 {
06313    mansession_lock(s);
06314    astman_send_error(s, m, error);
06315    s->parsing = MESSAGE_OKAY;
06316    mansession_unlock(s);
06317 }

static char* handle_showmanager ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2289 of file manager.c.

References ast_manager_user::acl, ast_manager_user::allowmultiplelogin, ast_cli_args::argc, ast_cli_args::argv, ast_acl_list_is_empty(), ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_strdup, ast_manager_user::chanvars, 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(), MAX_AUTH_PERM_STRING, ast_cli_args::n, ast_variable::name, ast_variable::next, NULL, ast_cli_args::pos, ast_manager_user::readperm, ast_manager_user::secret, ast_cli_entry::usage, user_authority_to_str(), ast_manager_user::username, ast_variable::value, ast_cli_args::word, and ast_manager_user::writeperm.

02290 {
02291    struct ast_manager_user *user = NULL;
02292    int l, which;
02293    char *ret = NULL;
02294    struct ast_str *rauthority = ast_str_alloca(MAX_AUTH_PERM_STRING);
02295    struct ast_str *wauthority = ast_str_alloca(MAX_AUTH_PERM_STRING);
02296    struct ast_variable *v;
02297 
02298    switch (cmd) {
02299    case CLI_INIT:
02300       e->command = "manager show user";
02301       e->usage =
02302          " Usage: manager show user <user>\n"
02303          "        Display all information related to the manager user specified.\n";
02304       return NULL;
02305    case CLI_GENERATE:
02306       l = strlen(a->word);
02307       which = 0;
02308       if (a->pos != 3) {
02309          return NULL;
02310       }
02311       AST_RWLIST_RDLOCK(&users);
02312       AST_RWLIST_TRAVERSE(&users, user, list) {
02313          if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) {
02314             ret = ast_strdup(user->username);
02315             break;
02316          }
02317       }
02318       AST_RWLIST_UNLOCK(&users);
02319       return ret;
02320    }
02321 
02322    if (a->argc != 4) {
02323       return CLI_SHOWUSAGE;
02324    }
02325 
02326    AST_RWLIST_RDLOCK(&users);
02327 
02328    if (!(user = get_manager_by_name_locked(a->argv[3]))) {
02329       ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]);
02330       AST_RWLIST_UNLOCK(&users);
02331       return CLI_SUCCESS;
02332    }
02333 
02334    ast_cli(a->fd, "\n");
02335    ast_cli(a->fd,
02336       "          username: %s\n"
02337       "            secret: %s\n"
02338       "               ACL: %s\n"
02339       "         read perm: %s\n"
02340       "        write perm: %s\n"
02341       "   displayconnects: %s\n"
02342       "allowmultiplelogin: %s\n",
02343       (user->username ? user->username : "(N/A)"),
02344       (user->secret ? "<Set>" : "(N/A)"),
02345       ((user->acl && !ast_acl_list_is_empty(user->acl)) ? "yes" : "no"),
02346       user_authority_to_str(user->readperm, &rauthority),
02347       user_authority_to_str(user->writeperm, &wauthority),
02348       (user->displayconnects ? "yes" : "no"),
02349       (user->allowmultiplelogin ? "yes" : "no"));
02350    ast_cli(a->fd, "         Variables: \n");
02351       for (v = user->chanvars ; v ; v = v->next) {
02352          ast_cli(a->fd, "                 %s = %s\n", v->name, v->value);
02353       }
02354 
02355    AST_RWLIST_UNLOCK(&users);
02356 
02357    return CLI_SUCCESS;
02358 }

static char* handle_showmanagers ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2360 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, NULL, ast_cli_entry::usage, and ast_manager_user::username.

02361 {
02362    struct ast_manager_user *user = NULL;
02363    int count_amu = 0;
02364    switch (cmd) {
02365    case CLI_INIT:
02366       e->command = "manager show users";
02367       e->usage =
02368          "Usage: manager show users\n"
02369          "       Prints a listing of all managers that are currently configured on that\n"
02370          " system.\n";
02371       return NULL;
02372    case CLI_GENERATE:
02373       return NULL;
02374    }
02375    if (a->argc != 3) {
02376       return CLI_SHOWUSAGE;
02377    }
02378 
02379    AST_RWLIST_RDLOCK(&users);
02380 
02381    /* If there are no users, print out something along those lines */
02382    if (AST_RWLIST_EMPTY(&users)) {
02383       ast_cli(a->fd, "There are no manager users.\n");
02384       AST_RWLIST_UNLOCK(&users);
02385       return CLI_SUCCESS;
02386    }
02387 
02388    ast_cli(a->fd, "\nusername\n--------\n");
02389 
02390    AST_RWLIST_TRAVERSE(&users, user, list) {
02391       ast_cli(a->fd, "%s\n", user->username);
02392       count_amu++;
02393    }
02394 
02395    AST_RWLIST_UNLOCK(&users);
02396 
02397    ast_cli(a->fd,"-------------------\n"
02398             "%d manager users configured.\n", count_amu);
02399    return CLI_SUCCESS;
02400 }

static char* handle_showmancmd ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2157 of file manager.c.

References manager_action::action, ast_cli_args::argc, manager_action::arguments, ast_cli_args::argv, ast_cli(), AST_LIST_NEXT, 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::description, manager_action::docsrc, ast_cli_args::fd, manager_action::final_response, manager_action::list_responses, MAX_AUTH_PERM_STRING, ast_cli_args::n, eventqent::next, NULL, print_event_instance(), S_OR, manager_action::seealso, manager_action::synopsis, synopsis, manager_action::syntax, term_color(), ast_cli_entry::usage, and ast_cli_args::word.

02158 {
02159    struct manager_action *cur;
02160    struct ast_str *authority;
02161    int num, l, which;
02162    const char *auth_str;
02163    char *ret = NULL;
02164 #ifdef AST_XML_DOCS
02165    char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64];
02166    char arguments_title[64], privilege_title[64], final_response_title[64], list_responses_title[64];
02167 #endif
02168 
02169    switch (cmd) {
02170    case CLI_INIT:
02171       e->command = "manager show command";
02172       e->usage =
02173          "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n"
02174          "  Shows the detailed description for a specific Asterisk manager interface command.\n";
02175       return NULL;
02176    case CLI_GENERATE:
02177       l = strlen(a->word);
02178       which = 0;
02179       AST_RWLIST_RDLOCK(&actions);
02180       AST_RWLIST_TRAVERSE(&actions, cur, list) {
02181          if (!strncasecmp(a->word, cur->action, l) && ++which > a->n) {
02182             ret = ast_strdup(cur->action);
02183             break;   /* make sure we exit even if ast_strdup() returns NULL */
02184          }
02185       }
02186       AST_RWLIST_UNLOCK(&actions);
02187       return ret;
02188    }
02189    authority = ast_str_alloca(MAX_AUTH_PERM_STRING);
02190    if (a->argc < 4) {
02191       return CLI_SHOWUSAGE;
02192    }
02193 
02194 #ifdef AST_XML_DOCS
02195    /* setup the titles */
02196    term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
02197    term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40);
02198    term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
02199    term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40);
02200    term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
02201    term_color(privilege_title, "[Privilege]\n", COLOR_MAGENTA, 0, 40);
02202    term_color(final_response_title, "[Final Response]\n", COLOR_MAGENTA, 0, 40);
02203    term_color(list_responses_title, "[List Responses]\n", COLOR_MAGENTA, 0, 40);
02204 #endif
02205 
02206    AST_RWLIST_RDLOCK(&actions);
02207    AST_RWLIST_TRAVERSE(&actions, cur, list) {
02208       for (num = 3; num < a->argc; num++) {
02209          if (!strcasecmp(cur->action, a->argv[num])) {
02210             auth_str = authority_to_str(cur->authority, &authority);
02211 
02212 #ifdef AST_XML_DOCS
02213             if (cur->docsrc == AST_XML_DOC) {
02214                char *syntax = ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1);
02215                char *synopsis = ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1);
02216                char *description = ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1);
02217                char *arguments = ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1);
02218                char *seealso = ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1);
02219                char *privilege = ast_xmldoc_printable(S_OR(auth_str, "Not available"), 1);
02220                char *responses = ast_xmldoc_printable("None", 1);
02221                ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s",
02222                   syntax_title, syntax,
02223                   synopsis_title, synopsis,
02224                   description_title, description,
02225                   arguments_title, arguments,
02226                   seealso_title, seealso,
02227                   privilege_title, privilege,
02228                   list_responses_title);
02229 
02230                if (!cur->list_responses) {
02231                   ast_cli(a->fd, "%s\n\n", responses);
02232                } else {
02233                   struct ast_xml_doc_item *temp;
02234                   for (temp = cur->list_responses; temp; temp = AST_LIST_NEXT(temp, next)) {
02235                      ast_cli(a->fd, "Event: %s\n", temp->name);
02236                      print_event_instance(a, temp);
02237                   }
02238                }
02239 
02240                ast_cli(a->fd, "%s", final_response_title);
02241 
02242                if (!cur->final_response) {
02243                   ast_cli(a->fd, "%s\n\n", responses);
02244                } else {
02245                   ast_cli(a->fd, "Event: %s\n", cur->final_response->name);
02246                   print_event_instance(a, cur->final_response);
02247                }
02248             } else
02249 #endif
02250             {
02251                ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
02252                   cur->action, cur->synopsis,
02253                   auth_str,
02254                   S_OR(cur->description, ""));
02255             }
02256          }
02257       }
02258    }
02259    AST_RWLIST_UNLOCK(&actions);
02260 
02261    return CLI_SUCCESS;
02262 }

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 2403 of file manager.c.

References manager_action::action, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, HSMC_FORMAT, manager_action::list, MGR_SHOW_TERMINAL_WIDTH, NULL, manager_action::synopsis, and ast_cli_entry::usage.

02404 {
02405    struct manager_action *cur;
02406    int name_len = 1;
02407    int space_remaining;
02408 #define HSMC_FORMAT "  %-*.*s  %-.*s\n"
02409    switch (cmd) {
02410    case CLI_INIT:
02411       e->command = "manager show commands";
02412       e->usage =
02413          "Usage: manager show commands\n"
02414          "  Prints a listing of all the available Asterisk manager interface commands.\n";
02415       return NULL;
02416    case CLI_GENERATE:
02417       return NULL;
02418    }
02419 
02420    AST_RWLIST_RDLOCK(&actions);
02421    AST_RWLIST_TRAVERSE(&actions, cur, list) {
02422       int incoming_len = strlen(cur->action);
02423       if (incoming_len > name_len) {
02424          name_len = incoming_len;
02425       }
02426    }
02427 
02428    space_remaining = MGR_SHOW_TERMINAL_WIDTH - name_len - 4;
02429    if (space_remaining < 0) {
02430       space_remaining = 0;
02431    }
02432 
02433    ast_cli(a->fd, HSMC_FORMAT, name_len, name_len, "Action", space_remaining, "Synopsis");
02434    ast_cli(a->fd, HSMC_FORMAT, name_len, name_len, "------", space_remaining, "--------");
02435 
02436    AST_RWLIST_TRAVERSE(&actions, cur, list) {
02437       ast_cli(a->fd, HSMC_FORMAT, name_len, name_len, cur->action, space_remaining, cur->synopsis);
02438    }
02439    AST_RWLIST_UNLOCK(&actions);
02440 
02441    return CLI_SUCCESS;
02442 }

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 2445 of file manager.c.

References mansession_session::addr, ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), ast_sockaddr_stringify_addr(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, mansession_session::fd, ast_cli_args::fd, HSMCONN_FORMAT1, HSMCONN_FORMAT2, mansession_session::inuse, NULL, mansession_session::readperm, session, mansession_session::sessionstart, unref_mansession(), ast_cli_entry::usage, mansession_session::username, and mansession_session::writeperm.

02446 {
02447    struct ao2_container *sessions;
02448    struct mansession_session *session;
02449    time_t now = time(NULL);
02450 #define HSMCONN_FORMAT1 "  %-15.15s  %-55.55s  %-10.10s  %-10.10s  %-8.8s  %-8.8s  %-5.5s  %-5.5s\n"
02451 #define HSMCONN_FORMAT2 "  %-15.15s  %-55.55s  %-10d  %-10d  %-8d  %-8d  %-5.5d  %-5.5d\n"
02452    int count = 0;
02453    struct ao2_iterator i;
02454 
02455    switch (cmd) {
02456    case CLI_INIT:
02457       e->command = "manager show connected";
02458       e->usage =
02459          "Usage: manager show connected\n"
02460          "  Prints a listing of the users that are currently connected to the\n"
02461          "Asterisk manager interface.\n";
02462       return NULL;
02463    case CLI_GENERATE:
02464       return NULL;
02465    }
02466 
02467    ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write");
02468 
02469    sessions = ao2_global_obj_ref(mgr_sessions);
02470    if (sessions) {
02471       i = ao2_iterator_init(sessions, 0);
02472       ao2_ref(sessions, -1);
02473       while ((session = ao2_iterator_next(&i))) {
02474          ao2_lock(session);
02475          ast_cli(a->fd, HSMCONN_FORMAT2, session->username,
02476             ast_sockaddr_stringify_addr(&session->addr),
02477             (int) (session->sessionstart),
02478             (int) (now - session->sessionstart),
02479             session->fd,
02480             session->inuse,
02481             session->readperm,
02482             session->writeperm);
02483          count++;
02484          ao2_unlock(session);
02485          unref_mansession(session);
02486       }
02487       ao2_iterator_destroy(&i);
02488    }
02489    ast_cli(a->fd, "%d users connected.\n", count);
02490 
02491    return CLI_SUCCESS;
02492 }

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 2496 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, NULL, ast_cli_entry::usage, and eventqent::usecount.

02497 {
02498    struct eventqent *s;
02499    switch (cmd) {
02500    case CLI_INIT:
02501       e->command = "manager show eventq";
02502       e->usage =
02503          "Usage: manager show eventq\n"
02504          "  Prints a listing of all events pending in the Asterisk manger\n"
02505          "event queue.\n";
02506       return NULL;
02507    case CLI_GENERATE:
02508       return NULL;
02509    }
02510    AST_RWLIST_RDLOCK(&all_events);
02511    AST_RWLIST_TRAVERSE(&all_events, s, eq_next) {
02512       ast_cli(a->fd, "Usecount: %d\n", s->usecount);
02513       ast_cli(a->fd, "Category: %d\n", s->category);
02514       ast_cli(a->fd, "Event:\n%s", s->eventdata);
02515    }
02516    AST_RWLIST_UNLOCK(&all_events);
02517 
02518    return CLI_SUCCESS;
02519 }

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 3515 of file manager.c.

References ast_begins_with(), ast_category_append(), ast_category_browse_filtered(), ast_category_delete(), ast_category_destroy(), ast_category_empty(), ast_category_get(), ast_category_inherit(), ast_category_insert(), ast_category_new(), ast_category_new_template(), ast_category_rename(), ast_free, ast_log, ast_str_create(), ast_strdupa, ast_strlen_zero, ast_strsep(), AST_STRSEP_STRIP, ast_variable_append(), ast_variable_delete(), ast_variable_insert(), ast_variable_new(), ast_variable_update(), astman_get_header(), c, eventqent::category, FAILURE_ALLOCATION, FAILURE_NEWCAT, FAILURE_TEMPLATE, FAILURE_UPDATE, LOG_WARNING, match(), NULL, ast_variable::object, result, UNKNOWN_ACTION, UNKNOWN_CATEGORY, UNSPECIFIED_ARGUMENT, UNSPECIFIED_CATEGORY, value, and var.

Referenced by action_updateconfig().

03516 {
03517    int x;
03518    char hdr[40];
03519    const char *action, *cat, *var, *value, *match, *line, *options;
03520    struct ast_variable *v;
03521    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
03522    enum error_type result = 0;
03523 
03524    for (x = 0; x < 100000; x++) {   /* 100000 = the max number of allowed updates + 1 */
03525       unsigned int object = 0;
03526       char *dupoptions;
03527       int allowdups = 0;
03528       int istemplate = 0;
03529       int ignoreerror = 0;
03530       char *inherit = NULL;
03531       char *catfilter = NULL;
03532       char *token;
03533       int foundvar = 0;
03534       int foundcat = 0;
03535       struct ast_category *category = NULL;
03536 
03537       snprintf(hdr, sizeof(hdr), "Action-%06d", x);
03538       action = astman_get_header(m, hdr);
03539       if (ast_strlen_zero(action))     /* breaks the for loop if no action header */
03540          break;                     /* this could cause problems if actions come in misnumbered */
03541 
03542       snprintf(hdr, sizeof(hdr), "Cat-%06d", x);
03543       cat = astman_get_header(m, hdr);
03544       if (ast_strlen_zero(cat)) {      /* every action needs a category */
03545          result =  UNSPECIFIED_CATEGORY;
03546          break;
03547       }
03548 
03549       snprintf(hdr, sizeof(hdr), "Var-%06d", x);
03550       var = astman_get_header(m, hdr);
03551 
03552       snprintf(hdr, sizeof(hdr), "Value-%06d", x);
03553       value = astman_get_header(m, hdr);
03554 
03555       if (!ast_strlen_zero(value) && *value == '>') {
03556          object = 1;
03557          value++;
03558       }
03559 
03560       snprintf(hdr, sizeof(hdr), "Match-%06d", x);
03561       match = astman_get_header(m, hdr);
03562 
03563       snprintf(hdr, sizeof(hdr), "Line-%06d", x);
03564       line = astman_get_header(m, hdr);
03565 
03566       snprintf(hdr, sizeof(hdr), "Options-%06d", x);
03567       options = astman_get_header(m, hdr);
03568       if (!ast_strlen_zero(options)) {
03569          dupoptions = ast_strdupa(options);
03570          while ((token = ast_strsep(&dupoptions, ',', AST_STRSEP_STRIP))) {
03571             if (!strcasecmp("allowdups", token)) {
03572                allowdups = 1;
03573                continue;
03574             }
03575             if (!strcasecmp("template", token)) {
03576                istemplate = 1;
03577                continue;
03578             }
03579             if (!strcasecmp("ignoreerror", token)) {
03580                ignoreerror = 1;
03581                continue;
03582             }
03583             if (ast_begins_with(token, "inherit")) {
03584                char *c = ast_strsep(&token, '=', AST_STRSEP_STRIP);
03585                c = ast_strsep(&token, '=', AST_STRSEP_STRIP);
03586                if (c) {
03587                   inherit = ast_strdupa(c);
03588                }
03589                continue;
03590             }
03591             if (ast_begins_with(token, "catfilter")) {
03592                char *c = ast_strsep(&token, '=', AST_STRSEP_STRIP);
03593                c = ast_strsep(&token, '=', AST_STRSEP_STRIP);
03594                if (c) {
03595                   catfilter = ast_strdupa(c);
03596                }
03597                continue;
03598             }
03599          }
03600       }
03601 
03602       if (!strcasecmp(action, "newcat")) {
03603          struct ast_category *template;
03604          char *tmpl_name = NULL;
03605 
03606          if (!allowdups) {
03607             if (ast_category_get(cfg, cat, "TEMPLATES=include")) {
03608                if (ignoreerror) {
03609                   continue;
03610                } else {
03611                   result = FAILURE_NEWCAT;   /* already exist */
03612                   break;
03613                }
03614             }
03615          }
03616 
03617          if (istemplate) {
03618             category = ast_category_new_template(cat, dfn, -1);
03619          } else {
03620             category = ast_category_new(cat, dfn, -1);
03621          }
03622 
03623          if (!category) {
03624             result = FAILURE_ALLOCATION;
03625             break;
03626          }
03627 
03628          if (inherit) {
03629             while ((tmpl_name = ast_strsep(&inherit, ',', AST_STRSEP_STRIP))) {
03630                if ((template = ast_category_get(cfg, tmpl_name, "TEMPLATES=restrict"))) {
03631                   if (ast_category_inherit(category, template)) {
03632                      result = FAILURE_ALLOCATION;
03633                      break;
03634                   }
03635                } else {
03636                   ast_category_destroy(category);
03637                   category = NULL;
03638                   result = FAILURE_TEMPLATE; /* template not found */
03639                   break;
03640                }
03641             }
03642          }
03643 
03644          if (category != NULL) {
03645             if (ast_strlen_zero(match)) {
03646                ast_category_append(cfg, category);
03647             } else {
03648                if (ast_category_insert(cfg, category, match)) {
03649                   ast_category_destroy(category);
03650                   result = FAILURE_NEWCAT;
03651                   break;
03652                }
03653             }
03654          }
03655       } else if (!strcasecmp(action, "renamecat")) {
03656          if (ast_strlen_zero(value)) {
03657             result = UNSPECIFIED_ARGUMENT;
03658             break;
03659          }
03660 
03661          foundcat = 0;
03662          while ((category = ast_category_browse_filtered(cfg, cat, category, catfilter))) {
03663             ast_category_rename(category, value);
03664             foundcat = 1;
03665          }
03666 
03667          if (!foundcat) {
03668             result = UNKNOWN_CATEGORY;
03669             break;
03670          }
03671       } else if (!strcasecmp(action, "delcat")) {
03672          foundcat = 0;
03673          while ((category = ast_category_browse_filtered(cfg, cat, category, catfilter))) {
03674             category = ast_category_delete(cfg, category);
03675             foundcat = 1;
03676          }
03677 
03678          if (!foundcat && !ignoreerror) {
03679             result = UNKNOWN_CATEGORY;
03680             break;
03681          }
03682       } else if (!strcasecmp(action, "emptycat")) {
03683          foundcat = 0;
03684          while ((category = ast_category_browse_filtered(cfg, cat, category, catfilter))) {
03685             ast_category_empty(category);
03686             foundcat = 1;
03687          }
03688 
03689          if (!foundcat) {
03690             result = UNKNOWN_CATEGORY;
03691             break;
03692          }
03693       } else if (!strcasecmp(action, "update")) {
03694          if (ast_strlen_zero(var)) {
03695             result = UNSPECIFIED_ARGUMENT;
03696             break;
03697          }
03698 
03699          foundcat = 0;
03700          foundvar = 0;
03701          while ((category = ast_category_browse_filtered(cfg, cat, category, catfilter))) {
03702             if (!ast_variable_update(category, var, value, match, object)) {
03703                foundvar = 1;
03704             }
03705             foundcat = 1;
03706          }
03707 
03708          if (!foundcat) {
03709             result = UNKNOWN_CATEGORY;
03710             break;
03711          }
03712 
03713          if (!foundvar) {
03714             result = FAILURE_UPDATE;
03715             break;
03716          }
03717       } else if (!strcasecmp(action, "delete")) {
03718          if ((ast_strlen_zero(var) && ast_strlen_zero(line))) {
03719             result = UNSPECIFIED_ARGUMENT;
03720             break;
03721          }
03722 
03723          foundcat = 0;
03724          foundvar = 0;
03725          while ((category = ast_category_browse_filtered(cfg, cat, category, catfilter))) {
03726             if (!ast_variable_delete(category, var, match, line)) {
03727                foundvar = 1;
03728             }
03729             foundcat = 1;
03730          }
03731 
03732          if (!foundcat) {
03733             result = UNKNOWN_CATEGORY;
03734             break;
03735          }
03736 
03737          if (!foundvar && !ignoreerror) {
03738             result = FAILURE_UPDATE;
03739             break;
03740          }
03741       } else if (!strcasecmp(action, "append")) {
03742          if (ast_strlen_zero(var)) {
03743             result = UNSPECIFIED_ARGUMENT;
03744             break;
03745          }
03746 
03747          foundcat = 0;
03748          while ((category = ast_category_browse_filtered(cfg, cat, category, catfilter))) {
03749             if (!(v = ast_variable_new(var, value, dfn))) {
03750                result = FAILURE_ALLOCATION;
03751                break;
03752             }
03753             if (object || (match && !strcasecmp(match, "object"))) {
03754                v->object = 1;
03755             }
03756             ast_variable_append(category, v);
03757             foundcat = 1;
03758          }
03759 
03760          if (!foundcat) {
03761             result = UNKNOWN_CATEGORY;
03762             break;
03763          }
03764       } else if (!strcasecmp(action, "insert")) {
03765          if (ast_strlen_zero(var) || ast_strlen_zero(line)) {
03766             result = UNSPECIFIED_ARGUMENT;
03767             break;
03768          }
03769 
03770          foundcat = 0;
03771          while ((category = ast_category_browse_filtered(cfg, cat, category, catfilter))) {
03772             if (!(v = ast_variable_new(var, value, dfn))) {
03773                result = FAILURE_ALLOCATION;
03774                break;
03775             }
03776             ast_variable_insert(category, v, line);
03777             foundcat = 1;
03778          }
03779 
03780          if (!foundcat) {
03781             result = UNKNOWN_CATEGORY;
03782             break;
03783          }
03784       }
03785       else {
03786          ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action);
03787          result = UNKNOWN_ACTION;
03788          break;
03789       }
03790    }
03791    ast_free(str1);
03792    ast_free(str2);
03793    return result;
03794 }

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 3417 of file manager.c.

Referenced by astman_append_json().

03418 {
03419    for (; *in; in++) {
03420       if (*in == '\\' || *in == '\"') {
03421          *out++ = '\\';
03422       }
03423       *out++ = *in;
03424    }
03425    *out = '\0';
03426 }

static struct ast_variable* man_do_variable_value ( struct ast_variable head,
const char *  hdr_val 
) [static, read]

Definition at line 2622 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_order().

02623 {
02624    char *parse;
02625    AST_DECLARE_APP_ARGS(args,
02626       AST_APP_ARG(vars)[64];
02627    );
02628 
02629    hdr_val = ast_skip_blanks(hdr_val); /* ignore leading spaces in the value */
02630    parse = ast_strdupa(hdr_val);
02631 
02632    /* Break the header value string into name=val pair items. */
02633    AST_STANDARD_APP_ARGS(args, parse);
02634    if (args.argc) {
02635       int y;
02636 
02637       /* Process each name=val pair item. */
02638       for (y = 0; y < args.argc; y++) {
02639          struct ast_variable *cur;
02640          char *var;
02641          char *val;
02642 
02643          if (!args.vars[y]) {
02644             continue;
02645          }
02646          var = val = args.vars[y];
02647          strsep(&val, "=");
02648 
02649          /* XXX We may wish to trim whitespace from the strings. */
02650          if (!val || ast_strlen_zero(var)) {
02651             continue;
02652          }
02653 
02654          /* Create new variable list node and prepend it to the list. */
02655          cur = ast_variable_new(var, val, "");
02656          if (cur) {
02657             cur->next = head;
02658             head = cur;
02659          }
02660       }
02661    }
02662 
02663    return head;
02664 }

static enum add_filter_result manager_add_filter ( const char *  filter_pattern,
struct ao2_container whitefilters,
struct ao2_container blackfilters 
) [static]

Add an event filter to a manager session.

Parameters:
filter_pattern Filter syntax to add, see below for syntax
Returns:
FILTER_ALLOC_FAILED Memory allocation failure

FILTER_COMPILE_FAIL If the filter did not compile

FILTER_SUCCESS Success

Filter will be used to match against each line of a manager event Filter can be any valid regular expression Filter can be a valid regular expression prefixed with !, which will add the filter as a black filter

Examples:

   filter_pattern = "Event: Newchannel"
   filter_pattern = "Event: New.*"
   filter_pattern = "!Channel: DAHDI.*"

Definition at line 5668 of file manager.c.

References ao2_ref, ao2_t_alloc, ao2_t_link, ao2_t_ref, event_filter_destructor(), FILTER_ALLOC_FAILED, FILTER_COMPILE_FAIL, and FILTER_SUCCESS.

Referenced by