Mon Mar 19 11:30:56 2012

Asterisk developer's documentation


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  channelvars
struct  eventqent
struct  fast_originate_helper
 helper function for originate More...
struct  manager_channel_variable
struct  manager_hooks
 list of hooks registered More...
struct  mansession
struct  mansession_session
struct  permalias
struct  users
 list of users found in the config file More...

Defines

#define ASTMAN_APPEND_BUF_INITSIZE   256
 initial allocated size for the astman_append_buf
#define DEFAULT_REALM   "asterisk"
#define GET_HEADER_FIRST_MATCH   0
#define GET_HEADER_LAST_MATCH   1
#define GET_HEADER_SKIP_EMPTY   2
#define MANAGER_EVENT_BUF_INITSIZE   256
#define MAX_BLACKLIST_CMD_LEN   2
 Descriptor for a manager session, either on the AMI socket or over HTTP.
#define MSG_MOREDATA   ((char *)astman_send_response)
 send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field.

Enumerations

enum  error_type {
  UNKNOWN_ACTION = 1, UNKNOWN_CATEGORY, UNSPECIFIED_CATEGORY, UNSPECIFIED_ARGUMENT,
  FAILURE_ALLOCATION, FAILURE_NEWCAT, FAILURE_DELCAT, FAILURE_EMPTYCAT,
  FAILURE_UPDATE, FAILURE_DELETE, FAILURE_APPEND
}

Functions

int __ast_manager_event_multichan (int category, const char *event, int chancount, struct ast_channel **chans, const char *file, int line, const char *func, const char *fmt,...)
static const char * __astman_get_header (const struct message *m, char *var, int mode)
 Return a matching header value.
static void __init_astman_append_buf (void)
 thread local buffer for astman_append
static void __init_manager_event_buf (void)
static void __init_manager_event_funcbuf (void)
static void __init_userevent_buf (void)
static int action_aocmessage (struct mansession *s, const struct message *m)
static int action_atxfer (struct mansession *s, const struct message *m)
static int action_challenge (struct mansession *s, const struct message *m)
static int action_command (struct mansession *s, const struct message *m)
 Manager command "command" - execute CLI command.
static int action_coresettings (struct mansession *s, const struct message *m)
 Show PBX core settings information.
static int action_coreshowchannels (struct mansession *s, const struct message *m)
 Manager command "CoreShowChannels" - List currently defined channels and some information about them.
static int action_corestatus (struct mansession *s, const struct message *m)
 Show PBX core status information.
static int action_createconfig (struct mansession *s, const struct message *m)
static void action_destroy (void *obj)
static int action_events (struct mansession *s, const struct message *m)
static int action_extensionstate (struct mansession *s, const struct message *m)
static struct manager_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_login (struct mansession *s, const struct message *m)
static int action_logoff (struct mansession *s, const struct message *m)
static int action_mailboxcount (struct mansession *s, const struct message *m)
static int action_mailboxstatus (struct mansession *s, const struct message *m)
static int action_originate (struct mansession *s, const struct message *m)
static int action_ping (struct mansession *s, const struct message *m)
static int action_redirect (struct mansession *s, const struct message *m)
 action_redirect: The redirect manager command
static int action_reload (struct mansession *s, const struct message *m)
 Send a reload event.
static int action_sendtext (struct mansession *s, const struct message *m)
static int action_setvar (struct mansession *s, const struct message *m)
static int action_status (struct mansession *s, const struct message *m)
 Manager "status" command to show channels.
static int action_timeout (struct mansession *s, const struct message *m)
static int action_updateconfig (struct mansession *s, const struct message *m)
static int action_userevent (struct mansession *s, const struct message *m)
static int action_waitevent (struct mansession *s, const struct message *m)
static struct eventqentadvance_event (struct eventqent *e)
static int aocmessage_get_unit_entry (const struct message *m, struct ast_aoc_unit_entry *entry, unsigned int entry_num)
static void append_channel_vars (struct ast_str **pbuf, struct ast_channel *chan)
static int append_event (const char *str, int category)
int ast_hook_send_action (struct manager_custom_hook *hook, const char *msg)
 Registered hooks can call this function to invoke actions and they will receive responses through registered callback.
static int ast_instring (const char *bigstr, const char *smallstr, const char delim)
int ast_manager_register2 (const char *action, int auth, int(*func)(struct mansession *s, const struct message *m), const char *synopsis, const char *description)
 Register a manager command with the manager interface.
void ast_manager_register_hook (struct manager_custom_hook *hook)
 Add a custom hook to be called when an event is fired.
static int ast_manager_register_struct (struct manager_action *act)
int ast_manager_unregister (char *action)
 Unregister a registered manager command.
void ast_manager_unregister_hook (struct manager_custom_hook *hook)
 Delete a custom hook to be called when an event is fired.
void astman_append (struct mansession *s, const char *fmt,...)
static void astman_append_json (struct mansession *s, const char *str)
const char * astman_get_header (const struct message *m, char *var)
 Get header from mananger transaction.
ast_variableastman_get_variables (const struct message *m)
 Get a linked list of the Variable: headers.
void astman_send_ack (struct mansession *s, const struct message *m, char *msg)
 Send ack in manager transaction.
void astman_send_error (struct mansession *s, const struct message *m, char *error)
 Send error in manager transaction.
void astman_send_listack (struct mansession *s, const struct message *m, char *msg, char *listflag)
 Send ack in manager list transaction.
void astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg)
 Send response in manager transaction.
static void astman_send_response_full (struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag)
static void astman_start_ack (struct mansession *s, const struct message *m)
static int authenticate (struct mansession *s, const struct message *m)
static const char * authority_to_str (int authority, struct ast_str **res)
 Convert authority code to a list of options.
static int blackfilter_cmp_fn (void *obj, void *arg, void *data, int flags)
static struct mansession_sessionbuild_mansession (struct sockaddr_in sin)
 Allocate manager session structure and add it to the list of sessions.
static int check_blacklist (const char *cmd)
int check_manager_enabled (void)
 Check if AMI is enabled.
static int check_manager_session_inuse (const char *name)
int check_webmanager_enabled (void)
 Check if AMI/HTTP is enabled.
static int do_message (struct mansession *s)
static void event_filter_destructor (void *obj)
static void * fast_originate (void *data)
static void free_channelvars (void)
static int get_input (struct mansession *s, char *output)
static struct ast_manager_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 char * handle_showmanager (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmanagers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmancmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmancmds (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list commands.
static char * handle_showmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list connected.
static char * handle_showmaneventq (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list eventq.
static enum error_type handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn)
static void json_escape (char *out, const char *in)
static struct ast_variableman_do_variable_value (struct ast_variable *head, const char *hdr_val)
static int manager_displayconnects (struct mansession_session *session)
 Get displayconnects config option.
static int manager_modulecheck (struct mansession *s, const struct message *m)
static int manager_moduleload (struct mansession *s, const struct message *m)
static int manager_state_cb (char *context, char *exten, int state, void *data)
static int mansession_cmp_fn (void *obj, void *arg, int flags)
static struct sockaddr_in * mansession_encode_sin_local (const struct mansession *s, struct sockaddr_in *sin_local)
static enum ast_security_event_transport_type mansession_get_transport (const struct mansession *s)
static void mansession_lock (struct mansession *s)
 Lock the 'mansession' structure.
static void mansession_unlock (struct mansession *s)
 Unlock the 'mansession' structure.
static int match_filter (struct mansession *s, char *eventdata)
static int process_events (struct mansession *s)
static int process_message (struct mansession *s, const struct message *m)
static void purge_events (void)
static void purge_sessions (int n_max)
 remove at most n_max stale session from the list.
static void report_auth_success (const struct mansession *s)
static void report_failed_acl (const struct mansession *s, const char *username)
static void report_failed_challenge_response (const struct mansession *s, const char *response, const char *expected_response)
static void report_inval_password (const struct mansession *s, const char *username)
static void report_invalid_user (const struct mansession *s, const char *username)
static void report_req_bad_format (const struct mansession *s, const char *action)
static void report_req_not_allowed (const struct mansession *s, const char *action)
static void report_session_limit (const struct mansession *s)
static int send_string (struct mansession *s, char *string)
static void session_destroy (struct mansession_session *s)
static void session_destructor (void *obj)
static void * session_do (void *data)
 The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ).
static int set_eventmask (struct mansession *s, const char *eventmask)
 Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm.
static int strings_to_mask (const char *string)
static struct mansession_sessionunref_mansession (struct mansession_session *s)
 Unreference manager session object. If no more references, then go ahead and delete it.
static int whitefilter_cmp_fn (void *obj, void *arg, void *data, int flags)

Variables

static int allowmultiplelogin = 1
static struct ast_threadstorage astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , }
static int authlimit
static int authtimeout
static int block_sockets
static int broken_events_action
struct {
   const char *   words [AST_MAX_CMD_LEN]
command_blacklist []
static const int DEFAULT_AUTHLIMIT = 50
static const int DEFAULT_AUTHTIMEOUT = 30
static const int DEFAULT_BLOCKSOCKETS = 0
static const int DEFAULT_BROKENEVENTSACTION = 0
static const int DEFAULT_DISPLAYCONNECTS = 1
static const int DEFAULT_ENABLED = 0
static const int DEFAULT_HTTPTIMEOUT = 60
static const int DEFAULT_MANAGERDEBUG = 0
static const int DEFAULT_TIMESTAMPEVENTS = 0
static const int DEFAULT_WEBENABLED = 0
static int displayconnects
static char global_realm [MAXHOSTNAMELEN]
static int httptimeout
static char * manager_channelvars
static int manager_debug = 0
static int manager_enabled = 0
static struct ast_threadstorage manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , }
static struct ast_threadstorage manager_event_funcbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_funcbuf , .custom_init = NULL , }
static struct permalias perms []
static struct ao2_containersessions = NULL
static int timestampevents
static int unauth_sessions = 0
static struct ast_threadstorage userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , }
static int webmanager_enabled = 0

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

Definition at line 1989 of file manager.c.

Referenced by astman_append().

#define DEFAULT_REALM   "asterisk"

Definition at line 902 of file manager.c.

Referenced by __init_manager(), and reload_config().

#define GET_HEADER_FIRST_MATCH   0

Definition at line 1750 of file manager.c.

Referenced by astman_get_header().

#define GET_HEADER_LAST_MATCH   1

Definition at line 1751 of file manager.c.

Referenced by __astman_get_header().

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 1752 of file manager.c.

Referenced by __astman_get_header(), and process_message().

#define MANAGER_EVENT_BUF_INITSIZE   256

Definition at line 5029 of file manager.c.

Referenced by __ast_manager_event_multichan().

#define MAX_BLACKLIST_CMD_LEN   2

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

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

Referenced by check_blacklist().

#define MSG_MOREDATA   ((char *)astman_send_response)

send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field.

Use the explicit constant MSG_MOREDATA to remove the empty line. XXX MSG_MOREDATA should go to a header file.

Definition at line 2030 of file manager.c.

Referenced by astman_send_response_full(), and astman_start_ack().


Enumeration Type Documentation

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 

Definition at line 834 of file manager.c.


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
contents Format string describing event
Since:
1.8

Definition at line 5031 of file manager.c.

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, append_channel_vars(), append_event(), ast_atomic_fetchadd_int(), AST_PTHREADT_NULL, AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_str_append(), ast_str_append_va(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_tvnow(), authority_to_str(), manager_custom_hook::helper, manager_debug, manager_event_buf, MANAGER_EVENT_BUF_INITSIZE, seq, timestampevents, and unref_mansession().

05033 {
05034    struct mansession_session *session;
05035    struct manager_custom_hook *hook;
05036    struct ast_str *auth = ast_str_alloca(80);
05037    const char *cat_str;
05038    va_list ap;
05039    struct timeval now;
05040    struct ast_str *buf;
05041    int i;
05042 
05043    if (!(sessions && ao2_container_count(sessions)) && AST_RWLIST_EMPTY(&manager_hooks)) {
05044       return 0;
05045    }
05046    
05047    if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) {
05048       return -1;
05049    }
05050 
05051    cat_str = authority_to_str(category, &auth);
05052    ast_str_set(&buf, 0,
05053          "Event: %s\r\nPrivilege: %s\r\n",
05054           event, cat_str);
05055 
05056    if (timestampevents) {
05057       now = ast_tvnow();
05058       ast_str_append(&buf, 0,
05059             "Timestamp: %ld.%06lu\r\n",
05060              (long)now.tv_sec, (unsigned long) now.tv_usec);
05061    }
05062    if (manager_debug) {
05063       static int seq;
05064       ast_str_append(&buf, 0,
05065             "SequenceNumber: %d\r\n",
05066              ast_atomic_fetchadd_int(&seq, 1));
05067       ast_str_append(&buf, 0,
05068             "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func);
05069    }
05070 
05071    va_start(ap, fmt);
05072    ast_str_append_va(&buf, 0, fmt, ap);
05073    va_end(ap);
05074    for (i = 0; i < chancount; i++) {
05075       append_channel_vars(&buf, chans[i]);
05076    }
05077 
05078    ast_str_append(&buf, 0, "\r\n");
05079 
05080    append_event(ast_str_buffer(buf), category);
05081 
05082    /* Wake up any sleeping sessions */
05083    if (sessions) {
05084       struct ao2_iterator i;
05085       i = ao2_iterator_init(sessions, 0);
05086       while ((session = ao2_iterator_next(&i))) {
05087          ao2_lock(session);
05088          if (session->waiting_thread != AST_PTHREADT_NULL) {
05089             pthread_kill(session->waiting_thread, SIGURG);
05090          } else {
05091             /* We have an event to process, but the mansession is
05092              * not waiting for it. We still need to indicate that there
05093              * is an event waiting so that get_input processes the pending
05094              * event instead of polling.
05095              */
05096             session->pending_event = 1;
05097          }
05098          ao2_unlock(session);
05099          unref_mansession(session);
05100       }
05101       ao2_iterator_destroy(&i);
05102    }
05103 
05104    if (!AST_RWLIST_EMPTY(&manager_hooks)) {
05105       AST_RWLIST_RDLOCK(&manager_hooks);
05106       AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) {
05107          hook->helper(category, event, ast_str_buffer(buf));
05108       }
05109       AST_RWLIST_UNLOCK(&manager_hooks);
05110    }
05111 
05112    return 0;
05113 }

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

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

Referenced by astman_get_header(), and process_message().

01768 {
01769    int x, l = strlen(var);
01770    const char *result = "";
01771 
01772    for (x = 0; x < m->hdrcount; x++) {
01773       const char *h = m->headers[x];
01774       if (!strncasecmp(var, h, l) && h[l] == ':') {
01775          const char *value = h + l + 1;
01776          value = ast_skip_blanks(value); /* ignore leading spaces in the value */
01777          /* found a potential candidate */
01778          if ((mode & GET_HEADER_SKIP_EMPTY) && ast_strlen_zero(value)) {
01779             continue;   /* not interesting */
01780          }
01781          if (mode & GET_HEADER_LAST_MATCH) {
01782             result = value;   /* record the last match so far */
01783          } else {
01784             return value;
01785          }
01786       }
01787    }
01788 
01789    return result;
01790 }

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

01995 {

static void __init_manager_event_buf ( void   )  [static]

Definition at line 5028 of file manager.c.

05033 {

static void __init_manager_event_funcbuf ( void   )  [static]

Definition at line 5001 of file manager.c.

05004 {

static void __init_userevent_buf ( void   )  [static]

Definition at line 1986 of file manager.c.

01995 {

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

Definition at line 3742 of file manager.c.

References ast_aoc_unit_entry::amount, aocmessage_get_unit_entry(), ast_aoc_add_unit_entry(), AST_AOC_BILLING_CALL_DEFLECTION, AST_AOC_BILLING_CALL_FWD_BUSY, AST_AOC_BILLING_CALL_FWD_NO_REPLY, AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL, AST_AOC_BILLING_CALL_TRANSFER, AST_AOC_BILLING_CREDIT_CARD, AST_AOC_BILLING_NA, AST_AOC_BILLING_NORMAL, AST_AOC_BILLING_REVERSE_CHARGE, AST_AOC_CHARGE_CURRENCY, AST_AOC_CHARGE_FREE, AST_AOC_CHARGE_NA, AST_AOC_CHARGE_UNIT, ast_aoc_create(), AST_AOC_D, ast_aoc_destroy_decoded(), ast_aoc_destroy_encoded(), AST_AOC_E, ast_aoc_encode(), AST_AOC_MULT_HUNDRED, AST_AOC_MULT_ONE, AST_AOC_MULT_ONEHUNDREDTH, AST_AOC_MULT_ONETENTH, AST_AOC_MULT_ONETHOUSANDTH, AST_AOC_MULT_TEN, AST_AOC_MULT_THOUSAND, ast_aoc_set_association_id(), ast_aoc_set_association_number(), ast_aoc_set_billing_id(), ast_aoc_set_currency_info(), ast_aoc_set_total_type(), AST_AOC_SUBTOTAL, AST_AOC_TOTAL, ast_channel_get_by_name(), ast_channel_get_by_name_prefix(), ast_channel_unref, AST_CONTROL_AOC, ast_indicate_data(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_aoc_unit_entry::type, ast_aoc_unit_entry::valid_amount, and ast_aoc_unit_entry::valid_type.

Referenced by __init_manager().

03743 {
03744    const char *channel = astman_get_header(m, "Channel");
03745    const char *pchannel = astman_get_header(m, "ChannelPrefix");
03746    const char *msgtype = astman_get_header(m, "MsgType");
03747    const char *chargetype = astman_get_header(m, "ChargeType");
03748    const char *currencyname = astman_get_header(m, "CurrencyName");
03749    const char *currencyamount = astman_get_header(m, "CurrencyAmount");
03750    const char *mult = astman_get_header(m, "CurrencyMultiplier");
03751    const char *totaltype = astman_get_header(m, "TotalType");
03752    const char *aocbillingid = astman_get_header(m, "AOCBillingId");
03753    const char *association_id= astman_get_header(m, "ChargingAssociationId");
03754    const char *association_num = astman_get_header(m, "ChargingAssociationNumber");
03755    const char *association_plan = astman_get_header(m, "ChargingAssociationPlan");
03756 
03757    enum ast_aoc_type _msgtype;
03758    enum ast_aoc_charge_type _chargetype;
03759    enum ast_aoc_currency_multiplier _mult = AST_AOC_MULT_ONE;
03760    enum ast_aoc_total_type _totaltype = AST_AOC_TOTAL;
03761    enum ast_aoc_billing_id _billingid = AST_AOC_BILLING_NA;
03762    unsigned int _currencyamount = 0;
03763    int _association_id = 0;
03764    unsigned int _association_plan = 0;
03765    struct ast_channel *chan = NULL;
03766 
03767    struct ast_aoc_decoded *decoded = NULL;
03768    struct ast_aoc_encoded *encoded = NULL;
03769    size_t encoded_size = 0;
03770 
03771    if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) {
03772       astman_send_error(s, m, "Channel and PartialChannel are not specified. Specify at least one of these.");
03773       goto aocmessage_cleanup;
03774    }
03775 
03776    if (!(chan = ast_channel_get_by_name(channel)) && !ast_strlen_zero(pchannel)) {
03777       chan = ast_channel_get_by_name_prefix(pchannel, strlen(pchannel));
03778    }
03779 
03780    if (!chan) {
03781       astman_send_error(s, m, "No such channel");
03782       goto aocmessage_cleanup;
03783    }
03784 
03785    if (ast_strlen_zero(msgtype) || (strcasecmp(msgtype, "d") && strcasecmp(msgtype, "e"))) {
03786       astman_send_error(s, m, "Invalid MsgType");
03787       goto aocmessage_cleanup;
03788    }
03789 
03790    if (ast_strlen_zero(chargetype)) {
03791       astman_send_error(s, m, "ChargeType not specified");
03792       goto aocmessage_cleanup;
03793    }
03794 
03795    _msgtype = strcasecmp(msgtype, "d") ? AST_AOC_E : AST_AOC_D;
03796 
03797    if (!strcasecmp(chargetype, "NA")) {
03798       _chargetype = AST_AOC_CHARGE_NA;
03799    } else if (!strcasecmp(chargetype, "Free")) {
03800       _chargetype = AST_AOC_CHARGE_FREE;
03801    } else if (!strcasecmp(chargetype, "Currency")) {
03802       _chargetype = AST_AOC_CHARGE_CURRENCY;
03803    } else if (!strcasecmp(chargetype, "Unit")) {
03804       _chargetype = AST_AOC_CHARGE_UNIT;
03805    } else {
03806       astman_send_error(s, m, "Invalid ChargeType");
03807       goto aocmessage_cleanup;
03808    }
03809 
03810    if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
03811 
03812       if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u", &_currencyamount) != 1)) {
03813          astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency");
03814          goto aocmessage_cleanup;
03815       }
03816 
03817       if (ast_strlen_zero(mult)) {
03818          astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency.");
03819          goto aocmessage_cleanup;
03820       } else if (!strcasecmp(mult, "onethousandth")) {
03821          _mult = AST_AOC_MULT_ONETHOUSANDTH;
03822       } else if (!strcasecmp(mult, "onehundredth")) {
03823          _mult = AST_AOC_MULT_ONEHUNDREDTH;
03824       } else if (!strcasecmp(mult, "onetenth")) {
03825          _mult = AST_AOC_MULT_ONETENTH;
03826       } else if (!strcasecmp(mult, "one")) {
03827          _mult = AST_AOC_MULT_ONE;
03828       } else if (!strcasecmp(mult, "ten")) {
03829          _mult = AST_AOC_MULT_TEN;
03830       } else if (!strcasecmp(mult, "hundred")) {
03831          _mult = AST_AOC_MULT_HUNDRED;
03832       } else if (!strcasecmp(mult, "thousand")) {
03833          _mult = AST_AOC_MULT_THOUSAND;
03834       } else {
03835          astman_send_error(s, m, "Invalid ChargeMultiplier");
03836          goto aocmessage_cleanup;
03837       }
03838    }
03839 
03840    /* create decoded object and start setting values */
03841    if (!(decoded = ast_aoc_create(_msgtype, _chargetype, 0))) {
03842          astman_send_error(s, m, "Message Creation Failed");
03843          goto aocmessage_cleanup;
03844    }
03845 
03846    if (_msgtype == AST_AOC_D) {
03847       if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype, "subtotal")) {
03848          _totaltype = AST_AOC_SUBTOTAL;
03849       }
03850 
03851       if (ast_strlen_zero(aocbillingid)) {
03852          /* ignore this is optional */
03853       } else if (!strcasecmp(aocbillingid, "Normal")) {
03854          _billingid = AST_AOC_BILLING_NORMAL;
03855       } else if (!strcasecmp(aocbillingid, "ReverseCharge")) {
03856          _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
03857       } else if (!strcasecmp(aocbillingid, "CreditCard")) {
03858          _billingid = AST_AOC_BILLING_CREDIT_CARD;
03859       } else {
03860          astman_send_error(s, m, "Invalid AOC-D AOCBillingId");
03861          goto aocmessage_cleanup;
03862       }
03863    } else {
03864       if (ast_strlen_zero(aocbillingid)) {
03865          /* ignore this is optional */
03866       } else if (!strcasecmp(aocbillingid, "Normal")) {
03867          _billingid = AST_AOC_BILLING_NORMAL;
03868       } else if (!strcasecmp(aocbillingid, "ReverseCharge")) {
03869          _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
03870       } else if (!strcasecmp(aocbillingid, "CreditCard")) {
03871          _billingid = AST_AOC_BILLING_CREDIT_CARD;
03872       } else if (!strcasecmp(aocbillingid, "CallFwdUnconditional")) {
03873          _billingid = AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL;
03874       } else if (!strcasecmp(aocbillingid, "CallFwdBusy")) {
03875          _billingid = AST_AOC_BILLING_CALL_FWD_BUSY;
03876       } else if (!strcasecmp(aocbillingid, "CallFwdNoReply")) {
03877          _billingid = AST_AOC_BILLING_CALL_FWD_NO_REPLY;
03878       } else if (!strcasecmp(aocbillingid, "CallDeflection")) {
03879          _billingid = AST_AOC_BILLING_CALL_DEFLECTION;
03880       } else if (!strcasecmp(aocbillingid, "CallTransfer")) {
03881          _billingid = AST_AOC_BILLING_CALL_TRANSFER;
03882       } else {
03883          astman_send_error(s, m, "Invalid AOC-E AOCBillingId");
03884          goto aocmessage_cleanup;
03885       }
03886 
03887       if (!ast_strlen_zero(association_id) && (sscanf(association_id, "%30d", &_association_id) != 1)) {
03888          astman_send_error(s, m, "Invalid ChargingAssociationId");
03889          goto aocmessage_cleanup;
03890       }
03891       if (!ast_strlen_zero(association_plan) && (sscanf(association_plan, "%30u", &_association_plan) != 1)) {
03892          astman_send_error(s, m, "Invalid ChargingAssociationPlan");
03893          goto aocmessage_cleanup;
03894       }
03895 
03896       if (_association_id) {
03897          ast_aoc_set_association_id(decoded, _association_id);
03898       } else if (!ast_strlen_zero(association_num)) {
03899          ast_aoc_set_association_number(decoded, association_num, _association_plan);
03900       }
03901    }
03902 
03903    if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
03904       ast_aoc_set_currency_info(decoded, _currencyamount, _mult, ast_strlen_zero(currencyname) ? NULL : currencyname);
03905    } else if (_chargetype == AST_AOC_CHARGE_UNIT) {
03906       struct ast_aoc_unit_entry entry;
03907       int i;
03908 
03909       /* multiple unit entries are possible, lets get them all */
03910       for (i = 0; i < 32; i++) {
03911          if (aocmessage_get_unit_entry(m, &entry, i)) {
03912             break; /* that's the end then */
03913          }
03914 
03915          ast_aoc_add_unit_entry(decoded, entry.valid_amount, entry.amount, entry.valid_type, entry.type);
03916       }
03917 
03918       /* at least one unit entry is required */
03919       if (!i) {
03920          astman_send_error(s, m, "Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit");
03921          goto aocmessage_cleanup;
03922       }
03923 
03924    }
03925 
03926    ast_aoc_set_billing_id(decoded, _billingid);
03927    ast_aoc_set_total_type(decoded, _totaltype);
03928 
03929 
03930    if ((encoded = ast_aoc_encode(decoded, &encoded_size, NULL)) && !ast_indicate_data(chan, AST_CONTROL_AOC, encoded, encoded_size)) {
03931       astman_send_ack(s, m, "AOC Message successfully queued on channel");
03932    } else {
03933       astman_send_error(s, m, "Error encoding AOC message, could not queue onto channel");
03934    }
03935 
03936 aocmessage_cleanup:
03937 
03938    ast_aoc_destroy_decoded(decoded);
03939    ast_aoc_destroy_encoded(encoded);
03940 
03941    if (chan) {
03942       chan = ast_channel_unref(chan);
03943    }
03944    return 0;
03945 }

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

Definition at line 3506 of file manager.c.

References ast_channel_get_by_name(), ast_channel_unref, ast_find_call_feature(), AST_FRAME_DTMF, ast_queue_frame(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), context, ast_call_feature::exten, exten, f, ast_frame_subclass::integer, name, pbx_builtin_setvar_helper(), and ast_frame::subclass.

Referenced by __init_manager().

03507 {
03508    const char *name = astman_get_header(m, "Channel");
03509    const char *exten = astman_get_header(m, "Exten");
03510    const char *context = astman_get_header(m, "Context");
03511    struct ast_channel *chan = NULL;
03512    struct ast_call_feature *atxfer_feature = NULL;
03513    char *feature_code = NULL;
03514 
03515    if (ast_strlen_zero(name)) {
03516       astman_send_error(s, m, "No channel specified");
03517       return 0;
03518    }
03519    if (ast_strlen_zero(exten)) {
03520       astman_send_error(s, m, "No extension specified");
03521       return 0;
03522    }
03523 
03524    if (!(atxfer_feature = ast_find_call_feature("atxfer"))) {
03525       astman_send_error(s, m, "No attended transfer feature found");
03526       return 0;
03527    }
03528 
03529    if (!(chan = ast_channel_get_by_name(name))) {
03530       astman_send_error(s, m, "Channel specified does not exist");
03531       return 0;
03532    }
03533 
03534    if (!ast_strlen_zero(context)) {
03535       pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context);
03536    }
03537 
03538    for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) {
03539       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code };
03540       ast_queue_frame(chan, &f);
03541    }
03542 
03543    for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) {
03544       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code };
03545       ast_queue_frame(chan, &f);
03546    }
03547 
03548    chan = ast_channel_unref(chan);
03549 
03550    astman_send_ack(s, m, "Atxfer successfully queued");
03551 
03552    return 0;
03553 }

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

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

03070 {
03071    const char *authtype = astman_get_header(m, "AuthType");
03072 
03073    if (!strcasecmp(authtype, "MD5")) {
03074       if (ast_strlen_zero(s->session->challenge)) {
03075          snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
03076       }
03077       mansession_lock(s);
03078       astman_start_ack(s, m);
03079       astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
03080       mansession_unlock(s);
03081    } else {
03082       astman_send_error(s, m, "Must specify AuthType");
03083    }
03084    return 0;
03085 }

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

Manager command "command" - execute CLI command.

Definition at line 3591 of file manager.c.

References ast_calloc, ast_cli_command, ast_free, ast_log(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), check_blacklist(), errno, LOG_WARNING, S_OR, and term_strip().

Referenced by __init_manager().

03592 {
03593    const char *cmd = astman_get_header(m, "Command");
03594    const char *id = astman_get_header(m, "ActionID");
03595    char *buf, *final_buf;
03596    char template[] = "/tmp/ast-ami-XXXXXX";  /* template for temporary file */
03597    int fd;
03598    off_t l;
03599 
03600    if (ast_strlen_zero(cmd)) {
03601       astman_send_error(s, m, "No command provided");
03602       return 0;
03603    }
03604 
03605    if (check_blacklist(cmd)) {
03606       astman_send_error(s, m, "Command blacklisted");
03607       return 0;
03608    }
03609 
03610    fd = mkstemp(template);
03611 
03612    astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
03613    if (!ast_strlen_zero(id)) {
03614       astman_append(s, "ActionID: %s\r\n", id);
03615    }
03616    /* FIXME: Wedge a ActionID response in here, waiting for later changes */
03617    ast_cli_command(fd, cmd);  /* XXX need to change this to use a FILE * */
03618    l = lseek(fd, 0, SEEK_END);   /* how many chars available */
03619 
03620    /* This has a potential to overflow the stack.  Hence, use the heap. */
03621    buf = ast_calloc(1, l + 1);
03622    final_buf = ast_calloc(1, l + 1);
03623    if (buf) {
03624       lseek(fd, 0, SEEK_SET);
03625       if (read(fd, buf, l) < 0) {
03626          ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
03627       }
03628       buf[l] = '\0';
03629       if (final_buf) {
03630          term_strip(final_buf, buf, l);
03631          final_buf[l] = '\0';
03632       }
03633       astman_append(s, "%s", S_OR(final_buf, buf));
03634       ast_free(buf);
03635    }
03636    close(fd);
03637    unlink(template);
03638    astman_append(s, "--END COMMAND--\r\n\r\n");
03639    if (final_buf) {
03640       ast_free(final_buf);
03641    }
03642    return 0;
03643 }

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

Show PBX core settings information.

Definition at line 4286 of file manager.c.

References AMI_VERSION, AST_CLI_YESNO, ast_config_AST_RUN_GROUP, ast_config_AST_RUN_USER, ast_config_AST_SYSTEM_NAME, ast_get_version(), ast_realtime_enabled(), ast_strlen_zero(), astman_append(), astman_get_header(), check_cdr_enabled(), check_webmanager_enabled(), option_maxcalls, option_maxfiles, and option_maxload.

Referenced by __init_manager().

04287 {
04288    const char *actionid = astman_get_header(m, "ActionID");
04289    char idText[150];
04290 
04291    if (!ast_strlen_zero(actionid)) {
04292       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
04293    } else {
04294       idText[0] = '\0';
04295    }
04296 
04297    astman_append(s, "Response: Success\r\n"
04298          "%s"
04299          "AMIversion: %s\r\n"
04300          "AsteriskVersion: %s\r\n"
04301          "SystemName: %s\r\n"
04302          "CoreMaxCalls: %d\r\n"
04303          "CoreMaxLoadAvg: %f\r\n"
04304          "CoreRunUser: %s\r\n"
04305          "CoreRunGroup: %s\r\n"
04306          "CoreMaxFilehandles: %d\r\n"
04307          "CoreRealTimeEnabled: %s\r\n"
04308          "CoreCDRenabled: %s\r\n"
04309          "CoreHTTPenabled: %s\r\n"
04310          "\r\n",
04311          idText,
04312          AMI_VERSION,
04313          ast_get_version(),
04314          ast_config_AST_SYSTEM_NAME,
04315          option_maxcalls,
04316          option_maxload,
04317          ast_config_AST_RUN_USER,
04318          ast_config_AST_RUN_GROUP,
04319          option_maxfiles,
04320          AST_CLI_YESNO(ast_realtime_enabled()),
04321          AST_CLI_YESNO(check_cdr_enabled()),
04322          AST_CLI_YESNO(check_webmanager_enabled())
04323          );
04324    return 0;
04325 }

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

References ast_channel::_state, ast_channel::accountcode, ast_channel::appl, ast_bridged_channel(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_state2str(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), astman_append(), astman_get_header(), astman_send_error(), astman_send_listack(), ast_channel::caller, ast_channel::cdr, ast_channel::connected, ast_channel::context, ast_channel::data, ast_channel::exten, ast_party_connected_line::id, ast_party_caller::id, ast_party_id::name, ast_channel::name, ast_party_id::number, ast_channel::priority, S_COR, S_OR, ast_cdr::start, ast_party_name::str, ast_party_number::str, ast_channel::uniqueid, ast_party_name::valid, and ast_party_number::valid.

Referenced by __init_manager().

04384 {
04385    const char *actionid = astman_get_header(m, "ActionID");
04386    char idText[256];
04387    struct ast_channel *c = NULL;
04388    int numchans = 0;
04389    int duration, durh, durm, durs;
04390    struct ast_channel_iterator *iter;
04391 
04392    if (!ast_strlen_zero(actionid)) {
04393       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
04394    } else {
04395       idText[0] = '\0';
04396    }
04397 
04398    if (!(iter = ast_channel_iterator_all_new())) {
04399       astman_send_error(s, m, "Memory Allocation Failure");
04400       return 1;
04401    }
04402 
04403    astman_send_listack(s, m, "Channels will follow", "start");
04404 
04405    for (; (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) {
04406       struct ast_channel *bc;
04407       char durbuf[10] = "";
04408 
04409       ast_channel_lock(c);
04410 
04411       bc = ast_bridged_channel(c);
04412       if (c->cdr && !ast_tvzero(c->cdr->start)) {
04413          duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
04414          durh = duration / 3600;
04415          durm = (duration % 3600) / 60;
04416          durs = duration % 60;
04417          snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
04418       }
04419 
04420       astman_append(s,
04421          "Event: CoreShowChannel\r\n"
04422          "%s"
04423          "Channel: %s\r\n"
04424          "UniqueID: %s\r\n"
04425          "Context: %s\r\n"
04426          "Extension: %s\r\n"
04427          "Priority: %d\r\n"
04428          "ChannelState: %d\r\n"
04429          "ChannelStateDesc: %s\r\n"
04430          "Application: %s\r\n"
04431          "ApplicationData: %s\r\n"
04432          "CallerIDnum: %s\r\n"
04433          "CallerIDname: %s\r\n"
04434          "ConnectedLineNum: %s\r\n"
04435          "ConnectedLineName: %s\r\n"
04436          "Duration: %s\r\n"
04437          "AccountCode: %s\r\n"
04438          "BridgedChannel: %s\r\n"
04439          "BridgedUniqueID: %s\r\n"
04440          "\r\n", idText, c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state,
04441          ast_state2str(c->_state), c->appl ? c->appl : "", c->data ? S_OR(c->data, "") : "",
04442          S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""),
04443          S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""),
04444          S_COR(c->connected.id.number.valid, c->connected.id.number.str, ""),
04445          S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""),
04446          durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : "");
04447 
04448       ast_channel_unlock(c);
04449 
04450       numchans++;
04451    }
04452 
04453    astman_append(s,
04454       "Event: CoreShowChannelsComplete\r\n"
04455       "EventList: Complete\r\n"
04456       "ListItems: %d\r\n"
04457       "%s"
04458       "\r\n", numchans, idText);
04459 
04460    ast_channel_iterator_destroy(iter);
04461 
04462    return 0;
04463 }

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

Show PBX core status information.

Definition at line 4328 of file manager.c.

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

Referenced by __init_manager().

04329 {
04330    const char *actionid = astman_get_header(m, "ActionID");
04331    char idText[150];
04332    char startuptime[150], startupdate[150];
04333    char reloadtime[150], reloaddate[150];
04334    struct ast_tm tm;
04335 
04336    if (!ast_strlen_zero(actionid)) {
04337       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
04338    } else {
04339       idText[0] = '\0';
04340    }
04341 
04342    ast_localtime(&ast_startuptime, &tm, NULL);
04343    ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm);
04344    ast_strftime(startupdate, sizeof(startupdate), "%Y-%m-%d", &tm);
04345    ast_localtime(&ast_lastreloadtime, &tm, NULL);
04346    ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm);
04347    ast_strftime(reloaddate, sizeof(reloaddate), "%Y-%m-%d", &tm);
04348 
04349    astman_append(s, "Response: Success\r\n"
04350          "%s"
04351          "CoreStartupDate: %s\r\n"
04352          "CoreStartupTime: %s\r\n"
04353          "CoreReloadDate: %s\r\n"
04354          "CoreReloadTime: %s\r\n"
04355          "CoreCurrentCalls: %d\r\n"
04356          "\r\n",
04357          idText,
04358          startupdate,
04359          startuptime,
04360          reloaddate,
04361          reloadtime,
04362          ast_active_channels()
04363          );
04364    return 0;
04365 }

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

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

02846 {
02847    int fd;
02848    const char *fn = astman_get_header(m, "Filename");
02849    struct ast_str *filepath = ast_str_alloca(PATH_MAX);
02850    ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR);
02851    ast_str_append(&filepath, 0, "%s", fn);
02852 
02853    if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
02854       close(fd);
02855       astman_send_ack(s, m, "New configuration file created successfully");
02856    } else {
02857       astman_send_error(s, m, strerror(errno));
02858    }
02859 
02860    return 0;
02861 }

static void action_destroy ( void *  obj  )  [static]

Definition at line 5201 of file manager.c.

References ast_string_field_free_memory.

Referenced by ast_manager_register2().

05202 {
05203    struct manager_action *doomed = obj;
05204 
05205    if (doomed->synopsis) {
05206       /* The string fields were initialized. */
05207       ast_string_field_free_memory(doomed);
05208    }
05209 }

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

Definition at line 2988 of file manager.c.

References ARRAY_LEN, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), broken_events_action, perms, and set_eventmask().

Referenced by __init_manager().

02989 {
02990    const char *mask = astman_get_header(m, "EventMask");
02991    int res, x;
02992    const char *id = astman_get_header(m, "ActionID");
02993    char id_text[256];
02994 
02995    if (!ast_strlen_zero(id)) {
02996       snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
02997    } else {
02998       id_text[0] = '\0';
02999    }
03000 
03001    res = set_eventmask(s, mask);
03002    if (broken_events_action) {
03003       /* if this option is set we should not return a response on
03004        * error, or when all events are set */
03005 
03006       if (res > 0) {
03007          for (x = 0; x < ARRAY_LEN(perms); x++) {
03008             if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) {
03009                return 0;
03010             }
03011          }
03012          astman_append(s, "Response: Success\r\n%s"
03013                 "Events: On\r\n\r\n", id_text);
03014       } else if (res == 0)
03015          astman_append(s, "Response: Success\r\n%s"
03016                 "Events: Off\r\n\r\n", id_text);
03017       return 0;
03018    }
03019 
03020    if (res > 0)
03021       astman_append(s, "Response: Success\r\n%s"
03022              "Events: On\r\n\r\n", id_text);
03023    else if (res == 0)
03024       astman_append(s, "Response: Success\r\n%s"
03025              "Events: Off\r\n\r\n", id_text);
03026    else
03027       astman_send_error(s, m, "Invalid event mask");
03028 
03029    return 0;
03030 }

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

Definition at line 4124 of file manager.c.

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

Referenced by __init_manager().

04125 {
04126    const char *exten = astman_get_header(m, "Exten");
04127    const char *context = astman_get_header(m, "Context");
04128    char hint[256] = "";
04129    int status;
04130    if (ast_strlen_zero(exten)) {
04131       astman_send_error(s, m, "Extension not specified");
04132       return 0;
04133    }
04134    if (ast_strlen_zero(context)) {
04135       context = "default";
04136    }
04137    status = ast_extension_state(NULL, context, exten);
04138    ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
04139    astman_start_ack(s, m);
04140    astman_append(s,   "Message: Extension Status\r\n"
04141             "Exten: %s\r\n"
04142             "Context: %s\r\n"
04143             "Hint: %s\r\n"
04144             "Status: %d\r\n\r\n",
04145             exten, context, hint, status);
04146    return 0;
04147 }

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

Definition at line 1059 of file manager.c.

References manager_action::action, ao2_t_ref, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, and manager_action::list.

Referenced by process_message().

01060 {
01061    struct manager_action *act;
01062 
01063    AST_RWLIST_RDLOCK(&actions);
01064    AST_RWLIST_TRAVERSE(&actions, act, list) {
01065       if (!strcasecmp(name, act->action)) {
01066          ao2_t_ref(act, +1, "found action object");
01067          break;
01068       }
01069    }
01070    AST_RWLIST_UNLOCK(&actions);
01071 
01072    return act;
01073 }

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

Definition at line 2463 of file manager.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load2(), ast_strlen_zero(), ast_variable_browse(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by __init_manager().

02464 {
02465    struct ast_config *cfg;
02466    const char *fn = astman_get_header(m, "Filename");
02467    const char *category = astman_get_header(m, "Category");
02468    int catcount = 0;
02469    int lineno = 0;
02470    char *cur_category = NULL;
02471    struct ast_variable *v;
02472    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02473 
02474    if (ast_strlen_zero(fn)) {
02475       astman_send_error(s, m, "Filename not specified");
02476       return 0;
02477    }
02478    cfg = ast_config_load2(fn, "manager", config_flags);
02479    if (cfg == CONFIG_STATUS_FILEMISSING) {
02480       astman_send_error(s, m, "Config file not found");
02481       return 0;
02482    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02483       astman_send_error(s, m, "Config file has invalid format");
02484       return 0;
02485    }
02486 
02487    astman_start_ack(s, m);
02488    while ((cur_category = ast_category_browse(cfg, cur_category))) {
02489       if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) {
02490          lineno = 0;
02491          astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category);
02492          for (v = ast_variable_browse(cfg, cur_category); v; v = v->next) {
02493             astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value);
02494          }
02495          catcount++;
02496       }
02497    }
02498    if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
02499       astman_append(s, "No categories found\r\n");
02500    }
02501    ast_config_destroy(cfg);
02502    astman_append(s, "\r\n");
02503 
02504    return 0;
02505 }

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

Definition at line 2573 of file manager.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load2(), ast_strlen_zero(), ast_variable_browse(), astman_append(), astman_append_json(), astman_get_header(), astman_send_error(), astman_start_ack(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, config_flags, CONFIG_STATUS_FILEINVALID, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by __init_manager().

02574 {
02575    struct ast_config *cfg;
02576    const char *fn = astman_get_header(m, "Filename");
02577    char *category = NULL;
02578    struct ast_variable *v;
02579    int comma1 = 0;
02580    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02581 
02582    if (ast_strlen_zero(fn)) {
02583       astman_send_error(s, m, "Filename not specified");
02584       return 0;
02585    }
02586 
02587    if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
02588       astman_send_error(s, m, "Config file not found");
02589       return 0;
02590    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02591       astman_send_error(s, m, "Config file has invalid format");
02592       return 0;
02593    }
02594 
02595    astman_start_ack(s, m);
02596    astman_append(s, "JSON: {");
02597    while ((category = ast_category_browse(cfg, category))) {
02598       int comma2 = 0;
02599 
02600       astman_append(s, "%s\"", comma1 ? "," : "");
02601       astman_append_json(s, category);
02602       astman_append(s, "\":[");
02603       comma1 = 1;
02604       for (v = ast_variable_browse(cfg, category); v; v = v->next) {
02605          astman_append(s, "%s\"", comma2 ? "," : "");
02606          astman_append_json(s, v->name);
02607          astman_append(s, "\":\"");
02608          astman_append_json(s, v->value);
02609          astman_append(s, "\"");
02610          comma2 = 1;
02611       }
02612       astman_append(s, "]");
02613    }
02614    astman_append(s, "}\r\n\r\n");
02615 
02616    ast_config_destroy(cfg);
02617 
02618    return 0;
02619 }

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

Definition at line 3163 of file manager.c.

References ast_channel_get_by_name(), ast_channel_unref, ast_dummy_channel_alloc(), ast_func_read(), ast_log(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), LOG_ERROR, name, pbx_retrieve_variable(), and S_OR.

Referenced by __init_manager().

03164 {
03165    struct ast_channel *c = NULL;
03166    const char *name = astman_get_header(m, "Channel");
03167    const char *varname = astman_get_header(m, "Variable");
03168    char *varval;
03169    char workspace[1024];
03170 
03171    if (ast_strlen_zero(varname)) {
03172       astman_send_error(s, m, "No variable specified");
03173       return 0;
03174    }
03175 
03176    if (!ast_strlen_zero(name)) {
03177       if (!(c = ast_channel_get_by_name(name))) {
03178          astman_send_error(s, m, "No such channel");
03179          return 0;
03180       }
03181    }
03182 
03183    workspace[0] = '\0';
03184    if (varname[strlen(varname) - 1] == ')') {
03185       if (!c) {
03186          c = ast_dummy_channel_alloc();
03187          if (c) {
03188             ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
03189          } else
03190             ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03191       } else {
03192          ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
03193       }
03194       varval = workspace;
03195    } else {
03196       pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
03197    }
03198 
03199    if (c) {
03200       c = ast_channel_unref(c);
03201    }
03202 
03203    astman_start_ack(s, m);
03204    astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, S_OR(varval, ""));
03205 
03206    return 0;
03207 }

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

Definition at line 3087 of file manager.c.

References ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_debug, ast_log(), AST_SOFTHANGUP_EXPLICIT, ast_softhangup_nolock(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), cause, ast_channel::hangupcause, LOG_NOTICE, ast_channel::name, and name.

Referenced by __init_manager().

03088 {
03089    struct ast_channel *c = NULL;
03090    int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */
03091    const char *name = astman_get_header(m, "Channel");
03092    const char *cause = astman_get_header(m, "Cause");
03093 
03094    if (ast_strlen_zero(name)) {
03095       astman_send_error(s, m, "No channel specified");
03096       return 0;
03097    }
03098 
03099    if (!ast_strlen_zero(cause)) {
03100       char *endptr;
03101       causecode = strtol(cause, &endptr, 10);
03102       if (causecode < 0 || causecode > 127 || *endptr != '\0') {
03103          ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause);
03104          /* keep going, better to hangup without cause than to not hang up at all */
03105          causecode = 0; /* do not set channel's hangupcause */
03106       }
03107    }
03108 
03109    if (!(c = ast_channel_get_by_name(name))) {
03110       astman_send_error(s, m, "No such channel");
03111       return 0;
03112    }
03113 
03114    ast_channel_lock(c);
03115    if (causecode > 0) {
03116       ast_debug(1, "Setting hangupcause of channel %s to %d (is %d now)\n",
03117             c->name, causecode, c->hangupcause);
03118       c->hangupcause = causecode;
03119    }
03120    ast_softhangup_nolock(c, AST_SOFTHANGUP_EXPLICIT);
03121    ast_channel_unlock(c);
03122 
03123    c = ast_channel_unref(c);
03124 
03125    astman_send_ack(s, m, "Channel Hungup");
03126 
03127    return 0;
03128 }

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

Definition at line 2507 of file manager.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load2(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, config_flags, and CONFIG_STATUS_FILEINVALID.

Referenced by __init_manager().

02508 {
02509    struct ast_config *cfg;
02510    const char *fn = astman_get_header(m, "Filename");
02511    char *category = NULL;
02512    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02513    int catcount = 0;
02514 
02515    if (ast_strlen_zero(fn)) {
02516       astman_send_error(s, m, "Filename not specified");
02517       return 0;
02518    }
02519    if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
02520       astman_send_error(s, m, "Config file not found");
02521       return 0;
02522    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02523       astman_send_error(s, m, "Config file has invalid format");
02524       return 0;
02525    }
02526    astman_start_ack(s, m);
02527    while ((category = ast_category_browse(cfg, category))) {
02528       astman_append(s, "Category-%06d: %s\r\n", catcount, category);
02529       catcount++;
02530    }
02531    if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
02532       astman_append(s, "Error: no categories found\r\n");
02533    }
02534    ast_config_destroy(cfg);
02535    astman_append(s, "\r\n");
02536 
02537    return 0;
02538 }

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

Definition at line 2969 of file manager.c.

References manager_action::action, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, astman_append(), astman_start_ack(), manager_action::authority, authority_to_str(), mansession::session, and mansession_session::writeperm.

Referenced by __init_manager().

02970 {
02971    struct manager_action *cur;
02972    struct ast_str *temp = ast_str_alloca(256);
02973 
02974    astman_start_ack(s, m);
02975    AST_RWLIST_RDLOCK(&actions);
02976    AST_RWLIST_TRAVERSE(&actions, cur, list) {
02977       if ((s->session->writeperm & cur->authority) || cur->authority == 0) {
02978          astman_append(s, "%s: %s (Priv: %s)\r\n",
02979             cur->action, cur->synopsis, authority_to_str(cur->authority, &temp));
02980       }
02981    }
02982    AST_RWLIST_UNLOCK(&actions);
02983    astman_append(s, "\r\n");
02984 
02985    return 0;
02986 }

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

Definition at line 3038 of file manager.c.

References ast_atomic_fetchadd_int(), ast_inet_ntoa(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, ast_str_alloca, ast_test_flag, ast_verb, astman_append(), astman_send_ack(), astman_send_error(), authenticate(), mansession_session::authenticated, authority_to_str(), EVENT_FLAG_SYSTEM, manager_displayconnects(), mansession_session::managerid, mansession_session::send_events, mansession::session, mansession_session::sin, unauth_sessions, and mansession_session::username.

Referenced by __init_manager().

03039 {
03040 
03041    /* still authenticated - don't process again */
03042    if (s->session->authenticated) {
03043       astman_send_ack(s, m, "Already authenticated");
03044       return 0;
03045    }
03046 
03047    if (authenticate(s, m)) {
03048       sleep(1);
03049       astman_send_error(s, m, "Authentication failed");
03050       return -1;
03051    }
03052    s->session->authenticated = 1;
03053    ast_atomic_fetchadd_int(&unauth_sessions, -1);
03054    if (manager_displayconnects(s->session)) {
03055       ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr));
03056    }
03057    astman_send_ack(s, m, "Authentication accepted");
03058    if ((s->session->send_events & EVENT_FLAG_SYSTEM)
03059       && ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
03060       struct ast_str *auth = ast_str_alloca(80);
03061       const char *cat_str = authority_to_str(EVENT_FLAG_SYSTEM, &auth);
03062       astman_append(s, "Event: FullyBooted\r\n"
03063          "Privilege: %s\r\n"
03064          "Status: Fully Booted\r\n\r\n", cat_str);
03065    }
03066    return 0;
03067 }

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

Definition at line 3032 of file manager.c.

References astman_send_response().

Referenced by __init_manager().

03033 {
03034    astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
03035    return -1;
03036 }

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

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

04104 {
04105    const char *mailbox = astman_get_header(m, "Mailbox");
04106    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;;
04107 
04108    if (ast_strlen_zero(mailbox)) {
04109       astman_send_error(s, m, "Mailbox not specified");
04110       return 0;
04111    }
04112    ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs);
04113    astman_start_ack(s, m);
04114    astman_append(s,   "Message: Mailbox Message Count\r\n"
04115             "Mailbox: %s\r\n"
04116             "UrgMessages: %d\r\n"
04117             "NewMessages: %d\r\n"
04118             "OldMessages: %d\r\n"
04119             "\r\n",
04120             mailbox, urgentmsgs, newmsgs, oldmsgs);
04121    return 0;
04122 }

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

Definition at line 4086 of file manager.c.

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

Referenced by __init_manager().

04087 {
04088    const char *mailbox = astman_get_header(m, "Mailbox");
04089    int ret;
04090 
04091    if (ast_strlen_zero(mailbox)) {
04092       astman_send_error(s, m, "Mailbox not specified");
04093       return 0;
04094    }
04095    ret = ast_app_has_voicemail(mailbox, NULL);
04096    astman_start_ack(s, m);
04097    astman_append(s, "Message: Mailbox Status\r\n"
04098           "Mailbox: %s\r\n"
04099           "Waiting: %d\r\n\r\n", mailbox, ret);
04100    return 0;
04101 }

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

Definition at line 3947 of file manager.c.

References app, ast_callerid_parse(), ast_calloc, ast_copy_string(), ast_findlabel_extension(), AST_FORMAT_SLINEAR, ast_free, ast_parse_allow_disallow(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_pthread_create_detached, ast_shrink_phone_number(), ast_string_field_build, ast_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_true(), ast_variables_destroy(), astman_get_header(), astman_get_variables(), astman_send_ack(), astman_send_error(), cid_name, cid_num, context, EVENT_FLAG_SYSTEM, exten, fast_originate(), name, mansession::session, strcasestr(), and mansession_session::writeperm.

Referenced by __init_manager().

03948 {
03949    const char *name = astman_get_header(m, "Channel");
03950    const char *exten = astman_get_header(m, "Exten");
03951    const char *context = astman_get_header(m, "Context");
03952    const char *priority = astman_get_header(m, "Priority");
03953    const char *timeout = astman_get_header(m, "Timeout");
03954    const char *callerid = astman_get_header(m, "CallerID");
03955    const char *account = astman_get_header(m, "Account");
03956    const char *app = astman_get_header(m, "Application");
03957    const char *appdata = astman_get_header(m, "Data");
03958    const char *async = astman_get_header(m, "Async");
03959    const char *id = astman_get_header(m, "ActionID");
03960    const char *codecs = astman_get_header(m, "Codecs");
03961    struct ast_variable *vars;
03962    char *tech, *data;
03963    char *l = NULL, *n = NULL;
03964    int pi = 0;
03965    int res;
03966    int to = 30000;
03967    int reason = 0;
03968    char tmp[256];
03969    char tmp2[256];
03970    format_t format = AST_FORMAT_SLINEAR;
03971 
03972    pthread_t th;
03973    if (ast_strlen_zero(name)) {
03974       astman_send_error(s, m, "Channel not specified");
03975       return 0;
03976    }
03977    if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) {
03978       if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
03979          astman_send_error(s, m, "Invalid priority");
03980          return 0;
03981       }
03982    }
03983    if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) {
03984       astman_send_error(s, m, "Invalid timeout");
03985       return 0;
03986    }
03987    ast_copy_string(tmp, name, sizeof(tmp));
03988    tech = tmp;
03989    data = strchr(tmp, '/');
03990    if (!data) {
03991       astman_send_error(s, m, "Invalid channel");
03992       return 0;
03993    }
03994    *data++ = '\0';
03995    ast_copy_string(tmp2, callerid, sizeof(tmp2));
03996    ast_callerid_parse(tmp2, &n, &l);
03997    if (n) {
03998       if (ast_strlen_zero(n)) {
03999          n = NULL;
04000       }
04001    }
04002    if (l) {
04003       ast_shrink_phone_number(l);
04004       if (ast_strlen_zero(l)) {
04005          l = NULL;
04006       }
04007    }
04008    if (!ast_strlen_zero(codecs)) {
04009       format = 0;
04010       ast_parse_allow_disallow(NULL, &format, codecs, 1);
04011    }
04012    if (!ast_strlen_zero(app)) {
04013       /* To run the System application (or anything else that goes to
04014        * shell), you must have the additional System privilege */
04015       if (!(s->session->writeperm & EVENT_FLAG_SYSTEM)
04016          && (
04017             strcasestr(app, "system") ||      /* System(rm -rf /)
04018                                                  TrySystem(rm -rf /)       */
04019             strcasestr(app, "exec") ||        /* Exec(System(rm -rf /))
04020                                                  TryExec(System(rm -rf /)) */
04021             strcasestr(app, "agi") ||         /* AGI(/bin/rm,-rf /)
04022                                                  EAGI(/bin/rm,-rf /)       */
04023             strstr(appdata, "SHELL") ||       /* NoOp(${SHELL(rm -rf /)})  */
04024             strstr(appdata, "EVAL")           /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
04025             )) {
04026          astman_send_error(s, m, "Originate with certain 'Application' arguments requires the additional System privilege, which you do not have.");
04027          return 0;
04028       }
04029    }
04030    /* Allocate requested channel variables */
04031    vars = astman_get_variables(m);
04032 
04033    if (ast_true(async)) {
04034       struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast));
04035       if (!fast || ast_string_field_init(fast, 252)) {
04036          if (fast) {
04037             ast_free(fast);
04038          }
04039          res = -1;
04040       } else {
04041          if (!ast_strlen_zero(id)) {
04042             ast_string_field_build(fast, idtext, "ActionID: %s", id);
04043          }
04044          ast_copy_string(fast->tech, tech, sizeof(fast->tech));
04045          ast_copy_string(fast->data, data, sizeof(fast->data));
04046          ast_string_field_set(fast, app, app);
04047          ast_string_field_set(fast, appdata, appdata);
04048          ast_string_field_set(fast, cid_num, l);
04049          ast_string_field_set(fast, cid_name, n);
04050          ast_string_field_set(fast, context, context);
04051          ast_string_field_set(fast, exten, exten);
04052          ast_string_field_set(fast, account, account);
04053          fast->vars = vars;
04054          fast->format = format;
04055          fast->timeout = to;
04056          fast->priority = pi;
04057          if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) {
04058             ast_string_field_free_memory(fast);
04059             ast_free(fast);
04060             res = -1;
04061          } else {
04062             res = 0;
04063          }
04064       }
04065    } else if (!ast_strlen_zero(app)) {
04066       res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
04067    } else {
04068       if (exten && context && pi) {
04069          res = ast_pbx_outgoing_exten(tech, format, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
04070       } else {
04071          astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
04072          if (vars) {
04073             ast_variables_destroy(vars);
04074          }
04075          return 0;
04076       }
04077    }
04078    if (!res) {
04079       astman_send_ack(s, m, "Originate successfully queued");
04080    } else {
04081       astman_send_error(s, m, "Originate failed");
04082    }
04083    return 0;
04084 }

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

Definition at line 2445 of file manager.c.

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

Referenced by __init_manager().

02446 {
02447    const char *actionid = astman_get_header(m, "ActionID");
02448    struct timeval now = ast_tvnow();
02449 
02450    astman_append(s, "Response: Success\r\n");
02451    if (!ast_strlen_zero(actionid)){
02452       astman_append(s, "ActionID: %s\r\n", actionid);
02453    }
02454    astman_append(
02455       s,
02456       "Ping: Pong\r\n"
02457       "Timestamp: %ld.%06lu\r\n"
02458       "\r\n",
02459       (long) now.tv_sec, (unsigned long) now.tv_usec);
02460    return 0;
02461 }

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

action_redirect: The redirect manager command

Definition at line 3403 of file manager.c.

References ast_async_goto(), ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_check_hangup_locked(), ast_findlabel_extension(), AST_FLAG_BRIDGE_HANGUP_DONT, ast_set_flag, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), context, exten, name, ast_channel::pbx, and ast_channel::priority.

Referenced by __init_manager().

03404 {
03405    const char *name = astman_get_header(m, "Channel");
03406    const char *name2 = astman_get_header(m, "ExtraChannel");
03407    const char *exten = astman_get_header(m, "Exten");
03408    const char *exten2 = astman_get_header(m, "ExtraExten");
03409    const char *context = astman_get_header(m, "Context");
03410    const char *context2 = astman_get_header(m, "ExtraContext");
03411    const char *priority = astman_get_header(m, "Priority");
03412    const char *priority2 = astman_get_header(m, "ExtraPriority");
03413    struct ast_channel *chan, *chan2 = NULL;
03414    int pi, pi2 = 0;
03415    int res;
03416 
03417    if (ast_strlen_zero(name)) {
03418       astman_send_error(s, m, "Channel not specified");
03419       return 0;
03420    }
03421 
03422    if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) {
03423       if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
03424          astman_send_error(s, m, "Invalid priority");
03425          return 0;
03426       }
03427    }
03428 
03429    if (!ast_strlen_zero(priority2) && (sscanf(priority2, "%30d", &pi2) != 1)) {
03430       if ((pi2 = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL)) < 1) {
03431          astman_send_error(s, m, "Invalid ExtraPriority");
03432          return 0;
03433       }
03434    }
03435 
03436    if (!(chan = ast_channel_get_by_name(name))) {
03437       char buf[256];
03438       snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
03439       astman_send_error(s, m, buf);
03440       return 0;
03441    }
03442 
03443    if (ast_check_hangup_locked(chan)) {
03444       astman_send_error(s, m, "Redirect failed, channel not up.");
03445       chan = ast_channel_unref(chan);
03446       return 0;
03447    }
03448 
03449    if (!ast_strlen_zero(name2)) {
03450       chan2 = ast_channel_get_by_name(name2);
03451    }
03452 
03453    if (chan2 && ast_check_hangup_locked(chan2)) {
03454       astman_send_error(s, m, "Redirect failed, extra channel not up.");
03455       chan = ast_channel_unref(chan);
03456       chan2 = ast_channel_unref(chan2);
03457       return 0;
03458    }
03459 
03460    if (chan->pbx) {
03461       ast_channel_lock(chan);
03462       ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
03463       ast_channel_unlock(chan);
03464    }
03465 
03466    res = ast_async_goto(chan, context, exten, pi);
03467    if (!res) {
03468       if (!ast_strlen_zero(name2)) {
03469          if (chan2) {
03470             if (chan2->pbx) {
03471                ast_channel_lock(chan2);
03472                ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
03473                ast_channel_unlock(chan2);
03474             }
03475             if (context2) {
03476                res = ast_async_goto(chan2, context2, exten2, pi2);
03477             } else {
03478                res = ast_async_goto(chan2, context, exten, pi);
03479             }
03480          } else {
03481             res = -1;
03482          }
03483          if (!res) {
03484             astman_send_ack(s, m, "Dual Redirect successful");
03485          } else {
03486             astman_send_error(s, m, "Secondary redirect failed");
03487          }
03488       } else {
03489          astman_send_ack(s, m, "Redirect successful");
03490       }
03491    } else {
03492       astman_send_error(s, m, "Redirect failed");
03493    }
03494 
03495    if (chan) {
03496       chan = ast_channel_unref(chan);
03497    }
03498 
03499    if (chan2) {
03500       chan2 = ast_channel_unref(chan2);
03501    }
03502 
03503    return 0;
03504 }

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

Send a reload event.

Definition at line 4368 of file manager.c.

References ast_module_reload(), astman_get_header(), astman_send_ack(), astman_send_error(), and S_OR.

Referenced by __init_manager().

04369 {
04370    const char *module = astman_get_header(m, "Module");
04371    int res = ast_module_reload(S_OR(module, NULL));
04372 
04373    if (res == 2) {
04374       astman_send_ack(s, m, "Module Reloaded");
04375    } else {
04376       astman_send_error(s, m, s == 0 ? "No such module" : "Module does not support reload");
04377    }
04378    return 0;
04379 }

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

Definition at line 3368 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(), and name.

Referenced by __init_manager().

03369 {
03370    struct ast_channel *c = NULL;
03371    const char *name = astman_get_header(m, "Channel");
03372    const char *textmsg = astman_get_header(m, "Message");
03373    int res = 0;
03374 
03375    if (ast_strlen_zero(name)) {
03376       astman_send_error(s, m, "No channel specified");
03377       return 0;
03378    }
03379 
03380    if (ast_strlen_zero(textmsg)) {
03381       astman_send_error(s, m, "No Message specified");
03382       return 0;
03383    }
03384 
03385    if (!(c = ast_channel_get_by_name(name))) {
03386       astman_send_error(s, m, "No such channel");
03387       return 0;
03388    }
03389 
03390    res = ast_sendtext(c, textmsg);
03391    c = ast_channel_unref(c);
03392 
03393    if (res >= 0) {
03394       astman_send_ack(s, m, "Success");
03395    } else {
03396       astman_send_error(s, m, "Failure");
03397    }
03398 
03399    return res;
03400 }

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

Definition at line 3130 of file manager.c.

References ast_channel_get_by_name(), ast_channel_unref, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), name, pbx_builtin_setvar_helper(), and S_OR.

Referenced by __init_manager().

03131 {
03132    struct ast_channel *c = NULL;
03133    const char *name = astman_get_header(m, "Channel");
03134    const char *varname = astman_get_header(m, "Variable");
03135    const char *varval = astman_get_header(m, "Value");
03136    int res = 0;
03137    
03138    if (ast_strlen_zero(varname)) {
03139       astman_send_error(s, m, "No variable specified");
03140       return 0;
03141    }
03142 
03143    if (!ast_strlen_zero(name)) {
03144       if (!(c = ast_channel_get_by_name(name))) {
03145          astman_send_error(s, m, "No such channel");
03146          return 0;
03147       }
03148    }
03149 
03150    res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
03151 
03152    if (c) {
03153       c = ast_channel_unref(c);
03154    }
03155    if (res == 0) {
03156       astman_send_ack(s, m, "Variable Set"); 
03157    } else {
03158       astman_send_error(s, m, "Variable not set");
03159    }
03160    return 0;
03161 }

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

Manager "status" command to show channels.

Definition at line 3211 of file manager.c.

References AST_APP_ARG, ast_channel_get_by_name(), ast_channel_iterator_all_new(), ast_channel_iterator_next(), ast_channel_lock, AST_DECLARE_APP_ARGS, ast_free, ast_func_read(), AST_STANDARD_APP_ARGS, ast_str_append(), ast_str_create(), ast_str_reset(), ast_strdupa, ast_strlen_zero(), ast_tvnow(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_channel::bridge, channels, ast_channel::name, name, pbx_retrieve_variable(), S_OR, and str.

Referenced by __init_manager().

03212 {
03213    const char *name = astman_get_header(m, "Channel");
03214    const char *cvariables = astman_get_header(m, "Variables");
03215    char *variables = ast_strdupa(S_OR(cvariables, ""));
03216    struct ast_channel *c;
03217    char bridge[256];
03218    struct timeval now = ast_tvnow();
03219    long elapsed_seconds = 0;
03220    int channels = 0;
03221    int all = ast_strlen_zero(name); /* set if we want all channels */
03222    const char *id = astman_get_header(m, "ActionID");
03223    char idText[256];
03224    AST_DECLARE_APP_ARGS(vars,
03225       AST_APP_ARG(name)[100];
03226    );
03227    struct ast_str *str = ast_str_create(1000);
03228    struct ast_channel_iterator *iter = NULL;
03229 
03230    if (!ast_strlen_zero(id)) {
03231       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
03232    } else {
03233       idText[0] = '\0';
03234    }
03235 
03236    if (all) {
03237       if (!(iter = ast_channel_iterator_all_new())) {
03238          ast_free(str);
03239          astman_send_error(s, m, "Memory Allocation Failure");
03240          return 1;
03241       }
03242       c = ast_channel_iterator_next(iter);
03243    } else {
03244       if (!(c = ast_channel_get_by_name(name))) {
03245          astman_send_error(s, m, "No such channel");
03246          ast_free(str);
03247          return 0;
03248       }
03249    }
03250 
03251    astman_send_ack(s, m, "Channel status will follow");
03252 
03253    if (!ast_strlen_zero(cvariables)) {
03254       AST_STANDARD_APP_ARGS(vars, variables);
03255    }
03256 
03257    /* if we look by name, we break after the first iteration */
03258    for (; c; c = ast_channel_iterator_next(iter)) {
03259       ast_channel_lock(c);
03260 
03261       if (!ast_strlen_zero(cvariables)) {
03262          int i;
03263          ast_str_reset(str);
03264          for (i = 0; i < vars.argc; i++) {
03265             char valbuf[512], *ret = NULL;
03266 
03267             if (vars.name[i][strlen(vars.name[i]) - 1] == ')') {
03268                if (ast_func_read(c, vars.name[i], valbuf, sizeof(valbuf)) < 0) {
03269                   valbuf[0] = '\0';
03270                }
03271                ret = valbuf;
03272             } else {
03273                pbx_retrieve_variable(c, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL);
03274             }
03275 
03276             ast_str_append(&str, 0, "Variable: %s=%s\r\n", vars.name[i], ret);
03277          }
03278       }
03279 
03280       channels++;
03281       if (c->_bridge) {
03282          snprintf(bridge, sizeof(bridge), "BridgedChannel: %s\r\nBridgedUniqueid: %s\r\n", c->_bridge->name, c->_bridge->uniqueid);
03283       } else {
03284          bridge[0] = '\0';
03285       }
03286       if (c->pbx) {
03287          if (c->cdr) {
03288             elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
03289          }
03290          astman_append(s,
03291          "Event: Status\r\n"
03292          "Privilege: Call\r\n"
03293          "Channel: %s\r\n"
03294          "CallerIDNum: %s\r\n"
03295          "CallerIDName: %s\r\n"
03296          "ConnectedLineNum: %s\r\n"
03297          "ConnectedLineName: %s\r\n"
03298          "Accountcode: %s\r\n"
03299          "ChannelState: %d\r\n"
03300          "ChannelStateDesc: %s\r\n"
03301          "Context: %s\r\n"
03302          "Extension: %s\r\n"
03303          "Priority: %d\r\n"
03304          "Seconds: %ld\r\n"
03305          "%s"
03306          "Uniqueid: %s\r\n"
03307          "%s"
03308          "%s"
03309          "\r\n",
03310          c->name,
03311          S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"),
03312          S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"),
03313          S_COR(c->connected.id.number.valid, c->connected.id.number.str, "<unknown>"),
03314          S_COR(c->connected.id.name.valid, c->connected.id.name.str, "<unknown>"),
03315          c->accountcode,
03316          c->_state,
03317          ast_state2str(c->_state), c->context,
03318          c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, ast_str_buffer(str), idText);
03319       } else {
03320          astman_append(s,
03321             "Event: Status\r\n"
03322             "Privilege: Call\r\n"
03323             "Channel: %s\r\n"
03324             "CallerIDNum: %s\r\n"
03325             "CallerIDName: %s\r\n"
03326             "ConnectedLineNum: %s\r\n"
03327             "ConnectedLineName: %s\r\n"
03328             "Account: %s\r\n"
03329             "State: %s\r\n"
03330             "%s"
03331             "Uniqueid: %s\r\n"
03332             "%s"
03333             "%s"
03334             "\r\n",
03335             c->name,
03336             S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"),
03337             S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"),
03338             S_COR(c->connected.id.number.valid, c->connected.id.number.str, "<unknown>"),
03339             S_COR(c->connected.id.name.valid, c->connected.id.name.str, "<unknown>"),
03340             c->accountcode,
03341             ast_state2str(c->_state), bridge, c->uniqueid,
03342             ast_str_buffer(str), idText);
03343       }
03344 
03345       ast_channel_unlock(c);
03346       c = ast_channel_unref(c);
03347 
03348       if (!all) {
03349          break;
03350       }
03351    }
03352 
03353    if (iter) {
03354       ast_channel_iterator_destroy(iter);
03355    }
03356 
03357    astman_append(s,
03358       "Event: StatusComplete\r\n"
03359       "%s"
03360       "Items: %d\r\n"
03361       "\r\n", idText, channels);
03362 
03363    ast_free(str);
03364 
03365    return 0;
03366 }

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

Definition at line 4149 of file manager.c.

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

Referenced by __init_manager().

04150 {
04151    struct ast_channel *c;
04152    const char *name = astman_get_header(m, "Channel");
04153    double timeout = atof(astman_get_header(m, "Timeout"));
04154    struct timeval when = { timeout, 0 };
04155 
04156    if (ast_strlen_zero(name)) {
04157       astman_send_error(s, m, "No channel specified");
04158       return 0;
04159    }
04160 
04161    if (!timeout || timeout < 0) {
04162       astman_send_error(s, m, "No timeout specified");
04163       return 0;
04164    }
04165 
04166    if (!(c = ast_channel_get_by_name(name))) {
04167       astman_send_error(s, m, "No such channel");
04168       return 0;
04169    }
04170 
04171    when.tv_usec = (timeout - when.tv_sec) * 1000000.0;
04172 
04173    ast_channel_lock(c);
04174    ast_channel_setwhentohangup_tv(c, when);
04175    ast_channel_unlock(c);
04176    c = ast_channel_unref(c);
04177 
04178    astman_send_ack(s, m, "Timeout Set");
04179 
04180    return 0;
04181 }

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

Definition at line 2767 of file manager.c.

References ast_config_destroy(), ast_config_load2(), ast_config_text_file_save(), ast_include_rename(), ast_module_reload(), ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, config_flags, CONFIG_STATUS_FILEINVALID, FAILURE_ALLOCATION, FAILURE_DELCAT, FAILURE_DELETE, FAILURE_EMPTYCAT, FAILURE_NEWCAT, FAILURE_UPDATE, handle_updates(), UNKNOWN_ACTION, UNKNOWN_CATEGORY, UNSPECIFIED_ARGUMENT, and UNSPECIFIED_CATEGORY.

Referenced by __init_manager().

02768 {
02769    struct ast_config *cfg;
02770    const char *sfn = astman_get_header(m, "SrcFilename");
02771    const char *dfn = astman_get_header(m, "DstFilename");
02772    int res;
02773    const char *rld = astman_get_header(m, "Reload");
02774    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02775    enum error_type result;
02776 
02777    if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) {
02778       astman_send_error(s, m, "Filename not specified");
02779       return 0;
02780    }
02781    if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) {
02782       astman_send_error(s, m, "Config file not found");
02783       return 0;
02784    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02785       astman_send_error(s, m, "Config file has invalid format");
02786       return 0;
02787    }
02788    result = handle_updates(s, m, cfg, dfn);
02789    if (!result) {
02790       ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */
02791       res = ast_config_text_file_save(dfn, cfg, "Manager");
02792       ast_config_destroy(cfg);
02793       if (res) {
02794          astman_send_error(s, m, "Save of config failed");
02795          return 0;
02796       }
02797       astman_send_ack(s, m, NULL);
02798       if (!ast_strlen_zero(rld)) {
02799          if (ast_true(rld)) {
02800             rld = NULL;
02801          }
02802          ast_module_reload(rld);
02803       }
02804    } else {
02805       ast_config_destroy(cfg);
02806       switch(result) {
02807       case UNKNOWN_ACTION:
02808          astman_send_error(s, m, "Unknown action command");
02809          break;
02810       case UNKNOWN_CATEGORY:
02811          astman_send_error(s, m, "Given category does not exist");
02812          break;
02813       case UNSPECIFIED_CATEGORY:
02814          astman_send_error(s, m, "Category not specified");
02815          break;
02816       case UNSPECIFIED_ARGUMENT:
02817          astman_send_error(s, m, "Problem with category, value, or line (if required)");
02818          break;
02819       case FAILURE_ALLOCATION:
02820          astman_send_error(s, m, "Memory allocation failure, this should not happen");
02821          break;
02822       case FAILURE_NEWCAT:
02823          astman_send_error(s, m, "Create category did not complete successfully");
02824          break;
02825       case FAILURE_DELCAT:
02826          astman_send_error(s, m, "Delete category did not complete successfully");
02827          break;
02828       case FAILURE_EMPTYCAT:
02829          astman_send_error(s, m, "Empty category did not complete successfully");
02830          break;
02831       case FAILURE_UPDATE:
02832          astman_send_error(s, m, "Update did not complete successfully");
02833          break;
02834       case FAILURE_DELETE:
02835          astman_send_error(s, m, "Delete did not complete successfully");
02836          break;
02837       case FAILURE_APPEND:
02838          astman_send_error(s, m, "Append did not complete successfully");
02839          break;
02840       }
02841    }
02842    return 0;
02843 }

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

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

04267 {
04268    const char *event = astman_get_header(m, "UserEvent");
04269    struct ast_str *body = ast_str_thread_get(&userevent_buf, 16);
04270    int x;
04271 
04272    ast_str_reset(body);
04273 
04274    for (x = 0; x < m->hdrcount; x++) {
04275       if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) {
04276          ast_str_append(&body, 0, "%s\r\n", m->headers[x]);
04277       }
04278    }
04279 
04280    astman_send_ack(s, m, "Event Sent");   
04281    manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, ast_str_buffer(body));
04282    return 0;
04283 }

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

Definition at line 2863 of file manager.c.

References ao2_lock, ao2_unlock, ast_debug, AST_PTHREADT_NULL, AST_RWLIST_NEXT, ast_strlen_zero(), astman_get_header(), mansession_session::last_ev, mansession_session::managerid, mansession_session::needdestroy, mansession_session::send_events, mansession::session, mansession_session::sessiontimeout, and mansession_session::waiting_thread.

Referenced by __init_manager().

02864 {
02865    const char *timeouts = astman_get_header(m, "Timeout");
02866    int timeout = -1;
02867    int x;
02868    int needexit = 0;
02869    const char *id = astman_get_header(m, "ActionID");
02870    char idText[256];
02871 
02872    if (!ast_strlen_zero(id)) {
02873       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
02874    } else {
02875       idText[0] = '\0';
02876    }
02877 
02878    if (!ast_strlen_zero(timeouts)) {
02879       sscanf(timeouts, "%30i", &timeout);
02880       if (timeout < -1) {
02881          timeout = -1;
02882       }
02883       /* XXX maybe put an upper bound, or prevent the use of 0 ? */
02884    }
02885 
02886    ao2_lock(s->session);
02887    if (s->session->waiting_thread != AST_PTHREADT_NULL) {
02888       pthread_kill(s->session->waiting_thread, SIGURG);
02889    }
02890 
02891    if (s->session->managerid) { /* AMI-over-HTTP session */
02892       /*
02893        * Make sure the timeout is within the expire time of the session,
02894        * as the client will likely abort the request if it does not see
02895        * data coming after some amount of time.
02896        */
02897       time_t now = time(NULL);
02898       int max = s->session->sessiontimeout - now - 10;
02899 
02900       if (max < 0) { /* We are already late. Strange but possible. */
02901          max = 0;
02902       }
02903       if (timeout < 0 || timeout > max) {
02904          timeout = max;
02905       }
02906       if (!s->session->send_events) {  /* make sure we record events */
02907          s->session->send_events = -1;
02908       }
02909    }
02910    ao2_unlock(s->session);
02911 
02912    /* XXX should this go inside the lock ? */
02913    s->session->waiting_thread = pthread_self(); /* let new events wake up this thread */
02914    ast_debug(1, "Starting waiting for an event!\n");
02915 
02916    for (x = 0; x < timeout || timeout < 0; x++) {
02917       ao2_lock(s->session);
02918       if (AST_RWLIST_NEXT(s->session->last_ev, eq_next)) {
02919          needexit = 1;
02920       }
02921       /* We can have multiple HTTP session point to the same mansession entry.
02922        * The way we deal with it is not very nice: newcomers kick out the previous
02923        * HTTP session. XXX this needs to be improved.
02924        */
02925       if (s->session->waiting_thread != pthread_self()) {
02926          needexit = 1;
02927       }
02928       if (s->session->needdestroy) {
02929          needexit = 1;
02930       }
02931       ao2_unlock(s->session);
02932       if (needexit) {
02933          break;
02934       }
02935       if (s->session->managerid == 0) {   /* AMI session */
02936          if (ast_wait_for_input(s->session->fd, 1000)) {
02937             break;
02938          }
02939       } else { /* HTTP session */
02940          sleep(1);
02941       }
02942    }
02943    ast_debug(1, "Finished waiting for an event!\n");
02944 
02945    ao2_lock(s->session);
02946    if (s->session->waiting_thread == pthread_self()) {
02947       struct eventqent *eqe = s->session->last_ev;
02948       astman_send_response(s, m, "Success", "Waiting for Event completed.");
02949       while ((eqe = advance_event(eqe))) {
02950          if (((s->session->readperm & eqe->category) == eqe->category) &&
02951              ((s->session->send_events & eqe->category) == eqe->category)) {
02952             astman_append(s, "%s", eqe->eventdata);
02953          }
02954          s->session->last_ev = eqe;
02955       }
02956       astman_append(s,
02957          "Event: WaitEventComplete\r\n"
02958          "%s"
02959          "\r\n", idText);
02960       s->session->waiting_thread = AST_PTHREADT_NULL;
02961    } else {
02962       ast_debug(1, "Abandoning event request!\n");
02963    }
02964    ao2_unlock(s->session);
02965 
02966    return 0;
02967 }

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

Definition at line 1737 of file manager.c.

References ast_atomic_fetchadd_int(), AST_RWLIST_NEXT, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, eventqent::eq_next, eventqent::next, and eventqent::usecount.

Referenced by process_events().

01738 {
01739    struct eventqent *next;
01740 
01741    AST_RWLIST_RDLOCK(&all_events);
01742    if ((next = AST_RWLIST_NEXT(e, eq_next))) {
01743       ast_atomic_fetchadd_int(&next->usecount, 1);
01744       ast_atomic_fetchadd_int(&e->usecount, -1);
01745    }
01746    AST_RWLIST_UNLOCK(&all_events);
01747    return next;
01748 }

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

Definition at line 3717 of file manager.c.

References ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_strlen_zero(), astman_get_header(), and str.

Referenced by action_aocmessage().

03718 {
03719    const char *unitamount;
03720    const char *unittype;
03721    struct ast_str *str = ast_str_alloca(32);
03722 
03723    memset(entry, 0, sizeof(*entry));
03724 
03725    ast_str_set(&str, 0, "UnitAmount(%u)", entry_num);
03726    unitamount = astman_get_header(m, ast_str_buffer(str));
03727 
03728    ast_str_set(&str, 0, "UnitType(%u)", entry_num);
03729    unittype = astman_get_header(m, ast_str_buffer(str));
03730 
03731    if (!ast_strlen_zero(unitamount) && (sscanf(unitamount, "%30u", &entry->amount) == 1)) {
03732       entry->valid_amount = 1;
03733    }
03734 
03735    if (!ast_strlen_zero(unittype) && sscanf(unittype, "%30u", &entry->type) == 1) {
03736       entry->valid_type = 1;
03737    }
03738 
03739    return 0;
03740 }

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

Definition at line 5003 of file manager.c.

References ast_func_read2(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_str_append(), ast_str_buffer(), ast_str_thread_get(), manager_event_funcbuf, ast_channel::name, pbx_builtin_getvar_helper(), and var.

Referenced by __ast_manager_event_multichan().

05004 {
05005    struct manager_channel_variable *var;
05006 
05007    AST_RWLIST_RDLOCK(&channelvars);
05008    AST_LIST_TRAVERSE(&channelvars, var, entry) {
05009       const char *val;
05010       struct ast_str *res;
05011 
05012       if (var->isfunc) {
05013          res = ast_str_thread_get(&manager_event_funcbuf, 16);
05014          if (res && ast_func_read2(chan, var->name, &res, 0) == 0) {
05015             val = ast_str_buffer(res);
05016          } else {
05017             val = NULL;
05018          }
05019       } else {
05020          val = pbx_builtin_getvar_helper(chan, var->name);
05021       }
05022       ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", chan->name, var->name, val ? val : "");
05023    }
05024    AST_RWLIST_UNLOCK(&channelvars);
05025 }

static int append_event ( const char *  str,
int  category 
) [static]

Definition at line 4977 of file manager.c.

References ast_atomic_fetchadd_int(), ast_malloc, AST_RWLIST_INSERT_TAIL, AST_RWLIST_NEXT, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_tvnow(), and seq.

Referenced by __ast_manager_event_multichan(), and __init_manager().

04978 {
04979    struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str));
04980    static int seq;   /* sequence number */
04981 
04982    if (!tmp) {
04983       return -1;
04984    }
04985 
04986    /* need to init all fields, because ast_malloc() does not */
04987    tmp->usecount = 0;
04988    tmp->category = category;
04989    tmp->seq = ast_atomic_fetchadd_int(&seq, 1);
04990    tmp->tv = ast_tvnow();
04991    AST_RWLIST_NEXT(tmp, eq_next) = NULL;
04992    strcpy(tmp->eventdata, str);
04993 
04994    AST_RWLIST_WRLOCK(&all_events);
04995    AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next);
04996    AST_RWLIST_UNLOCK(&all_events);
04997 
04998    return 0;
04999 }

int ast_hook_send_action ( struct manager_custom_hook hook,
const char *  msg 
)

Registered hooks can call this function to invoke actions and they will receive responses through registered callback.

Parameters:
hook the file identifier specified in manager_custom_hook struct when registering a hook
msg ami action mesage string e.g. "Action: SipPeers\r\n"
Return values:
0 on Success
non-zero on Failure

Definition at line 1880 of file manager.c.

References ARRAY_LEN, ast_strdup, message::hdrcount, message::headers, and mansession::session.

01881 {
01882    const char *action;
01883    int ret = 0;
01884    struct manager_action *act_found;
01885    struct mansession s = {.session = NULL, };
01886    struct message m = { 0 };
01887    char *dup_str;
01888    char *src;
01889    int x = 0;
01890    int curlen;
01891 
01892    if (hook == NULL) {
01893       return -1;
01894    }
01895 
01896    /* Create our own copy of the AMI action msg string. */
01897    src = dup_str = ast_strdup(msg);
01898    if (!dup_str) {
01899       return -1;
01900    }
01901 
01902    /* convert msg string to message struct */
01903    curlen = strlen(src);
01904    for (x = 0; x < curlen; x++) {
01905       int cr;  /* set if we have \r */
01906       if (src[x] == '\r' && x+1 < curlen && src[x+1] == '\n')
01907          cr = 2;  /* Found. Update length to include \r\n */
01908       else if (src[x] == '\n')
01909          cr = 1;  /* also accept \n only */
01910       else
01911          continue;
01912       /* don't keep empty lines */
01913       if (x && m.hdrcount < ARRAY_LEN(m.headers)) {
01914          /* ... but trim \r\n and terminate the header string */
01915          src[x] = '\0';
01916          m.headers[m.hdrcount++] = src;
01917       }
01918       x += cr;
01919       curlen -= x;      /* remaining size */
01920       src += x;      /* update pointer */
01921       x = -1;        /* reset loop */
01922    }
01923 
01924    action = astman_get_header(&m, "Action");
01925    if (strcasecmp(action, "login")) {
01926       act_found = action_find(action);
01927       if (act_found) {
01928          /*
01929           * we have to simulate a session for this action request
01930           * to be able to pass it down for processing
01931           * This is necessary to meet the previous design of manager.c
01932           */
01933          s.hook = hook;
01934          s.f = (void*)1; /* set this to something so our request will make it through all functions that test it*/
01935 
01936          ao2_lock(act_found);
01937          if (act_found->registered && act_found->func) {
01938             ret = act_found->func(&s, &m);
01939          } else {
01940             ret = -1;
01941          }
01942          ao2_unlock(act_found);
01943          ao2_t_ref(act_found, -1, "done with found action object");
01944       }
01945    }
01946    ast_free(dup_str);
01947    return ret;
01948 }

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

References eventqent::next.

Referenced by get_perm().

01208 {
01209    const char *val = bigstr, *next;
01210 
01211    do {
01212       if ((next = strchr(val, delim))) {
01213          if (!strncmp(val, smallstr, (next - val))) {
01214             return 1;
01215          } else {
01216             continue;
01217          }
01218       } else {
01219          return !strcmp(smallstr, val);
01220       }
01221    } while (*(val = (next + 1)));
01222 
01223    return 0;
01224 }

int ast_manager_register2 ( const char *  action,
int  authority,
int(*)(struct mansession *s, const struct message *m)  func,
const char *  synopsis,
const char *  description 
)

Register a manager command with the manager interface.

Parameters:
action Name of the requested Action:
authority Required authority for this command
func Function to call for this command
synopsis Help text (one line, up to 30 chars) for CLI manager show commands
description Help text, several lines

Definition at line 5213 of file manager.c.

References action_destroy(), ao2_alloc, ao2_t_ref, ast_free, ast_manager_register_struct(), AST_STATIC_DOC, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), and ast_xmldoc_build_syntax().

Referenced by load_module().

05214 {
05215    struct manager_action *cur;
05216 
05217    cur = ao2_alloc(sizeof(*cur), action_destroy);
05218    if (!cur) {
05219       return -1;
05220    }
05221    if (ast_string_field_init(cur, 128)) {
05222       ao2_t_ref(cur, -1, "action object creation failed");
05223       return -1;
05224    }
05225 
05226    cur->action = action;
05227    cur->authority = auth;
05228    cur->func = func;
05229 #ifdef AST_XML_DOCS
05230    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
05231       char *tmpxml;
05232 
05233       tmpxml = ast_xmldoc_build_synopsis("manager", action, NULL);
05234       ast_string_field_set(cur, synopsis, tmpxml);
05235       ast_free(tmpxml);
05236 
05237       tmpxml = ast_xmldoc_build_syntax("manager", action, NULL);
05238       ast_string_field_set(cur, syntax, tmpxml);
05239       ast_free(tmpxml);
05240 
05241       tmpxml = ast_xmldoc_build_description("manager", action, NULL);
05242       ast_string_field_set(cur, description, tmpxml);
05243       ast_free(tmpxml);
05244 
05245       tmpxml = ast_xmldoc_build_seealso("manager", action, NULL);
05246       ast_string_field_set(cur, seealso, tmpxml);
05247       ast_free(tmpxml);
05248 
05249       tmpxml = ast_xmldoc_build_arguments("manager", action, NULL);
05250       ast_string_field_set(cur, arguments, tmpxml);
05251       ast_free(tmpxml);
05252 
05253       cur->docsrc = AST_XML_DOC;
05254    } else
05255 #endif
05256    {
05257       ast_string_field_set(cur, synopsis, synopsis);
05258       ast_string_field_set(cur, description, description);
05259 #ifdef AST_XML_DOCS
05260       cur->docsrc = AST_STATIC_DOC;
05261 #endif
05262    }
05263    if (ast_manager_register_struct(cur)) {
05264       ao2_t_ref(cur, -1, "action object registration failed");
05265       return -1;
05266    }
05267 
05268    ao2_t_ref(cur, -1, "action object registration successful");
05269    return 0;
05270 }

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

References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and manager_action::list.

static int ast_manager_register_struct ( struct manager_action act  )  [static]

Definition at line 5158 of file manager.c.

References manager_action::action, ao2_t_ref, ast_log(), AST_RWLIST_INSERT_AFTER, AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, LOG_WARNING, and manager_action::registered.

Referenced by ast_manager_register2().

05159 {
05160    struct manager_action *cur, *prev = NULL;
05161 
05162    AST_RWLIST_WRLOCK(&actions);
05163    AST_RWLIST_TRAVERSE(&actions, cur, list) {
05164       int ret;
05165 
05166       ret = strcasecmp(cur->action, act->action);
05167       if (ret == 0) {
05168          ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action);
05169          AST_RWLIST_UNLOCK(&actions);
05170          return -1;
05171       }
05172       if (ret > 0) { /* Insert these alphabetically */
05173          prev = cur;
05174          break;
05175       }
05176    }
05177 
05178    ao2_t_ref(act, +1, "action object added to list");
05179    act->registered = 1;
05180    if (prev) {
05181       AST_RWLIST_INSERT_AFTER(&actions, prev, act, list);
05182    } else {
05183       AST_RWLIST_INSERT_HEAD(&actions, act, list);
05184    }
05185 
05186    ast_verb(2, "Manager registered action %s\n", act->action);
05187 
05188    AST_RWLIST_UNLOCK(&actions);
05189 
05190    return 0;
05191 }

int ast_manager_unregister ( char *  action  ) 

Unregister a registered manager command.

Parameters:
action Name of registered Action:

Definition at line 5118 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, and ast_verb.

Referenced by __unload_module(), and unload_module().

05119 {
05120    struct manager_action *cur;
05121 
05122    AST_RWLIST_WRLOCK(&actions);
05123    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) {
05124       if (!strcasecmp(action, cur->action)) {
05125          AST_RWLIST_REMOVE_CURRENT(list);
05126          break;
05127       }
05128    }
05129    AST_RWLIST_TRAVERSE_SAFE_END;
05130    AST_RWLIST_UNLOCK(&actions);
05131 
05132    if (cur) {
05133       /*
05134        * We have removed the action object from the container so we
05135        * are no longer in a hurry.
05136        */
05137       ao2_lock(cur);
05138       cur->registered = 0;
05139       ao2_unlock(cur);
05140 
05141       ao2_t_ref(cur, -1, "action object removed from list");
05142       ast_verb(2, "Manager unregistered action %s\n", action);
05143    }
05144 
05145    return 0;
05146 }

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and manager_action::list.

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

utility functions for creating AMI replies

Definition at line 1994 of file manager.c.

References ast_str_buffer(), ast_str_set_va(), ast_str_thread_get(), ast_verbose, astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE, mansession_session::f, mansession::f, send_string(), and mansession::session.

Referenced by __iax2_show_peers(), _sip_show_peer(), _sip_show_peers(), _skinny_show_device(), _skinny_show_devices(), _skinny_show_line(), _skinny_show_lines(), action_agents(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_dahdishowchannels(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_listcategories(), action_listcommands(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_ping(), ast_cli_netstats(), astman_append_json(), astman_send_response_full(), data_result_manager_output(), do_print(), manager_data_get(), manager_dbget(), manager_iax2_show_netstats(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_jabber_send(), manager_list_voicemail_users(), manager_modulecheck(), manager_mute_mixmonitor(), manager_mutestream(), manager_parking_status(), manager_queue_rule_show(), manager_queues_show(), manager_queues_status(), manager_queues_summary(), manager_rpt_local_nodes(), manager_rpt_status(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_show_registry(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), rpt_manager_do_stats(), rpt_manager_success(), and session_do().

01995 {
01996    va_list ap;
01997    struct ast_str *buf;
01998 
01999    if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
02000       return;
02001    }
02002 
02003    va_start(ap, fmt);
02004    ast_str_set_va(&buf, 0, fmt, ap);
02005    va_end(ap);
02006 
02007    if (s->f != NULL || s->session->f != NULL) {
02008       send_string(s, ast_str_buffer(buf));
02009    } else {
02010       ast_verbose("fd == -1 in astman_append, should not happen\n");
02011    }
02012 }

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

Definition at line 2564 of file manager.c.

References astman_append(), and json_escape().

Referenced by action_getconfigjson().

02565 {
02566    char *buf;
02567 
02568    buf = alloca(2 * strlen(str) + 1);
02569    json_escape(buf, str);
02570    astman_append(s, "%s", buf);
02571 }

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

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

References __astman_get_header(), and GET_HEADER_FIRST_MATCH.

Referenced by _sip_show_peer(), _sip_show_peers(), _skinny_show_devices(), _skinny_show_lines(), action_add_agi_cmd(), action_agent_logoff(), action_agents(), action_aocmessage(), action_atxfer(), action_bridge(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdishowchannels(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_originate(), action_ping(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), action_waitevent(), aocmessage_get_unit_entry(), astman_send_response_full(), authenticate(), change_monitor_action(), do_pause_or_unpause(), handle_updates(), manager_add_queue_member(), manager_data_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_jabber_send(), manager_list_voicemail_users(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_optimize_away(), manager_park(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_queue_rule_show(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), manager_rpt_status(), manager_show_dialplan(), manager_show_registry(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), meetmemute(), process_message(), rpt_manager_do_stats(), rpt_manager_success(), start_monitor_action(), and stop_monitor_action().

01801 {
01802    return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH);
01803 }

struct ast_variable* astman_get_variables ( const struct message m  ) 

Get a linked list of the Variable: headers.

Definition at line 1858 of file manager.c.

References message::hdrcount, message::headers, and man_do_variable_value().

Referenced by action_originate(), and manager_sipnotify().

01859 {
01860    int varlen;
01861    int x;
01862    struct ast_variable *head = NULL;
01863 
01864    static const char var_hdr[] = "Variable:";
01865 
01866    /* Process all "Variable:" headers. */
01867    varlen = strlen(var_hdr);
01868    for (x = 0; x < m->hdrcount; x++) {
01869       if (strncasecmp(var_hdr, m->headers[x], varlen)) {
01870          continue;
01871       }
01872       head = man_do_variable_value(head, m->headers[x] + varlen);
01873    }
01874 
01875    return head;
01876 }

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

Send ack in manager transaction.

Definition at line 2061 of file manager.c.

References astman_send_response_full().

Referenced by action_add_agi_cmd(), action_agent_logoff(), action_agents(), action_aocmessage(), action_atxfer(), action_bridge(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_dahdishowchannels(), action_hangup(), action_login(), action_originate(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), change_monitor_action(), do_pause_or_unpause(), manager_add_queue_member(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_jabber_send(), manager_list_voicemail_users(), manager_moduleload(), manager_optimize_away(), manager_park(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), meetmemute(), start_monitor_action(), and stop_monitor_action().

02062 {
02063    astman_send_response_full(s, m, "Success", msg, NULL);
02064 }

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

Send error in manager transaction.

Definition at line 2056 of file manager.c.

References astman_send_response_full().

Referenced by _sip_qualify_peer(), _sip_show_peer(), action_add_agi_cmd(), action_agent_logoff(), action_aocmessage(), action_atxfer(), action_bridge(), action_challenge(), action_command(), action_coreshowchannels(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_originate(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), change_monitor_action(), do_message(), do_pause_or_unpause(), manager_add_queue_member(), manager_data_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_jabber_send(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_optimize_away(), manager_park(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_remove_queue_member(), manager_rpt_status(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_line(), meetmemute(), process_message(), start_monitor_action(), and stop_monitor_action().

02057 {
02058    astman_send_response_full(s, m, "Error", error, NULL);
02059 }

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

Send ack in manager list transaction.

Definition at line 2071 of file manager.c.

References astman_send_response_full().

Referenced by action_coreshowchannels(), action_meetmelist(), manager_dpsendack(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_show_registry(), manager_sip_show_peers(), manager_skinny_show_devices(), and manager_skinny_show_lines().

02072 {
02073    astman_send_response_full(s, m, "Success", msg, listflag);
02074 }

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

Send response in manager transaction.

Definition at line 2051 of file manager.c.

References astman_send_response_full().

Referenced by action_logoff().

02052 {
02053    astman_send_response_full(s, m, resp, msg, NULL);
02054 }

static void astman_send_response_full ( struct mansession s,
const struct message m,
char *  resp,
char *  msg,
char *  listflag 
) [static]

Definition at line 2031 of file manager.c.

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

Referenced by astman_send_ack(), astman_send_error(), astman_send_listack(), astman_send_response(), and astman_start_ack().

02032 {
02033    const char *id = astman_get_header(m, "ActionID");
02034 
02035    astman_append(s, "Response: %s\r\n", resp);
02036    if (!ast_strlen_zero(id)) {
02037       astman_append(s, "ActionID: %s\r\n", id);
02038    }
02039    if (listflag) {
02040       astman_append(s, "EventList: %s\r\n", listflag);   /* Start, complete, cancelled */
02041    }
02042    if (msg == MSG_MOREDATA) {
02043       return;
02044    } else if (msg) {
02045       astman_append(s, "Message: %s\r\n\r\n", msg);
02046    } else {
02047       astman_append(s, "\r\n");
02048    }
02049 }

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

Definition at line 2066 of file manager.c.

References astman_send_response_full(), and MSG_MOREDATA.

Referenced by action_challenge(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_listcategories(), action_listcommands(), action_mailboxcount(), and action_mailboxstatus().

02067 {
02068    astman_send_response_full(s, m, "Success", MSG_MOREDATA, NULL);
02069 }

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

Definition at line 2348 of file manager.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_t_link, ao2_t_ref, ast_apply_ha(), ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_sockaddr_from_sin, ast_strlen_zero(), ast_tvnow(), astman_get_header(), mansession_session::blackfilters, mansession_session::challenge, get_manager_by_name_locked(), len(), LOG_NOTICE, md5(), MD5Final(), MD5Init(), MD5Update(), mansession_session::readperm, report_auth_success(), report_failed_acl(), report_failed_challenge_response(), report_inval_password(), report_invalid_user(), S_OR, mansession::session, mansession_session::sessionstart, mansession_session::sessionstart_tv, set_eventmask(), mansession_session::sin, user, mansession_session::username, mansession_session::whitefilters, mansession_session::writeperm, and mansession_session::writetimeout.

02349 {
02350    const char *username = astman_get_header(m, "Username");
02351    const char *password = astman_get_header(m, "Secret");
02352    int error = -1;
02353    struct ast_manager_user *user = NULL;
02354    regex_t *regex_filter;
02355    struct ao2_iterator filter_iter;
02356    struct ast_sockaddr addr;
02357 
02358    if (ast_strlen_zero(username)) { /* missing username */
02359       return -1;
02360    }
02361 
02362    /* locate user in locked state */
02363    AST_RWLIST_WRLOCK(&users);
02364 
02365    ast_sockaddr_from_sin(&addr, &s->session->sin);
02366 
02367    if (!(user = get_manager_by_name_locked(username))) {
02368       report_invalid_user(s, username);
02369       ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
02370    } else if (user->ha && !ast_apply_ha(user->ha, &addr)) {
02371       report_failed_acl(s, username);
02372       ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
02373    } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) {
02374       const char *key = astman_get_header(m, "Key");
02375       if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) {
02376          int x;
02377          int len = 0;
02378          char md5key[256] = "";
02379          struct MD5Context md5;
02380          unsigned char digest[16];
02381 
02382          MD5Init(&md5);
02383          MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge));
02384          MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret));
02385          MD5Final(digest, &md5);
02386          for (x = 0; x < 16; x++)
02387             len += sprintf(md5key + len, "%2.2x", digest[x]);
02388          if (!strcmp(md5key, key)) {
02389             error = 0;
02390          } else {
02391             report_failed_challenge_response(s, key, md5key);
02392          }
02393       } else {
02394          ast_debug(1, "MD5 authentication is not possible.  challenge: '%s'\n",
02395             S_OR(s->session->challenge, ""));
02396       }
02397    } else if (user->secret) {
02398       if (!strcmp(password, user->secret)) {
02399          error = 0;
02400       } else {
02401          report_inval_password(s, username);
02402       }
02403    }
02404 
02405    if (error) {
02406       ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
02407       AST_RWLIST_UNLOCK(&users);
02408       return -1;
02409    }
02410 
02411    /* auth complete */
02412 
02413    /* All of the user parameters are copied to the session so that in the event
02414      * of a reload and a configuration change, the session parameters are not
02415      * changed. */
02416    ast_copy_string(s->session->username, username, sizeof(s->session->username));
02417    s->session->readperm = user->readperm;
02418    s->session->writeperm = user->writeperm;
02419    s->session->writetimeout = user->writetimeout;
02420 
02421    filter_iter = ao2_iterator_init(user->whitefilters, 0);
02422    while ((regex_filter = ao2_iterator_next(&filter_iter))) {
02423       ao2_t_link(s->session->whitefilters, regex_filter, "add white user filter to session");
02424       ao2_t_ref(regex_filter, -1, "remove iterator ref");
02425    }
02426    ao2_iterator_destroy(&filter_iter);
02427 
02428    filter_iter = ao2_iterator_init(user->blackfilters, 0);
02429    while ((regex_filter = ao2_iterator_next(&filter_iter))) {
02430       ao2_t_link(s->session->blackfilters, regex_filter, "add black user filter to session");
02431       ao2_t_ref(regex_filter, -1, "remove iterator ref");
02432    }
02433    ao2_iterator_destroy(&filter_iter);
02434 
02435    s->session->sessionstart = time(NULL);
02436    s->session->sessionstart_tv = ast_tvnow();
02437    set_eventmask(s, astman_get_header(m, "Events"));
02438 
02439    report_auth_success(s);
02440 
02441    AST_RWLIST_UNLOCK(&users);
02442    return 0;
02443 }

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

Convert authority code to a list of options.

Definition at line 1183 of file manager.c.

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

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

01184 {
01185    int i;
01186    char *sep = "";
01187 
01188    ast_str_reset(*res);
01189    for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
01190       if (authority & perms[i].num) {
01191          ast_str_append(res, 0, "%s%s", sep, perms[i].label);
01192          sep = ",";
01193       }
01194    }
01195 
01196    if (ast_str_strlen(*res) == 0)   /* replace empty string with something sensible */
01197       ast_str_append(res, 0, "<none>");
01198 
01199    return ast_str_buffer(*res);
01200 }

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

Definition at line 4197 of file manager.c.

References CMP_MATCH, and CMP_STOP.

Referenced by match_filter().

04198 {
04199    regex_t *regex_filter = obj;
04200    const char *eventdata = arg;
04201    int *result = data;
04202 
04203    if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
04204       *result = 0;
04205       return (CMP_MATCH | CMP_STOP);
04206    }
04207 
04208    *result = 1;
04209    return 0;
04210 }

static struct mansession_session* build_mansession ( struct sockaddr_in  sin  )  [static]

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

Definition at line 1324 of file manager.c.

References ao2_alloc, ao2_container_alloc, ao2_link, ao2_ref, AST_PTHREADT_NULL, and session_destructor().

Referenced by session_do().

01325 {
01326    struct mansession_session *newsession;
01327 
01328    if (!(newsession = ao2_alloc(sizeof(*newsession), session_destructor))) {
01329       return NULL;
01330    }
01331 
01332    if (!(newsession->whitefilters = ao2_container_alloc(1, NULL, NULL))) {
01333       ao2_ref(newsession, -1);
01334       return NULL;
01335    }
01336 
01337    if (!(newsession->blackfilters = ao2_container_alloc(1, NULL, NULL))) {
01338       ao2_ref(newsession, -1); /* session_destructor will cleanup the other filter */
01339       return NULL;
01340    }
01341 
01342    newsession->fd = -1;
01343    newsession->waiting_thread = AST_PTHREADT_NULL;
01344    newsession->writetimeout = 100;
01345    newsession->send_events = -1;
01346    newsession->sin = sin;
01347 
01348    ao2_link(sessions, newsession);
01349 
01350    return newsession;
01351 }

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

Definition at line 3555 of file manager.c.

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

Referenced by action_command().

03556 {
03557    char *cmd_copy, *cur_cmd;
03558    char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, };
03559    int i;
03560 
03561    cmd_copy = ast_strdupa(cmd);
03562    for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) {
03563       cur_cmd = ast_strip(cur_cmd);
03564       if (ast_strlen_zero(cur_cmd)) {
03565          i--;
03566          continue;
03567       }
03568 
03569       cmd_words[i] = cur_cmd;
03570    }
03571 
03572    for (i = 0; i < ARRAY_LEN(command_blacklist); i++) {
03573       int j, match = 1;
03574 
03575       for (j = 0; command_blacklist[i].words[j]; j++) {
03576          if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) {
03577             match = 0;
03578             break;
03579          }
03580       }
03581 
03582       if (match) {
03583          return 1;
03584       }
03585    }
03586 
03587    return 0;
03588 }

int check_manager_enabled ( void   ) 

Check if AMI is enabled.

Definition at line 1091 of file manager.c.

Referenced by handle_show_settings().

01092 {
01093    return manager_enabled;
01094 }

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

Definition at line 1367 of file manager.c.

References ao2_find, mansession_session::inuse, and unref_mansession().

Referenced by process_message().

01368 {
01369    struct mansession_session *session = ao2_find(sessions, (char *) name, 0);
01370    int inuse = 0;
01371 
01372    if (session) {
01373       inuse = 1;
01374       unref_mansession(session);
01375    }
01376    return inuse;
01377 }

int check_webmanager_enabled ( void   ) 

Check if AMI/HTTP is enabled.

Definition at line 1096 of file manager.c.

Referenced by action_coresettings(), and handle_show_settings().

01097 {
01098    return (webmanager_enabled && manager_enabled);
01099 }

static int do_message ( struct mansession s  )  [static]

Definition at line 4769 of file manager.c.

References ARRAY_LEN, ast_free, ast_inet_ntoa(), ast_log(), ast_strdup, ast_strlen_zero(), ast_verb, astman_send_error(), authtimeout, displayconnects, errno, get_input(), message::hdrcount, message::headers, mansession_session::inbuf, LOG_ERROR, mansession_lock(), mansession_unlock(), process_events(), process_message(), and mansession::session.

Referenced by session_do().

04770 {
04771    struct message m = { 0 };
04772    char header_buf[sizeof(s->session->inbuf)] = { '\0' };
04773    int res;
04774    int idx;
04775    int hdr_loss;
04776    time_t now;
04777 
04778    hdr_loss = 0;
04779    for (;;) {
04780       /* Check if any events are pending and do them if needed */
04781       if (process_events(s)) {
04782          res = -1;
04783          break;
04784       }
04785       res = get_input(s, header_buf);
04786       if (res == 0) {
04787          /* No input line received. */
04788          if (!s->session->authenticated) {
04789             if (time(&now) == -1) {
04790                ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
04791                res = -1;
04792                break;
04793             }
04794 
04795             if (now - s->session->authstart > authtimeout) {
04796                if (displayconnects) {
04797                   ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout);
04798                }
04799                res = -1;
04800                break;
04801             }
04802          }
04803          continue;
04804       } else if (res > 0) {
04805          /* Input line received. */
04806          if (ast_strlen_zero(header_buf)) {
04807             if (hdr_loss) {
04808                mansession_lock(s);
04809                astman_send_error(s, &m, "Too many lines in message or allocation failure");
04810                mansession_unlock(s);
04811                res = 0;
04812             } else {
04813                res = process_message(s, &m) ? -1 : 0;
04814             }
04815             break;
04816          } else if (m.hdrcount < ARRAY_LEN(m.headers)) {
04817             m.headers[m.hdrcount] = ast_strdup(header_buf);
04818             if (!m.headers[m.hdrcount]) {
04819                /* Allocation failure. */
04820                hdr_loss = 1;
04821             } else {
04822                ++m.hdrcount;
04823             }
04824          } else {
04825             /* Too many lines in message. */
04826             hdr_loss = 1;
04827          }
04828       } else {
04829          /* Input error. */
04830          break;
04831       }
04832    }
04833 
04834    /* Free AMI request headers. */
04835    for (idx = 0; idx < m.hdrcount; ++idx) {
04836       ast_free((void *) m.headers[idx]);
04837    }
04838    return res;
04839 }

static void event_filter_destructor ( void *  obj  )  [static]

Definition at line 1287 of file manager.c.

01288 {
01289    regex_t *regex_filter = obj;
01290    regfree(regex_filter);
01291 }

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

Definition at line 3666 of file manager.c.

References fast_originate_helper::account, fast_originate_helper::app, fast_originate_helper::appdata, AST_CHANNEL_NAME, ast_channel_unlock, ast_free, ast_manager_event_multichan, ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_string_field_free_memory, ast_strlen_zero(), fast_originate_helper::cid_name, fast_originate_helper::cid_num, fast_originate_helper::context, fast_originate_helper::data, EVENT_FLAG_CALL, fast_originate_helper::exten, fast_originate_helper::format, fast_originate_helper::idtext, ast_channel::name, fast_originate_helper::priority, S_OR, fast_originate_helper::tech, fast_originate_helper::timeout, ast_channel::uniqueid, and fast_originate_helper::vars.

Referenced by action_originate().

03667 {
03668    struct fast_originate_helper *in = data;
03669    int res;
03670    int reason = 0;
03671    struct ast_channel *chan = NULL, *chans[1];
03672    char requested_channel[AST_CHANNEL_NAME];
03673 
03674    if (!ast_strlen_zero(in->app)) {
03675       res = ast_pbx_outgoing_app(in->tech, in->format, in->data, in->timeout, in->app, in->appdata, &reason, 1,
03676          S_OR(in->cid_num, NULL),
03677          S_OR(in->cid_name, NULL),
03678          in->vars, in->account, &chan);
03679    } else {
03680       res = ast_pbx_outgoing_exten(in->tech, in->format, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1,
03681          S_OR(in->cid_num, NULL),
03682          S_OR(in->cid_name, NULL),
03683          in->vars, in->account, &chan);
03684    }
03685 
03686    if (!chan) {
03687       snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);
03688    }
03689    /* Tell the manager what happened with the channel */
03690    chans[0] = chan;
03691    ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans,
03692       "%s%s"
03693       "Response: %s\r\n"
03694       "Channel: %s\r\n"
03695       "Context: %s\r\n"
03696       "Exten: %s\r\n"
03697       "Reason: %d\r\n"
03698       "Uniqueid: %s\r\n"
03699       "CallerIDNum: %s\r\n"
03700       "CallerIDName: %s\r\n",
03701       in->idtext, ast_strlen_zero(in->idtext) ? "" : "\r\n", res ? "Failure" : "Success",
03702       chan ? chan->name : requested_channel, in->context, in->exten, reason,
03703       chan ? chan->uniqueid : "<null>",
03704       S_OR(in->cid_num, "<unknown>"),
03705       S_OR(in->cid_name, "<unknown>")
03706       );
03707 
03708    /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
03709    if (chan) {
03710       ast_channel_unlock(chan);
03711    }
03712    ast_string_field_free_memory(in);
03713    ast_free(in);
03714    return NULL;
03715 }

static void free_channelvars ( void   )  [static]

Definition at line 6890 of file manager.c.

References ast_free, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, manager_channel_variable::entry, and var.

Referenced by __init_manager(), and load_channelvars().

06891 {
06892    struct manager_channel_variable *var;
06893    AST_RWLIST_WRLOCK(&channelvars);
06894    while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) {
06895       ast_free(var);
06896    }
06897    AST_RWLIST_UNLOCK(&channelvars);
06898 }

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

References mansession_session::inbuf, mansession_session::inlen, mansession::session, and ast_frame::src.

04673 {
04674    int res, x;
04675    int maxlen = sizeof(s->session->inbuf) - 1;
04676    char *src = s->session->inbuf;
04677    int timeout = -1;
04678    time_t now;
04679 
04680    /*
04681     * Look for \r\n within the buffer. If found, copy to the output
04682     * buffer and return, trimming the \r\n (not used afterwards).
04683     */
04684    for (x = 0; x < s->session->inlen; x++) {
04685       int cr;  /* set if we have \r */
04686       if (src[x] == '\r' && x+1 < s->session->inlen && src[x + 1] == '\n') {
04687          cr = 2;  /* Found. Update length to include \r\n */
04688       } else if (src[x] == '\n') {
04689          cr = 1;  /* also accept \n only */
04690       } else {
04691          continue;
04692       }
04693       memmove(output, src, x);   /*... but trim \r\n */
04694       output[x] = '\0';    /* terminate the string */
04695       x += cr;       /* number of bytes used */
04696       s->session->inlen -= x;       /* remaining size */
04697       memmove(src, src + x, s->session->inlen); /* remove used bytes */
04698       return 1;
04699    }
04700    if (s->session->inlen >= maxlen) {
04701       /* no crlf found, and buffer full - sorry, too long for us */
04702       ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", ast_inet_ntoa(s->session->sin.sin_addr), src);
04703       s->session->inlen = 0;
04704    }
04705    res = 0;
04706    while (res == 0) {
04707       /* calculate a timeout if we are not authenticated */
04708       if (!s->session->authenticated) {
04709          if(time(&now) == -1) {
04710             ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
04711             return -1;
04712          }
04713 
04714          timeout = (authtimeout - (now - s->session->authstart)) * 1000;
04715          if (timeout < 0) {
04716             /* we have timed out */
04717             return 0;
04718          }
04719       }
04720 
04721       ao2_lock(s->session);
04722       if (s->session->pending_event) {
04723          s->session->pending_event = 0;
04724          ao2_unlock(s->session);
04725          return 0;
04726       }
04727       s->session->waiting_thread = pthread_self();
04728       ao2_unlock(s->session);
04729 
04730       res = ast_wait_for_input(s->session->fd, timeout);
04731 
04732       ao2_lock(s->session);
04733       s->session->waiting_thread = AST_PTHREADT_NULL;
04734       ao2_unlock(s->session);
04735    }
04736    if (res < 0) {
04737       /* If we get a signal from some other thread (typically because
04738        * there are new events queued), return 0 to notify the caller.
04739        */
04740       if (errno == EINTR || errno == EAGAIN) {
04741          return 0;
04742       }
04743       ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno));
04744       return -1;
04745    }
04746 
04747    ao2_lock(s->session);
04748    res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f);
04749    if (res < 1) {
04750       res = -1;   /* error return */
04751    } else {
04752       s->session->inlen += res;
04753       src[s->session->inlen] = '\0';
04754       res = 0;
04755    }
04756    ao2_unlock(s->session);
04757    return res;
04758 }

static struct ast_manager_user* get_manager_by_name_locked ( const char *  name  )  [static]

lookup an entry in the list of registered users. must be called with the list lock held.

Definition at line 1384 of file manager.c.

References AST_RWLIST_TRAVERSE, ast_manager_user::list, and user.

Referenced by authenticate(), handle_showmanager(), and manager_displayconnects().

01385 {
01386    struct ast_manager_user *user = NULL;
01387 
01388    AST_RWLIST_TRAVERSE(&users, user, list) {
01389       if (!strcasecmp(user->username, name)) {
01390          break;
01391       }
01392    }
01393 
01394    return user;
01395 }

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

Definition at line 1226 of file manager.c.

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

Referenced by strings_to_mask().

01227 {
01228    int x = 0, ret = 0;
01229 
01230    if (!instr) {
01231       return 0;
01232    }
01233 
01234    for (x = 0; x < ARRAY_LEN(perms); x++) {
01235       if (ast_instring(instr, perms[x].label, ',')) {
01236          ret |= perms[x].num;
01237       }
01238    }
01239 
01240    return ret;
01241 }

static struct eventqent* grab_last ( void   )  [static]

Grab a reference to the last event, update usecount as needed. Can handle a NULL pointer.

Definition at line 1105 of file manager.c.

References ast_atomic_fetchadd_int(), AST_RWLIST_LAST, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and eventqent::usecount.

Referenced by session_do().

01106 {
01107    struct eventqent *ret;
01108 
01109    AST_RWLIST_WRLOCK(&all_events);
01110    ret = AST_RWLIST_LAST(&all_events);
01111    /* the list is never empty now, but may become so when
01112     * we optimize it in the future, so be prepared.
01113     */
01114    if (ret) {
01115       ast_atomic_fetchadd_int(&ret->usecount, 1);
01116    }
01117    AST_RWLIST_UNLOCK(&all_events);
01118    return ret;
01119 }

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

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

01719 {
01720    switch (cmd) {
01721    case CLI_INIT:
01722       e->command = "manager reload";
01723       e->usage =
01724          "Usage: manager reload\n"
01725          "       Reloads the manager configuration.\n";
01726       return NULL;
01727    case CLI_GENERATE:
01728       return NULL;
01729    }
01730    if (a->argc > 2) {
01731       return CLI_SHOWUSAGE;
01732    }
01733    reload_manager();
01734    return CLI_SUCCESS;
01735 }

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

Definition at line 1492 of file manager.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

01493 {
01494    switch (cmd) {
01495    case CLI_INIT:
01496       e->command = "manager set debug [on|off]";
01497       e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n";
01498       return NULL;
01499    case CLI_GENERATE:
01500       return NULL;
01501    }
01502 
01503    if (a->argc == 3) {
01504       ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off");
01505    } else if (a->argc == 4) {
01506       if (!strcasecmp(a->argv[3], "on")) {
01507          manager_debug = 1;
01508       } else if (!strcasecmp(a->argv[3], "off")) {
01509          manager_debug = 0;
01510       } else {
01511          return CLI_SHOWUSAGE;
01512       }
01513    }
01514    return CLI_SUCCESS;
01515 }

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

Definition at line 1517 of file manager.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_strdup, authority_to_str(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_manager_by_name_locked(), ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, user, and ast_cli_args::word.

01518 {
01519    struct ast_manager_user *user = NULL;
01520    int l, which;
01521    char *ret = NULL;
01522    struct ast_str *rauthority = ast_str_alloca(128);
01523    struct ast_str *wauthority = ast_str_alloca(128);
01524 
01525    switch (cmd) {
01526    case CLI_INIT:
01527       e->command = "manager show user";
01528       e->usage =
01529          " Usage: manager show user <user>\n"
01530          "        Display all information related to the manager user specified.\n";
01531       return NULL;
01532    case CLI_GENERATE:
01533       l = strlen(a->word);
01534       which = 0;
01535       if (a->pos != 3) {
01536          return NULL;
01537       }
01538       AST_RWLIST_RDLOCK(&users);
01539       AST_RWLIST_TRAVERSE(&users, user, list) {
01540          if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) {
01541             ret = ast_strdup(user->username);
01542             break;
01543          }
01544       }
01545       AST_RWLIST_UNLOCK(&users);
01546       return ret;
01547    }
01548 
01549    if (a->argc != 4) {
01550       return CLI_SHOWUSAGE;
01551    }
01552 
01553    AST_RWLIST_RDLOCK(&users);
01554 
01555    if (!(user = get_manager_by_name_locked(a->argv[3]))) {
01556       ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]);
01557       AST_RWLIST_UNLOCK(&users);
01558       return CLI_SUCCESS;
01559    }
01560 
01561    ast_cli(a->fd, "\n");
01562    ast_cli(a->fd,
01563       "       username: %s\n"
01564       "         secret: %s\n"
01565       "            acl: %s\n"
01566       "      read perm: %s\n"
01567       "     write perm: %s\n"
01568       "displayconnects: %s\n",
01569       (user->username ? user->username : "(N/A)"),
01570       (user->secret ? "<Set>" : "(N/A)"),
01571       (user->ha ? "yes" : "no"),
01572       authority_to_str(user->readperm, &rauthority),
01573       authority_to_str(user->writeperm, &wauthority),
01574       (user->displayconnects ? "yes" : "no"));
01575 
01576    AST_RWLIST_UNLOCK(&users);
01577 
01578    return CLI_SUCCESS;
01579 }

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

Definition at line 1581 of file manager.c.

References ast_cli_args::argc, ast_cli(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_manager_user::list, ast_cli_entry::usage, and user.

01582 {
01583    struct ast_manager_user *user = NULL;
01584    int count_amu = 0;
01585    switch (cmd) {
01586    case CLI_INIT:
01587       e->command = "manager show users";
01588       e->usage =
01589          "Usage: manager show users\n"
01590          "       Prints a listing of all managers that are currently configured on that\n"
01591          " system.\n";
01592       return NULL;
01593    case CLI_GENERATE:
01594       return NULL;
01595    }
01596    if (a->argc != 3) {
01597       return CLI_SHOWUSAGE;
01598    }
01599 
01600    AST_RWLIST_RDLOCK(&users);
01601 
01602    /* If there are no users, print out something along those lines */
01603    if (AST_RWLIST_EMPTY(&users)) {
01604       ast_cli(a->fd, "There are no manager users.\n");
01605       AST_RWLIST_UNLOCK(&users);
01606       return CLI_SUCCESS;
01607    }
01608 
01609    ast_cli(a->fd, "\nusername\n--------\n");
01610 
01611    AST_RWLIST_TRAVERSE(&users, user, list) {
01612       ast_cli(a->fd, "%s\n", user->username);
01613       count_amu++;
01614    }
01615 
01616    AST_RWLIST_UNLOCK(&users);
01617 
01618    ast_cli(a->fd,"-------------------\n"
01619             "%d manager users configured.\n", count_amu);
01620    return CLI_SUCCESS;
01621 }

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

Definition at line 1415 of file manager.c.

References manager_action::action, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_strdup, AST_XML_DOC, ast_xmldoc_printable(), manager_action::authority, authority_to_str(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, COLOR_MAGENTA, ast_cli_entry::command, manager_action::docsrc, ast_cli_args::fd, ast_cli_args::n, S_OR, term_color(), ast_cli_entry::usage, and ast_cli_args::word.

01416 {
01417    struct manager_action *cur;
01418    struct ast_str *authority;
01419    int num, l, which;
01420    char *ret = NULL;
01421 #ifdef AST_XML_DOCS
01422    char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64];
01423 #endif
01424 
01425    switch (cmd) {
01426    case CLI_INIT:
01427       e->command = "manager show command";
01428       e->usage =
01429          "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n"
01430          "  Shows the detailed description for a specific Asterisk manager interface command.\n";
01431       return NULL;
01432    case CLI_GENERATE:
01433       l = strlen(a->word);
01434       which = 0;
01435       AST_RWLIST_RDLOCK(&actions);
01436       AST_RWLIST_TRAVERSE(&actions, cur, list) {
01437          if (!strncasecmp(a->word, cur->action, l) && ++which > a->n) {
01438             ret = ast_strdup(cur->action);
01439             break;   /* make sure we exit even if ast_strdup() returns NULL */
01440          }
01441       }
01442       AST_RWLIST_UNLOCK(&actions);
01443       return ret;
01444    }
01445    authority = ast_str_alloca(80);
01446    if (a->argc < 4) {
01447       return CLI_SHOWUSAGE;
01448    }
01449 
01450 #ifdef AST_XML_DOCS
01451    /* setup the titles */
01452    term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
01453    term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40);
01454    term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
01455    term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40);
01456    term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
01457 #endif
01458 
01459    AST_RWLIST_RDLOCK(&actions);
01460    AST_RWLIST_TRAVERSE(&actions, cur, list) {
01461       for (num = 3; num < a->argc; num++) {
01462          if (!strcasecmp(cur->action, a->argv[num])) {
01463 #ifdef AST_XML_DOCS
01464             if (cur->docsrc == AST_XML_DOC) {
01465                ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n",
01466                   syntax_title,
01467                   ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1),
01468                   synopsis_title,
01469                   ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1),
01470                   description_title,
01471                   ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1),
01472                   arguments_title,
01473                   ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1),
01474                   seealso_title,
01475                   ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1));
01476             } else
01477 #endif
01478             {
01479                ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
01480                   cur->action, cur->synopsis,
01481                   authority_to_str(cur->authority, &authority),
01482                   S_OR(cur->description, ""));
01483             }
01484          }
01485       }
01486    }
01487    AST_RWLIST_UNLOCK(&actions);
01488 
01489    return CLI_SUCCESS;
01490 }

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

References manager_action::action, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, manager_action::authority, authority_to_str(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, HSMC_FORMAT, and ast_cli_entry::usage.

01625 {
01626    struct manager_action *cur;
01627    struct ast_str *authority;
01628 #define HSMC_FORMAT "  %-15.15s  %-15.15s  %-55.55s\n"
01629    switch (cmd) {
01630    case CLI_INIT:
01631       e->command = "manager show commands";
01632       e->usage =
01633          "Usage: manager show commands\n"
01634          "  Prints a listing of all the available Asterisk manager interface commands.\n";
01635       return NULL;
01636    case CLI_GENERATE:
01637       return NULL;
01638    }
01639    authority = ast_str_alloca(80);
01640    ast_cli(a->fd, HSMC_FORMAT, "Action", "Privilege", "Synopsis");
01641    ast_cli(a->fd, HSMC_FORMAT, "------", "---------", "--------");
01642 
01643    AST_RWLIST_RDLOCK(&actions);
01644    AST_RWLIST_TRAVERSE(&actions, cur, list) {
01645       ast_cli(a->fd, HSMC_FORMAT, cur->action, authority_to_str(cur->authority, &authority), cur->synopsis);
01646    }
01647    AST_RWLIST_UNLOCK(&actions);
01648 
01649    return CLI_SUCCESS;
01650 }

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

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_cli(), ast_inet_ntoa(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, HSMCONN_FORMAT1, HSMCONN_FORMAT2, unref_mansession(), and ast_cli_entry::usage.

01654 {
01655    struct mansession_session *session;
01656    time_t now = time(NULL);
01657 #define HSMCONN_FORMAT1 "  %-15.15s  %-15.15s  %-10.10s  %-10.10s  %-8.8s  %-8.8s  %-5.5s  %-5.5s\n"
01658 #define HSMCONN_FORMAT2 "  %-15.15s  %-15.15s  %-10d  %-10d  %-8d  %-8d  %-5.5d  %-5.5d\n"
01659    int count = 0;
01660    struct ao2_iterator i;
01661 
01662    switch (cmd) {
01663    case CLI_INIT:
01664       e->command = "manager show connected";
01665       e->usage =
01666          "Usage: manager show connected\n"
01667          "  Prints a listing of the users that are currently connected to the\n"
01668          "Asterisk manager interface.\n";
01669       return NULL;
01670    case CLI_GENERATE:
01671       return NULL;
01672    }
01673 
01674    ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write");
01675 
01676    i = ao2_iterator_init(sessions, 0);
01677    while ((session = ao2_iterator_next(&i))) {
01678       ao2_lock(session);
01679       ast_cli(a->fd, HSMCONN_FORMAT2, session->username, ast_inet_ntoa(session->sin.sin_addr), (int)(session->sessionstart), (int)(now - session->sessionstart), session->fd, session->inuse, session->readperm, session->writeperm);
01680       count++;
01681       ao2_unlock(session);
01682       unref_mansession(session);
01683    }
01684    ao2_iterator_destroy(&i);
01685    ast_cli(a->fd, "%d users connected.\n", count);
01686 
01687    return CLI_SUCCESS;
01688 }

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

References ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, eventqent::category, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, eventqent::eq_next, eventqent::eventdata, ast_cli_args::fd, ast_cli_entry::usage, and eventqent::usecount.

01693 {
01694    struct eventqent *s;
01695    switch (cmd) {
01696    case CLI_INIT:
01697       e->command = "manager show eventq";
01698       e->usage =
01699          "Usage: manager show eventq\n"
01700          "  Prints a listing of all events pending in the Asterisk manger\n"
01701          "event queue.\n";
01702       return NULL;
01703    case CLI_GENERATE:
01704       return NULL;
01705    }
01706    AST_RWLIST_RDLOCK(&all_events);
01707    AST_RWLIST_TRAVERSE(&all_events, s, eq_next) {
01708       ast_cli(a->fd, "Usecount: %d\n", s->usecount);
01709       ast_cli(a->fd, "Category: %d\n", s->category);
01710       ast_cli(a->fd, "Event:\n%s", s->eventdata);
01711    }
01712    AST_RWLIST_UNLOCK(&all_events);
01713 
01714    return CLI_SUCCESS;
01715 }

static enum error_type handle_updates ( struct mansession s,
const struct message m,
struct ast_config cfg,
const char *  dfn 
) [static]

Definition at line 2622 of file manager.c.

References ast_category_append(), ast_category_delete(), ast_category_empty(), ast_category_get(), ast_category_insert(), ast_category_new(), ast_category_rename(), ast_free, ast_log(), ast_str_create(), ast_strlen_zero(), ast_variable_append(), ast_variable_delete(), ast_variable_insert(), ast_variable_new(), ast_variable_update(), astman_get_header(), FAILURE_ALLOCATION, FAILURE_DELCAT, FAILURE_DELETE, FAILURE_EMPTYCAT, FAILURE_NEWCAT, FAILURE_UPDATE, LOG_WARNING, match(), ast_variable::object, UNKNOWN_ACTION, UNKNOWN_CATEGORY, UNSPECIFIED_ARGUMENT, UNSPECIFIED_CATEGORY, value, and var.

Referenced by action_updateconfig().

02623 {
02624    int x;
02625    char hdr[40];
02626    const char *action, *cat, *var, *value, *match, *line;
02627    struct ast_category *category;
02628    struct ast_variable *v;
02629    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
02630    enum error_type result = 0;
02631 
02632    for (x = 0; x < 100000; x++) {   /* 100000 = the max number of allowed updates + 1 */
02633       unsigned int object = 0;
02634 
02635       snprintf(hdr, sizeof(hdr), "Action-%06d", x);
02636       action = astman_get_header(m, hdr);
02637       if (ast_strlen_zero(action))     /* breaks the for loop if no action header */
02638          break;                        /* this could cause problems if actions come in misnumbered */
02639 
02640       snprintf(hdr, sizeof(hdr), "Cat-%06d", x);
02641       cat = astman_get_header(m, hdr);
02642       if (ast_strlen_zero(cat)) {      /* every action needs a category */
02643          result =  UNSPECIFIED_CATEGORY;
02644          break;
02645       }
02646 
02647       snprintf(hdr, sizeof(hdr), "Var-%06d", x);
02648       var = astman_get_header(m, hdr);
02649 
02650       snprintf(hdr, sizeof(hdr), "Value-%06d", x);
02651       value = astman_get_header(m, hdr);
02652 
02653       if (!ast_strlen_zero(value) && *value == '>') {
02654          object = 1;
02655          value++;
02656       }
02657 
02658       snprintf(hdr, sizeof(hdr), "Match-%06d", x);
02659       match = astman_get_header(m, hdr);
02660 
02661       snprintf(hdr, sizeof(hdr), "Line-%06d", x);
02662       line = astman_get_header(m, hdr);
02663 
02664       if (!strcasecmp(action, "newcat")) {
02665          if (ast_category_get(cfg,cat)) { /* check to make sure the cat doesn't */
02666             result = FAILURE_NEWCAT;   /* already exist */
02667             break;
02668          }
02669          if (!(category = ast_category_new(cat, dfn, -1))) {
02670             result = FAILURE_ALLOCATION;
02671             break;
02672          }
02673          if (ast_strlen_zero(match)) {
02674             ast_category_append(cfg, category);
02675          } else {
02676             ast_category_insert(cfg, category, match);
02677          }
02678       } else if (!strcasecmp(action, "renamecat")) {
02679          if (ast_strlen_zero(value)) {
02680             result = UNSPECIFIED_ARGUMENT;
02681             break;
02682          }
02683          if (!(category = ast_category_get(cfg, cat))) {
02684             result = UNKNOWN_CATEGORY;
02685             break;
02686          }
02687          ast_category_rename(category, value);
02688       } else if (!strcasecmp(action, "delcat")) {
02689          if (ast_category_delete(cfg, cat)) {
02690             result = FAILURE_DELCAT;
02691             break;
02692          }
02693       } else if (!strcasecmp(action, "emptycat")) {
02694          if (ast_category_empty(cfg, cat)) {
02695             result = FAILURE_EMPTYCAT;
02696             break;
02697          }
02698       } else if (!strcasecmp(action, "update")) {
02699          if (ast_strlen_zero(var)) {
02700             result = UNSPECIFIED_ARGUMENT;
02701             break;
02702          }
02703          if (!(category = ast_category_get(cfg,cat))) {
02704             result = UNKNOWN_CATEGORY;
02705             break;
02706          }
02707          if (ast_variable_update(category, var, value, match, object)) {
02708             result = FAILURE_UPDATE;
02709             break;
02710          }
02711       } else if (!strcasecmp(action, "delete")) {
02712          if ((ast_strlen_zero(var) && ast_strlen_zero(line))) {
02713             result = UNSPECIFIED_ARGUMENT;
02714             break;
02715          }
02716          if (!(category = ast_category_get(cfg, cat))) {
02717             result = UNKNOWN_CATEGORY;
02718             break;
02719          }
02720          if (ast_variable_delete(category, var, match, line)) {
02721             result = FAILURE_DELETE;
02722             break;
02723          }
02724       } else if (!strcasecmp(action, "append")) {
02725          if (ast_strlen_zero(var)) {
02726             result = UNSPECIFIED_ARGUMENT;
02727             break;
02728          }
02729          if (!(category = ast_category_get(cfg, cat))) {
02730             result = UNKNOWN_CATEGORY;
02731             break;
02732          }
02733          if (!(v = ast_variable_new(var, value, dfn))) {
02734             result = FAILURE_ALLOCATION;
02735             break;
02736          }
02737          if (object || (match && !strcasecmp(match, "object"))) {
02738             v->object = 1;
02739          }
02740          ast_variable_append(category, v);
02741       } else if (!strcasecmp(action, "insert")) {
02742          if (ast_strlen_zero(var) || ast_strlen_zero(line)) {
02743             result = UNSPECIFIED_ARGUMENT;
02744             break;
02745          }
02746          if (!(category = ast_category_get(cfg, cat))) {
02747             result = UNKNOWN_CATEGORY;
02748             break;
02749          }
02750          if (!(v = ast_variable_new(var, value, dfn))) {
02751             result = FAILURE_ALLOCATION;
02752             break;
02753          }
02754          ast_variable_insert(category, v, line);
02755       }
02756       else {
02757          ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action);
02758          result = UNKNOWN_ACTION;
02759          break;
02760       }
02761    }
02762    ast_free(str1);
02763    ast_free(str2);
02764    return result;
02765 }

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

Referenced by astman_append_json().

02545 {
02546    for (; *in; in++) {
02547       if (*in == '\\' || *in == '\"') {
02548          *out++ = '\\';
02549       }
02550       *out++ = *in;
02551    }
02552    *out = '\0';
02553 }

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

Definition at line 1814 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(), parse(), strsep(), and var.

Referenced by astman_get_variables().

01815 {
01816    char *parse;
01817    AST_DECLARE_APP_ARGS(args,
01818       AST_APP_ARG(vars)[64];
01819    );
01820 
01821    hdr_val = ast_skip_blanks(hdr_val); /* ignore leading spaces in the value */
01822    parse = ast_strdupa(hdr_val);
01823 
01824    /* Break the header value string into name=val pair items. */
01825    AST_STANDARD_APP_ARGS(args, parse);
01826    if (args.argc) {
01827       int y;
01828 
01829       /* Process each name=val pair item. */
01830       for (y = 0; y < args.argc; y++) {
01831          struct ast_variable *cur;
01832          char *var;
01833          char *val;
01834 
01835          if (!args.vars[y]) {
01836             continue;
01837          }
01838          var = val = args.vars[y];
01839          strsep(&val, "=");
01840 
01841          /* XXX We may wish to trim whitespace from the strings. */
01842          if (!val || ast_strlen_zero(var)) {
01843             continue;
01844          }
01845 
01846          /* Create new variable list node and prepend it to the list. */
01847          cur = ast_variable_new(var, val, "");
01848          if (cur) {
01849             cur->next = head;
01850             head = cur;
01851          }
01852       }
01853    }
01854 
01855    return head;
01856 }

static int manager_displayconnects ( struct mansession_session session  )  [static]

Get displayconnects config option.

Parameters:
session manager session to get parameter from.
Returns:
displayconnects config option value.

Definition at line 1401 of file manager.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, get_manager_by_name_locked(), user, and mansession_session::username.

Referenced by action_login(), and purge_sessions().

01402 {
01403    struct ast_manager_user *user = NULL;
01404    int ret = 0;
01405 
01406    AST_RWLIST_RDLOCK(&users);
01407    if ((user = get_manager_by_name_locked (session->username))) {
01408       ret = user->displayconnects;
01409    }
01410    AST_RWLIST_UNLOCK(&users);
01411 
01412    return ret;
01413 }

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

Definition at line 4466 of file manager.c.

References ast_copy_string(), ast_file_version_find(), ast_log(), ast_module_check(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), LOG_DEBUG, and version.

Referenced by __init_manager().

04467 {
04468    int res;
04469    const char *module = astman_get_header(m, "Module");
04470    const char *id = astman_get_header(m, "ActionID");
04471    char idText[256];
04472 #if !defined(LOW_MEMORY)
04473    const char *version;
04474 #endif
04475    char filename[PATH_MAX];
04476    char *cut;
04477 
04478    ast_copy_string(filename, module, sizeof(filename));
04479    if ((cut = strchr(filename, '.'))) {
04480       *cut = '\0';
04481    } else {
04482       cut = filename + strlen(filename);
04483    }
04484    snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".so");
04485    ast_log(LOG_DEBUG, "**** ModuleCheck .so file %s\n", filename);
04486    res = ast_module_check(filename);
04487    if (!res) {
04488       astman_send_error(s, m, "Module not loaded");
04489       return 0;
04490    }
04491    snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".c");
04492    ast_log(LOG_DEBUG, "**** ModuleCheck .c file %s\n", filename);
04493 #if !defined(LOW_MEMORY)
04494    version = ast_file_version_find(filename);
04495 #endif
04496 
04497    if (!ast_strlen_zero(id)) {
04498       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
04499    } else {
04500       idText[0] = '\0';
04501    }
04502    astman_append(s, "Response: Success\r\n%s", idText);
04503 #if !defined(LOW_MEMORY)
04504    astman_append(s, "Version: %s\r\n\r\n", version ? version : "");
04505 #endif
04506    return 0;
04507 }

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

Definition at line 4509 of file manager.c.

References AST_FORCE_SOFT, ast_load_resource(), ast_module_reload(), ast_strlen_zero(), ast_unload_resource(), astman_get_header(), astman_send_ack(), and astman_send_error().

Referenced by __init_manager().

04510 {
04511    int res;
04512    const char *module = astman_get_header(m, "Module");
04513    const char *loadtype = astman_get_header(m, "LoadType");
04514 
04515    if (!loadtype || strlen(loadtype) == 0) {
04516       astman_send_error(s, m, "Incomplete ModuleLoad action.");
04517    }
04518    if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0) {
04519       astman_send_error(s, m, "Need module name");
04520    }
04521 
04522    if (!strcasecmp(loadtype, "load")) {
04523       res = ast_load_resource(module);
04524       if (res) {
04525          astman_send_error(s, m, "Could not load module.");
04526       } else {
04527          astman_send_ack(s, m, "Module loaded.");
04528       }
04529    } else if (!strcasecmp(loadtype, "unload")) {
04530       res = ast_unload_resource(module, AST_FORCE_SOFT);
04531       if (res) {
04532          astman_send_error(s, m, "Could not unload module.");
04533       } else {
04534          astman_send_ack(s, m, "Module unloaded.");
04535       }
04536    } else if (!strcasecmp(loadtype, "reload")) {
04537       if (!ast_strlen_zero(module)) {
04538          res = ast_module_reload(module);
04539          if (res == 0) {
04540             astman_send_error(s, m, "No such module.");
04541          } else if (res == 1) {
04542             astman_send_error(s, m, "Module does not support reload action.");
04543          } else {
04544             astman_send_ack(s, m, "Module reloaded.");
04545          }
04546       } else {
04547          ast_module_reload(NULL);   /* Reload all modules */
04548          astman_send_ack(s, m, "All modules reloaded");
04549       }
04550    } else
04551       astman_send_error(s, m, "Incomplete ModuleLoad action.");
04552    return 0;
04553 }

static int manager_state_cb ( char *  context,
char *  exten,
int  state,
void *  data 
) [static]

Definition at line 5148 of file manager.c.

References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.

Referenced by __init_manager().

05149 {
05150    /* Notify managers of change */
05151    char hint[512];
05152    ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten);
05153 
05154    manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state);
05155    return 0;
05156 }

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

Definition at line 1353 of file manager.c.

References CMP_MATCH, str, and mansession_session::username.

01354 {
01355    struct mansession_session *s = obj;
01356    char *str = arg;
01357    return !strcasecmp(s->username, str) ? CMP_MATCH : 0;
01358 }

static struct sockaddr_in* mansession_encode_sin_local ( const struct mansession s,
struct sockaddr_in *  sin_local 
) [static]

Definition at line 2111 of file manager.c.

References ast_sockaddr_to_sin, ast_tcptls_session_args::local_address, ast_tcptls_session_instance::parent, and mansession::tcptls_session.

Referenced by report_auth_success(), report_failed_acl(), report_failed_challenge_response(), report_inval_password(), report_invalid_user(), report_req_bad_format(), report_req_not_allowed(), and report_session_limit().

02113 {
02114    ast_sockaddr_to_sin(&s->tcptls_session->parent->local_address,
02115              sin_local);
02116 
02117    return sin_local;
02118 }

static enum ast_security_event_transport_type mansession_get_transport ( const struct mansession s  )  [static]

Definition at line 2105 of file manager.c.

References AST_SECURITY_EVENT_TRANSPORT_TCP, AST_SECURITY_EVENT_TRANSPORT_TLS, ast_tcptls_session_instance::parent, mansession::tcptls_session, and ast_tcptls_session_args::tls_cfg.

Referenced by report_auth_success(), report_failed_acl(), report_failed_challenge_response(), report_inval_password(), report_invalid_user(), report_req_bad_format(), report_req_not_allowed(), and report_session_limit().

static void mansession_lock ( struct mansession s  )  [static]

Lock the 'mansession' structure.

Definition at line 2077 of file manager.c.

References ast_mutex_lock, and mansession::lock.

Referenced by action_challenge(), do_message(), and process_message().

02078 {
02079    ast_mutex_lock(&s->lock);
02080 }

static void mansession_unlock ( struct mansession s  )  [static]

Unlock the 'mansession' structure.

Definition at line 2083 of file manager.c.

References ast_mutex_unlock, and mansession::lock.

Referenced by action_challenge(), do_message(), and process_message().

02084 {
02085    ast_mutex_unlock(&s->lock);
02086 }

static int match_filter ( struct mansession s,
char *  eventdata 
) [static]

Definition at line 4212 of file manager.c.

References ao2_container_count(), ao2_t_callback_data, ast_debug, blackfilter_cmp_fn(), mansession_session::blackfilters, OBJ_NODATA, mansession::session, whitefilter_cmp_fn(), and mansession_session::whitefilters.

Referenced by process_events().

04213 {
04214    int result = 0;
04215 
04216    ast_debug(3, "Examining event:\n%s\n", eventdata);
04217    if (!ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) {
04218       return 1; /* no filtering means match all */
04219    } else if (ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) {
04220       /* white filters only: implied black all filter processed first, then white filters */
04221       ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04222    } else if (!ao2_container_count(s->session->whitefilters) && ao2_container_count(s->session->blackfilters)) {
04223       /* black filters only: implied white all filter processed first, then black filters */
04224       ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04225    } else {
04226       /* white and black filters: implied black all filter processed first, then white filters, and lastly black filters */
04227       ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04228       if (result) {
04229          result = 0;
04230          ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04231       }
04232    }
04233 
04234    return result;
04235 }

static int process_events ( struct mansession s  )  [static]

Send any applicable events to the client listening on this socket. Wait only for a finite time on each event, and drop all events whether they are successfully sent or not.

Definition at line 4242 of file manager.c.

References advance_event(), ao2_lock, ao2_unlock, mansession_session::authenticated, eventqent::category, eventqent::eventdata, mansession_session::f, mansession_session::last_ev, match_filter(), mansession_session::readperm, mansession_session::send_events, send_string(), and mansession::session.

Referenced by do_message(), and process_message().

04243 {
04244    int ret = 0;
04245 
04246    ao2_lock(s->session);
04247    if (s->session->f != NULL) {
04248       struct eventqent *eqe = s->session->last_ev;
04249 
04250       while ((eqe = advance_event(eqe))) {
04251          if (!ret && s->session->authenticated &&
04252              (s->session->readperm & eqe->category) == eqe->category &&
04253              (s->session->send_events & eqe->category) == eqe->category) {
04254                if (match_filter(s, eqe->eventdata)) {
04255                   if (send_string(s, eqe->eventdata) < 0)
04256                      ret = -1;   /* don't send more */
04257                }
04258          }
04259          s->session->last_ev = eqe;
04260       }
04261    }
04262    ao2_unlock(s->session);
04263    return ret;
04264 }

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

Definition at line 4568 of file manager.c.

References __astman_get_header(), manager_action::action, action_find(), allowmultiplelogin, ao2_lock, ao2_t_ref, ao2_unlock, ast_debug, ast_strlen_zero(), astman_get_header(), astman_send_error(), mansession_session::authenticated, manager_action::authority, check_manager_session_inuse(), manager_action::func, GET_HEADER_SKIP_EMPTY, mansession_lock(), mansession_unlock(), process_events(), manager_action::registered, report_req_bad_format(), report_req_not_allowed(), report_session_limit(), mansession::session, and mansession_session::writeperm.

Referenced by do_message().

04569 {
04570    int ret = 0;
04571    struct manager_action *act_found;
04572    const char *user;
04573    const char *action;
04574 
04575    action = __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY);
04576    if (ast_strlen_zero(action)) {
04577       report_req_bad_format(s, "NONE");
04578       mansession_lock(s);
04579       astman_send_error(s, m, "Missing action in request");
04580       mansession_unlock(s);
04581       return 0;
04582    }
04583 
04584    if (!s->session->authenticated
04585       && strcasecmp(action, "Login")
04586       && strcasecmp(action, "Logoff")
04587       && strcasecmp(action, "Challenge")) {
04588       if (!s->session->authenticated) {
04589          report_req_not_allowed(s, action);
04590       }
04591       mansession_lock(s);
04592       astman_send_error(s, m, "Permission denied");
04593       mansession_unlock(s);
04594       return 0;
04595    }
04596 
04597    if (!allowmultiplelogin
04598       && !s->session->authenticated
04599       && (!strcasecmp(action, "Login")
04600          || !strcasecmp(action, "Challenge"))) {
04601       user = astman_get_header(m, "Username");
04602 
04603       if (check_manager_session_inuse(user)) {
04604          report_session_limit(s);
04605          sleep(1);
04606          mansession_lock(s);
04607          astman_send_error(s, m, "Login Already In Use");
04608          mansession_unlock(s);
04609          return -1;
04610       }
04611    }
04612 
04613    act_found = action_find(action);
04614    if (act_found) {
04615       /* Found the requested AMI action. */
04616       int acted = 0;
04617 
04618       if ((s->session->writeperm & act_found->authority)
04619          || act_found->authority == 0) {
04620          /* We have the authority to execute the action. */
04621          ao2_lock(act_found);
04622          if (act_found->registered && act_found->func) {
04623             ast_debug(1, "Running action '%s'\n", act_found->action);
04624             ret = act_found->func(s, m);
04625             acted = 1;
04626          }
04627          ao2_unlock(act_found);
04628       }
04629       if (!acted) {
04630          /*
04631           * We did not execute the action because access was denied, it
04632           * was no longer registered, or no action was really registered.
04633           * Complain about it and leave.
04634           */
04635          report_req_not_allowed(s, action);
04636          mansession_lock(s);
04637          astman_send_error(s, m, "Permission denied");
04638          mansession_unlock(s);
04639       }
04640       ao2_t_ref(act_found, -1, "done with found action object");
04641    } else {
04642       char buf[512];
04643 
04644       report_req_bad_format(s, action);
04645       snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action);
04646       mansession_lock(s);
04647       astman_send_error(s, m, buf);
04648       mansession_unlock(s);
04649    }
04650    if (ret) {
04651       return ret;
04652    }
04653    /* Once done with our message, deliver any pending events unless the
04654       requester doesn't want them as part of this response.
04655    */
04656    if (ast_strlen_zero(astman_get_header(m, "SuppressEvents"))) {
04657       return process_events(s);
04658    } else {
04659       return ret;
04660    }
04661 }

static void purge_events ( void   )  [static]

Purge unused events. Remove elements from the head as long as their usecount is 0 and there is a next element.

Definition at line 1125 of file manager.c.

References ast_free, AST_RWLIST_FIRST, AST_RWLIST_NEXT, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_tvdiff_sec(), ast_tvnow(), eventqent::eq_next, eventqent::tv, and eventqent::usecount.

Referenced by purge_old_stuff().

01126 {
01127    struct eventqent *ev;
01128    struct timeval now = ast_tvnow();
01129 
01130    AST_RWLIST_WRLOCK(&all_events);
01131    while ( (ev = AST_RWLIST_FIRST(&all_events)) &&
01132        ev->usecount == 0 && AST_RWLIST_NEXT(ev, eq_next)) {
01133       AST_RWLIST_REMOVE_HEAD(&all_events, eq_next);
01134       ast_free(ev);
01135    }
01136 
01137    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&all_events, ev, eq_next) {
01138       /* Never release the last event */
01139       if (!AST_RWLIST_NEXT(ev, eq_next)) {
01140          break;
01141       }
01142 
01143       /* 2.5 times whatever the HTTP timeout is (maximum 2.5 hours) is the maximum time that we will definitely cache an event */
01144       if (ev->usecount == 0 && ast_tvdiff_sec(now, ev->tv) > (httptimeout > 3600 ? 3600 : httptimeout) * 2.5) {
01145          AST_RWLIST_REMOVE_CURRENT(eq_next);
01146          ast_free(ev);
01147       }
01148    }
01149    AST_RWLIST_TRAVERSE_SAFE_END;
01150    AST_RWLIST_UNLOCK(&all_events);
01151 }

static void purge_sessions ( int  n_max  )  [static]

remove at most n_max stale session from the list.

Definition at line 4948 of file manager.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_inet_ntoa(), ast_verb, mansession_session::authenticated, mansession_session::inuse, manager_displayconnects(), session_destroy(), mansession_session::sessiontimeout, mansession_session::sin, unref_mansession(), mansession_session::username, and VERBOSITY_ATLEAST.

Referenced by purge_old_stuff().

04949 {
04950    struct mansession_session *session;
04951    time_t now = time(NULL);
04952    struct ao2_iterator i;
04953 
04954    i = ao2_iterator_init(sessions, 0);
04955    while ((session = ao2_iterator_next(&i)) && n_max > 0) {
04956       ao2_lock(session);
04957       if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) {
04958          if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) {
04959             ast_verb(2, "HTTP Manager '%s' timed out from %s\n",
04960                session->username, ast_inet_ntoa(session->sin.sin_addr));
04961          }
04962          ao2_unlock(session);
04963          session_destroy(session);
04964          n_max--;
04965       } else {
04966          ao2_unlock(session);
04967          unref_mansession(session);
04968       }
04969    }
04970    ao2_iterator_destroy(&i);
04971 }

static void report_auth_success ( const struct mansession s  )  [static]

Definition at line 2198 of file manager.c.

References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_SUCCESSFUL_AUTH, AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION, ast_security_event_successful_auth::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.

Referenced by authenticate().

02199 {
02200    struct sockaddr_in sin_local;
02201    char session_id[32];
02202    struct ast_security_event_successful_auth successful_auth = {
02203       .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH,
02204       .common.version    = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
02205       .common.service    = "AMI",
02206       .common.account_id = s->session->username,
02207       .common.session_tv = &s->session->sessionstart_tv,
02208       .common.local_addr = {
02209          .sin       = mansession_encode_sin_local(s, &sin_local),
02210          .transport = mansession_get_transport(s),
02211       },
02212       .common.remote_addr = {
02213          .sin       = &s->session->sin,
02214          .transport = mansession_get_transport(s),
02215       },
02216       .common.session_id = session_id,
02217    };
02218 
02219    snprintf(session_id, sizeof(session_id), "%p", s->session);
02220 
02221    ast_security_event_report(AST_SEC_EVT(&successful_auth));
02222 }

static void report_failed_acl ( const struct mansession s,
const char *  username 
) [static]

Definition at line 2146 of file manager.c.

References AST_SEC_EVT, AST_SECURITY_EVENT_FAILED_ACL, AST_SECURITY_EVENT_FAILED_ACL_VERSION, ast_security_event_report(), ast_security_event_failed_acl::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, and mansession_session::sin.

Referenced by authenticate().

02147 {
02148    struct sockaddr_in sin_local;
02149    char session_id[32];
02150    struct ast_security_event_failed_acl failed_acl_event = {
02151       .common.event_type = AST_SECURITY_EVENT_FAILED_ACL,
02152       .common.version    = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
02153       .common.service    = "AMI",
02154       .common.account_id = username,
02155       .common.session_tv = &s->session->sessionstart_tv,
02156       .common.local_addr = {
02157          .sin       = mansession_encode_sin_local(s, &sin_local),
02158          .transport = mansession_get_transport(s),
02159       },
02160       .common.remote_addr = {
02161          .sin       = &s->session->sin,
02162          .transport = mansession_get_transport(s),
02163       },
02164       .common.session_id = session_id,
02165    };
02166 
02167    snprintf(session_id, sizeof(session_id), "%p", s->session);
02168 
02169    ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
02170 }

static void report_failed_challenge_response ( const struct mansession s,
const char *  response,
const char *  expected_response 
) [static]

Definition at line 2284 of file manager.c.

References AST_SEC_EVT, AST_SECURITY_EVENT_CHAL_RESP_FAILED, AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION, ast_security_event_report(), mansession_session::challenge, ast_security_event_chal_resp_failed::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.

Referenced by authenticate().

02286 {
02287    struct sockaddr_in sin_local;
02288    char session_id[32];
02289    struct ast_security_event_chal_resp_failed chal_resp_failed = {
02290       .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED,
02291       .common.version    = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
02292       .common.service    = "AMI",
02293       .common.account_id = s->session->username,
02294       .common.session_tv = &s->session->sessionstart_tv,
02295       .common.local_addr = {
02296          .sin       = mansession_encode_sin_local(s, &sin_local),
02297          .transport = mansession_get_transport(s),
02298       },
02299       .common.remote_addr = {
02300          .sin       = &s->session->sin,
02301          .transport = mansession_get_transport(s),
02302       },
02303       .common.session_id = session_id,
02304 
02305       .challenge         = s->session->challenge,
02306       .response          = response,
02307       .expected_response = expected_response,
02308    };
02309 
02310    snprintf(session_id, sizeof(session_id), "%p", s->session);
02311 
02312    ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
02313 }

static void report_inval_password ( const struct mansession s,
const char *  username 
) [static]

Definition at line 2172 of file manager.c.

References AST_SEC_EVT, AST_SECURITY_EVENT_INVAL_PASSWORD, AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION, ast_security_event_report(), ast_security_event_inval_password::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, and mansession_session::sin.

Referenced by authenticate().

02173 {
02174    struct sockaddr_in sin_local;
02175    char session_id[32];
02176    struct ast_security_event_inval_password inval_password = {
02177       .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD,
02178       .common.version    = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
02179       .common.service    = "AMI",
02180       .common.account_id = username,
02181       .common.session_tv = &s->session->sessionstart_tv,
02182       .common.local_addr = {
02183          .sin       = mansession_encode_sin_local(s, &sin_local),
02184          .transport = mansession_get_transport(s),
02185       },
02186       .common.remote_addr = {
02187          .sin       = &s->session->sin,
02188          .transport = mansession_get_transport(s),
02189       },
02190       .common.session_id = session_id,
02191    };
02192 
02193    snprintf(session_id, sizeof(session_id), "%p", s->session);
02194 
02195    ast_security_event_report(AST_SEC_EVT(&inval_password));
02196 }

static void report_invalid_user ( const struct mansession s,
const char *  username 
) [static]

Definition at line 2120 of file manager.c.

References AST_SEC_EVT, AST_SECURITY_EVENT_INVAL_ACCT_ID, AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION, ast_security_event_report(), ast_security_event_inval_acct_id::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, and mansession_session::sin.

Referenced by authenticate().

02121 {
02122    struct sockaddr_in sin_local;
02123    char session_id[32];
02124    struct ast_security_event_inval_acct_id inval_acct_id = {
02125       .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID,
02126       .common.version    = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
02127       .common.service    = "AMI",
02128       .common.account_id = username,
02129       .common.session_tv = &s->session->sessionstart_tv,
02130       .common.local_addr = {
02131          .sin       = mansession_encode_sin_local(s, &sin_local),
02132          .transport = mansession_get_transport(s),
02133       },
02134       .common.remote_addr = {
02135          .sin       = &s->session->sin,
02136          .transport = mansession_get_transport(s),
02137       },
02138       .common.session_id = session_id,
02139    };
02140 
02141    snprintf(session_id, sizeof(session_id), "%p", s);
02142 
02143    ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
02144 }

static void report_req_bad_format ( const struct mansession s,
const char *  action 
) [static]

Definition at line 2254 of file manager.c.

References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_REQ_BAD_FORMAT, AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION, ast_security_event_req_bad_format::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.

Referenced by process_message().

02255 {
02256    struct sockaddr_in sin_local;
02257    char session_id[32];
02258    char request_type[64];
02259    struct ast_security_event_req_bad_format req_bad_format = {
02260       .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT,
02261       .common.version    = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
02262       .common.service    = "AMI",
02263       .common.account_id = s->session->username,
02264       .common.session_tv = &s->session->sessionstart_tv,
02265       .common.local_addr = {
02266          .sin       = mansession_encode_sin_local(s, &sin_local),
02267          .transport = mansession_get_transport(s),
02268       },
02269       .common.remote_addr = {
02270          .sin       = &s->session->sin,
02271          .transport = mansession_get_transport(s),
02272       },
02273       .common.session_id = session_id,
02274 
02275       .request_type      = request_type,
02276    };
02277 
02278    snprintf(session_id, sizeof(session_id), "%p", s->session);
02279    snprintf(request_type, sizeof(request_type), "Action: %s", action);
02280 
02281    ast_security_event_report(AST_SEC_EVT(&req_bad_format));
02282 }

static void report_req_not_allowed ( const struct mansession s,
const char *  action 
) [static]

Definition at line 2224 of file manager.c.

References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_REQ_NOT_ALLOWED, AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION, ast_security_event_req_not_allowed::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.

Referenced by process_message().

02225 {
02226    struct sockaddr_in sin_local;
02227    char session_id[32];
02228    char request_type[64];
02229    struct ast_security_event_req_not_allowed req_not_allowed = {
02230       .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED,
02231       .common.version    = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
02232       .common.service    = "AMI",
02233       .common.account_id = s->session->username,
02234       .common.session_tv = &s->session->sessionstart_tv,
02235       .common.local_addr = {
02236          .sin       = mansession_encode_sin_local(s, &sin_local),
02237          .transport = mansession_get_transport(s),
02238       },
02239       .common.remote_addr = {
02240          .sin       = &s->session->sin,
02241          .transport = mansession_get_transport(s),
02242       },
02243       .common.session_id = session_id,
02244 
02245       .request_type      = request_type,
02246    };
02247 
02248    snprintf(session_id, sizeof(session_id), "%p", s->session);
02249    snprintf(request_type, sizeof(request_type), "Action: %s", action);
02250 
02251    ast_security_event_report(AST_SEC_EVT(&req_not_allowed));
02252 }

static void report_session_limit ( const struct mansession s  )  [static]

Definition at line 2315 of file manager.c.

References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_SESSION_LIMIT, AST_SECURITY_EVENT_SESSION_LIMIT_VERSION, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, session_limit, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.

Referenced by process_message().

02316 {
02317    struct sockaddr_in sin_local;
02318    char session_id[32];
02319    struct ast_security_event_session_limit session_limit = {
02320       .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT,
02321       .common.version    = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
02322       .common.service    = "AMI",
02323       .common.account_id = s->session->username,
02324       .common.session_tv = &s->session->sessionstart_tv,
02325       .common.local_addr = {
02326          .sin       = mansession_encode_sin_local(s, &sin_local),
02327          .transport = mansession_get_transport(s),
02328       },
02329       .common.remote_addr = {
02330          .sin       = &s->session->sin,
02331          .transport = mansession_get_transport(s),
02332       },
02333       .common.session_id = session_id,
02334    };
02335 
02336    snprintf(session_id, sizeof(session_id), "%p", s->session);
02337 
02338    ast_security_event_report(AST_SEC_EVT(&session_limit));
02339 }

static int send_string ( struct mansession s,
char *  string 
) [static]

helper function to send a string to the socket. Return -1 on error (e.g. buffer full).

Definition at line 1955 of file manager.c.

References ast_careful_fwrite(), EVENT_FLAG_HOOKRESPONSE, mansession_session::f, mansession::f, f, mansession_session::fd, mansession::fd, manager_custom_hook::helper, mansession::hook, mansession::session, mansession::write_error, and mansession_session::writetimeout.

Referenced by astman_append(), and process_events().

01956 {
01957    int res;
01958    FILE *f = s->f ? s->f : s->session->f;
01959    int fd = s->f ? s->fd : s->session->fd;
01960 
01961    /* It's a result from one of the hook's action invocation */
01962    if (s->hook) {
01963       /*
01964        * to send responses, we're using the same function
01965        * as for receiving events. We call the event "HookResponse"
01966        */
01967       s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string);
01968       return 0;
01969    }
01970        
01971    if ((res = ast_careful_fwrite(f, fd, string, strlen(string), s->session->writetimeout))) {
01972       s->write_error = 1;
01973    }
01974 
01975    return res;
01976 }

static void session_destroy ( struct mansession_session s  )  [static]

Definition at line 1360 of file manager.c.

References ao2_unlink, and unref_mansession().

Referenced by purge_sessions(), session_do(), and spandsp_fax_destroy().

01361 {
01362    unref_mansession(s);
01363    ao2_unlink(sessions, s);
01364 }

static void session_destructor ( void *  obj  )  [static]

Definition at line 1293 of file manager.c.

References ao2_t_callback, ao2_t_ref, ast_atomic_fetchadd_int(), ast_datastore_free(), AST_LIST_REMOVE_HEAD, mansession_session::blackfilters, mansession_session::datastores, ast_datastore::entry, mansession_session::f, mansession_session::last_ev, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, eventqent::usecount, and mansession_session::whitefilters.

Referenced by build_mansession().

01294 {
01295    struct mansession_session *session = obj;
01296    struct eventqent *eqe = session->last_ev;
01297    struct ast_datastore *datastore;
01298 
01299    /* Get rid of each of the data stores on the session */
01300    while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) {
01301       /* Free the data store */
01302       ast_datastore_free(datastore);
01303    }
01304 
01305    if (session->f != NULL) {
01306       fclose(session->f);
01307    }
01308    if (eqe) {
01309       ast_atomic_fetchadd_int(&eqe->usecount, -1);
01310    }
01311 
01312    if (session->whitefilters) {
01313       ao2_t_callback(session->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters");
01314       ao2_t_ref(session->whitefilters, -1 , "decrement ref for white container, should be last one");
01315    }
01316 
01317    if (session->blackfilters) {
01318       ao2_t_callback(session->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters");
01319       ao2_t_ref(session->blackfilters, -1 , "decrement ref for black container, should be last one");
01320    }
01321 }

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

The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ).

Definition at line 4849 of file manager.c.

References AMI_VERSION, ao2_lock, ao2_unlock, ast_atomic_fetchadd_int(), AST_LIST_HEAD_INIT_NOLOCK, ast_log(), ast_mutex_init, ast_sockaddr_to_sin, astman_append(), authlimit, mansession_session::authstart, block_sockets, build_mansession(), mansession_session::datastores, do_message(), errno, mansession::f, mansession_session::f, ast_tcptls_session_instance::f, mansession::fd, mansession_session::fd, ast_tcptls_session_instance::fd, ast_frame::flags, grab_last(), mansession_session::last_ev, mansession::lock, LOG_ERROR, LOG_WARNING, ast_tcptls_session_instance::remote_address, mansession::session, session_destroy(), mansession_session::sin, mansession::tcptls_session, unauth_sessions, and mansession::write_error.

04850 {
04851    struct ast_tcptls_session_instance *ser = data;
04852    struct mansession_session *session;
04853    struct mansession s = {
04854       .tcptls_session = data,
04855    };
04856    int flags;
04857    int res;
04858    struct sockaddr_in ser_remote_address_tmp;
04859    struct protoent *p;
04860 
04861    if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
04862       fclose(ser->f);
04863       ast_atomic_fetchadd_int(&unauth_sessions, -1);
04864       goto done;
04865    }
04866 
04867    ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
04868    session = build_mansession(ser_remote_address_tmp);
04869 
04870    if (session == NULL) {
04871       fclose(ser->f);
04872       ast_atomic_fetchadd_int(&unauth_sessions, -1);
04873       goto done;
04874    }
04875 
04876    /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
04877     * This is necessary to prevent delays (caused by buffering) as we
04878     * write to the socket in bits and peices. */
04879    p = getprotobyname("tcp");
04880    if (p) {
04881       int arg = 1;
04882       if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
04883          ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY mode: %s\nSome manager actions may be slow to respond.\n", strerror(errno));
04884       }
04885    } else {
04886       ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY, getprotobyname(\"tcp\") failed\nSome manager actions may be slow to respond.\n");
04887    }
04888 
04889    flags = fcntl(ser->fd, F_GETFL);
04890    if (!block_sockets) { /* make sure socket is non-blocking */
04891       flags |= O_NONBLOCK;
04892    } else {
04893       flags &= ~O_NONBLOCK;
04894    }
04895    fcntl(ser->fd, F_SETFL, flags);
04896 
04897    ao2_lock(session);
04898    /* Hook to the tail of the event queue */
04899    session->last_ev = grab_last();
04900 
04901    ast_mutex_init(&s.lock);
04902 
04903    /* these fields duplicate those in the 'ser' structure */
04904    session->fd = s.fd = ser->fd;
04905    session->f = s.f = ser->f;
04906    session->sin = ser_remote_address_tmp;
04907    s.session = session;
04908 
04909    AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
04910 
04911    if(time(&session->authstart) == -1) {
04912       ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
04913       ast_atomic_fetchadd_int(&unauth_sessions, -1);
04914       ao2_unlock(session);
04915       session_destroy(session);
04916       goto done;
04917    }
04918    ao2_unlock(session);
04919 
04920    astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION);   /* welcome prompt */
04921    for (;;) {
04922       if ((res = do_message(&s)) < 0 || s.write_error) {
04923          break;
04924       }
04925    }
04926    /* session is over, explain why and terminate */
04927    if (session->authenticated) {
04928       if (manager_displayconnects(session)) {
04929          ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
04930       }
04931    } else {
04932       ast_atomic_fetchadd_int(&unauth_sessions, -1);
04933       if (displayconnects) {
04934          ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
04935       }
04936    }
04937 
04938    session_destroy(session);
04939 
04940    ast_mutex_destroy(&s.lock);
04941 done:
04942    ao2_ref(ser, -1);
04943    ser = NULL;
04944    return NULL;
04945 }

static int set_eventmask ( struct mansession s,
const char *  eventmask 
) [static]

Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm.

Definition at line 2092 of file manager.c.

References ao2_lock, ao2_unlock, mansession_session::send_events, mansession::session, and strings_to_mask().

Referenced by action_events(), and authenticate().

02093 {
02094    int maskint = strings_to_mask(eventmask);
02095 
02096    ao2_lock(s->session);
02097    if (maskint >= 0) {
02098       s->session->send_events = maskint;
02099    }
02100    ao2_unlock(s->session);
02101 
02102    return maskint;
02103 }

static int strings_to_mask ( const char *  string  )  [static]

A number returns itself, false returns 0, true returns all flags, other strings return the flags that are set.

Definition at line 1247 of file manager.c.

References ARRAY_LEN, ast_false(), ast_strlen_zero(), ast_true(), get_perm(), and perms.

Referenced by set_eventmask().

01248 {
01249    const char *p;
01250 
01251    if (ast_strlen_zero(string)) {
01252       return -1;
01253    }
01254 
01255    for (p = string; *p; p++) {
01256       if (*p < '0' || *p > '9') {
01257          break;
01258       }
01259    }
01260    if (!*p) { /* all digits */
01261       return atoi(string);
01262    }
01263    if (ast_false(string)) {
01264       return 0;
01265    }
01266    if (ast_true(string)) { /* all permissions */
01267       int x, ret = 0;
01268       for (x = 0; x < ARRAY_LEN(perms); x++) {
01269          ret |= perms[x].num;
01270       }
01271       return ret;
01272    }
01273    return get_perm(string);
01274 }

static struct mansession_session* unref_mansession ( struct mansession_session s  )  [static]

Unreference manager session object. If no more references, then go ahead and delete it.

Definition at line 1278 of file manager.c.

References ao2_ref, ast_log(), and LOG_DEBUG.

Referenced by __ast_manager_event_multichan(), astman_is_authed(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), check_manager_session_inuse(), find_session(), find_session_by_nonce(), handle_showmanconn(), purge_sessions(), and session_destroy().

01279 {
01280    int refcount = ao2_ref(s, -1);
01281         if (manager_debug) {
01282       ast_log(LOG_DEBUG, "Mansession: %p refcount now %d\n", s, refcount - 1);
01283    }
01284    return s;
01285 }

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

Definition at line 4183 of file manager.c.

References CMP_MATCH, and CMP_STOP.

Referenced by match_filter().

04184 {
04185    regex_t *regex_filter = obj;
04186    const char *eventdata = arg;
04187    int *result = data;
04188 
04189    if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
04190       *result = 1;
04191       return (CMP_MATCH | CMP_STOP);
04192    }
04193 
04194    return 0;
04195 }


Variable Documentation

int allowmultiplelogin = 1 [static]

Definition at line 891 of file manager.c.

Referenced by handle_manager_show_settings(), and process_message().

struct ast_threadstorage astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , } [static]

Definition at line 1985 of file manager.c.

Referenced by astman_append().

int authlimit [static]

Definition at line 899 of file manager.c.

int authtimeout [static]

Definition at line 898 of file manager.c.

int block_sockets [static]

Definition at line 905 of file manager.c.

Referenced by __init_manager(), handle_manager_show_settings(), and session_do().

int broken_events_action [static]

Definition at line 894 of file manager.c.

Referenced by __init_manager(), and action_events().

struct { ... } command_blacklist[] [static]

Referenced by check_blacklist().

const int DEFAULT_AUTHLIMIT = 50 [static]

Default setting for authlimit

Definition at line 887 of file manager.c.

Referenced by __init_manager(), and reload_config().

const int DEFAULT_AUTHTIMEOUT = 30 [static]

Default setting for authtimeout

Definition at line 886 of file manager.c.

Referenced by __init_manager(), and reload_config().

const int DEFAULT_BLOCKSOCKETS = 0 [static]

Default setting for block-sockets

Definition at line 881 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_BROKENEVENTSACTION = 0 [static]

Default setting for brokeneventsaction

Definition at line 885 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_DISPLAYCONNECTS = 1 [static]

Default setting for displaying manager connections

Definition at line 882 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_ENABLED = 0 [static]

Default setting for manager to be enabled

Definition at line 879 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_HTTPTIMEOUT = 60 [static]

Default manager http timeout

Definition at line 884 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_MANAGERDEBUG = 0 [static]

Default setting for manager debug

Definition at line 888 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_TIMESTAMPEVENTS = 0 [static]

Default setting for timestampevents

Definition at line 883 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_WEBENABLED = 0 [static]

Default setting for the web interface to be enabled

Definition at line 880 of file manager.c.

Referenced by __init_manager().

int displayconnects [static]

Definition at line 890 of file manager.c.

Referenced by __init_manager(), do_message(), and handle_manager_show_settings().

char global_realm[MAXHOSTNAMELEN] [static]

Default realm

Definition at line 903 of file manager.c.

Referenced by __init_manager().

int httptimeout [static]

Definition at line 893 of file manager.c.

Referenced by __init_manager(), and handle_manager_show_settings().

char* manager_channelvars [static]

Definition at line 900 of file manager.c.

Referenced by handle_manager_show_settings(), and load_channelvars().

int manager_debug = 0 [static]

enable some debugging code in the manager

Definition at line 897 of file manager.c.

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

int manager_enabled = 0 [static]

Definition at line 895 of file manager.c.

Referenced by __init_manager(), and handle_manager_show_settings().

struct ast_threadstorage manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , } [static]

Definition at line 5028 of file manager.c.

Referenced by __ast_manager_event_multichan().

struct ast_threadstorage manager_event_funcbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_funcbuf , .custom_init = NULL , } [static]

Definition at line 5001 of file manager.c.

Referenced by append_channel_vars().

struct permalias perms[] [static]

helper functions to convert back and forth between string and numeric representation of set of flags

Referenced by action_events(), authority_to_str(), get_perm(), and strings_to_mask().

struct ao2_container* sessions = NULL [static]

Definition at line 1009 of file manager.c.

int timestampevents [static]

Definition at line 892 of file manager.c.

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

int unauth_sessions = 0 [static]

Definition at line 906 of file manager.c.

struct ast_threadstorage userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , } [static]

Definition at line 1986 of file manager.c.

Referenced by action_userevent().

int webmanager_enabled = 0 [static]

Definition at line 896 of file manager.c.

Referenced by __init_manager(), and handle_manager_show_settings().

const char* words[AST_MAX_CMD_LEN] [inherited]

Definition at line 921 of file manager.c.


Generated on Mon Mar 19 11:30:57 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7