Wed Apr 6 11:30:11 2011

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)
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 int action_events (struct mansession *s, const struct message *m)
static int action_extensionstate (struct mansession *s, const struct message *m)
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,...)
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 ()
 Check if AMI is enabled.
static int check_manager_session_inuse (const char *name)
int check_webmanager_enabled ()
 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 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 block_sockets
static int broken_events_action
struct {
   const char *   words [AST_MAX_CMD_LEN]
command_blacklist []
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_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
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 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 1880 of file manager.c.

Referenced by astman_append().

#define DEFAULT_REALM   "asterisk"

Definition at line 873 of file manager.c.

Referenced by __init_manager().

#define GET_HEADER_FIRST_MATCH   0

Definition at line 1701 of file manager.c.

Referenced by astman_get_header().

#define GET_HEADER_LAST_MATCH   1

Definition at line 1702 of file manager.c.

Referenced by __astman_get_header().

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 1703 of file manager.c.

Referenced by __astman_get_header(), and process_message().

#define MANAGER_EVENT_BUF_INITSIZE   256

Definition at line 4783 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 890 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 1921 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 811 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 4785 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().

04787 {
04788    struct mansession_session *session;
04789    struct manager_custom_hook *hook;
04790    struct ast_str *auth = ast_str_alloca(80);
04791    const char *cat_str;
04792    va_list ap;
04793    struct timeval now;
04794    struct ast_str *buf;
04795    int i;
04796 
04797    if (!(sessions && ao2_container_count(sessions)) && AST_RWLIST_EMPTY(&manager_hooks)) {
04798       return 0;
04799    }
04800    
04801    if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) {
04802       return -1;
04803    }
04804 
04805    cat_str = authority_to_str(category, &auth);
04806    ast_str_set(&buf, 0,
04807          "Event: %s\r\nPrivilege: %s\r\n",
04808           event, cat_str);
04809 
04810    if (timestampevents) {
04811       now = ast_tvnow();
04812       ast_str_append(&buf, 0,
04813             "Timestamp: %ld.%06lu\r\n",
04814              (long)now.tv_sec, (unsigned long) now.tv_usec);
04815    }
04816    if (manager_debug) {
04817       static int seq;
04818       ast_str_append(&buf, 0,
04819             "SequenceNumber: %d\r\n",
04820              ast_atomic_fetchadd_int(&seq, 1));
04821       ast_str_append(&buf, 0,
04822             "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func);
04823    }
04824 
04825    va_start(ap, fmt);
04826    ast_str_append_va(&buf, 0, fmt, ap);
04827    va_end(ap);
04828    for (i = 0; i < chancount; i++) {
04829       append_channel_vars(&buf, chans[i]);
04830    }
04831 
04832    ast_str_append(&buf, 0, "\r\n");
04833 
04834    append_event(ast_str_buffer(buf), category);
04835 
04836    /* Wake up any sleeping sessions */
04837    if (sessions) {
04838       struct ao2_iterator i;
04839       i = ao2_iterator_init(sessions, 0);
04840       while ((session = ao2_iterator_next(&i))) {
04841          ao2_lock(session);
04842          if (session->waiting_thread != AST_PTHREADT_NULL) {
04843             pthread_kill(session->waiting_thread, SIGURG);
04844          } else {
04845             /* We have an event to process, but the mansession is
04846              * not waiting for it. We still need to indicate that there
04847              * is an event waiting so that get_input processes the pending
04848              * event instead of polling.
04849              */
04850             session->pending_event = 1;
04851          }
04852          ao2_unlock(session);
04853          unref_mansession(session);
04854       }
04855       ao2_iterator_destroy(&i);
04856    }
04857 
04858    if (!AST_RWLIST_EMPTY(&manager_hooks)) {
04859       AST_RWLIST_RDLOCK(&manager_hooks);
04860       AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) {
04861          hook->helper(category, event, ast_str_buffer(buf));
04862       }
04863       AST_RWLIST_UNLOCK(&manager_hooks);
04864    }
04865 
04866    return 0;
04867 }

static const char* __astman_get_header ( const struct message m,
char *  var,
int  mode 
) [static]

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

01705 {
01706    int x, l = strlen(var);
01707    const char *result = "";
01708 
01709    for (x = 0; x < m->hdrcount; x++) {
01710       const char *h = m->headers[x];
01711       if (!strncasecmp(var, h, l) && h[l] == ':') {
01712          const char *value = h + l + 1;
01713          value = ast_skip_blanks(value); /* ignore leading spaces in the value */
01714          /* found a potential candidate */
01715          if (mode & GET_HEADER_SKIP_EMPTY && ast_strlen_zero(value))
01716             continue;   /* not interesting */
01717          if (mode & GET_HEADER_LAST_MATCH)
01718             result = value;   /* record the last match so far */
01719          else
01720             return value;
01721       }
01722    }
01723 
01724    return "";
01725 }

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

01886 {

static void __init_manager_event_buf ( void   )  [static]

Definition at line 4782 of file manager.c.

04787 {

static void __init_manager_event_funcbuf ( void   )  [static]

Definition at line 4759 of file manager.c.

04762 {

static void __init_userevent_buf ( void   )  [static]

Definition at line 1877 of file manager.c.

01886 {

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

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

03613 {
03614    const char *channel = astman_get_header(m, "Channel");
03615    const char *pchannel = astman_get_header(m, "ChannelPrefix");
03616    const char *msgtype = astman_get_header(m, "MsgType");
03617    const char *chargetype = astman_get_header(m, "ChargeType");
03618    const char *currencyname = astman_get_header(m, "CurrencyName");
03619    const char *currencyamount = astman_get_header(m, "CurrencyAmount");
03620    const char *mult = astman_get_header(m, "CurrencyMultiplier");
03621    const char *totaltype = astman_get_header(m, "TotalType");
03622    const char *aocbillingid = astman_get_header(m, "AOCBillingId");
03623    const char *association_id= astman_get_header(m, "ChargingAssociationId");
03624    const char *association_num = astman_get_header(m, "ChargingAssociationNumber");
03625    const char *association_plan = astman_get_header(m, "ChargingAssociationPlan");
03626 
03627    enum ast_aoc_type _msgtype;
03628    enum ast_aoc_charge_type _chargetype;
03629    enum ast_aoc_currency_multiplier _mult = AST_AOC_MULT_ONE;
03630    enum ast_aoc_total_type _totaltype = AST_AOC_TOTAL;
03631    enum ast_aoc_billing_id _billingid = AST_AOC_BILLING_NA;
03632    unsigned int _currencyamount = 0;
03633    int _association_id = 0;
03634    unsigned int _association_plan = 0;
03635    struct ast_channel *chan = NULL;
03636 
03637    struct ast_aoc_decoded *decoded = NULL;
03638    struct ast_aoc_encoded *encoded = NULL;
03639    size_t encoded_size = 0;
03640 
03641    if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) {
03642       astman_send_error(s, m, "Channel and PartialChannel are not specified. Specify at least one of these.");
03643       goto aocmessage_cleanup;
03644    }
03645 
03646    if (!(chan = ast_channel_get_by_name(channel)) && !ast_strlen_zero(pchannel)) {
03647       chan = ast_channel_get_by_name_prefix(pchannel, strlen(pchannel));
03648    }
03649 
03650    if (!chan) {
03651       astman_send_error(s, m, "No such channel");
03652       goto aocmessage_cleanup;
03653    }
03654 
03655    if (ast_strlen_zero(msgtype) || (strcasecmp(msgtype, "d") && strcasecmp(msgtype, "e"))) {
03656       astman_send_error(s, m, "Invalid MsgType");
03657       goto aocmessage_cleanup;
03658    }
03659 
03660    if (ast_strlen_zero(chargetype)) {
03661       astman_send_error(s, m, "ChargeType not specified");
03662       goto aocmessage_cleanup;
03663    }
03664 
03665    _msgtype = strcasecmp(msgtype, "d") ? AST_AOC_E : AST_AOC_D;
03666 
03667    if (!strcasecmp(chargetype, "NA")) {
03668       _chargetype = AST_AOC_CHARGE_NA;
03669    } else if (!strcasecmp(chargetype, "Free")) {
03670       _chargetype = AST_AOC_CHARGE_FREE;
03671    } else if (!strcasecmp(chargetype, "Currency")) {
03672       _chargetype = AST_AOC_CHARGE_CURRENCY;
03673    } else if (!strcasecmp(chargetype, "Unit")) {
03674       _chargetype = AST_AOC_CHARGE_UNIT;
03675    } else {
03676       astman_send_error(s, m, "Invalid ChargeType");
03677       goto aocmessage_cleanup;
03678    }
03679 
03680    if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
03681 
03682       if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u", &_currencyamount) != 1)) {
03683          astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency");
03684          goto aocmessage_cleanup;
03685       }
03686 
03687       if (ast_strlen_zero(mult)) {
03688          astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency.");
03689          goto aocmessage_cleanup;
03690       } else if (!strcasecmp(mult, "onethousandth")) {
03691          _mult = AST_AOC_MULT_ONETHOUSANDTH;
03692       } else if (!strcasecmp(mult, "onehundredth")) {
03693          _mult = AST_AOC_MULT_ONEHUNDREDTH;
03694       } else if (!strcasecmp(mult, "onetenth")) {
03695          _mult = AST_AOC_MULT_ONETENTH;
03696       } else if (!strcasecmp(mult, "one")) {
03697          _mult = AST_AOC_MULT_ONE;
03698       } else if (!strcasecmp(mult, "ten")) {
03699          _mult = AST_AOC_MULT_TEN;
03700       } else if (!strcasecmp(mult, "hundred")) {
03701          _mult = AST_AOC_MULT_HUNDRED;
03702       } else if (!strcasecmp(mult, "thousand")) {
03703          _mult = AST_AOC_MULT_THOUSAND;
03704       } else {
03705          astman_send_error(s, m, "Invalid ChargeMultiplier");
03706          goto aocmessage_cleanup;
03707       }
03708    }
03709 
03710    /* create decoded object and start setting values */
03711    if (!(decoded = ast_aoc_create(_msgtype, _chargetype, 0))) {
03712          astman_send_error(s, m, "Message Creation Failed");
03713          goto aocmessage_cleanup;
03714    }
03715 
03716    if (_msgtype == AST_AOC_D) {
03717       if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype, "subtotal")) {
03718          _totaltype = AST_AOC_SUBTOTAL;
03719       }
03720 
03721       if (ast_strlen_zero(aocbillingid)) {
03722          /* ignore this is optional */
03723       } else if (!strcasecmp(aocbillingid, "Normal")) {
03724          _billingid = AST_AOC_BILLING_NORMAL;
03725       } else if (!strcasecmp(aocbillingid, "ReverseCharge")) {
03726          _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
03727       } else if (!strcasecmp(aocbillingid, "CreditCard")) {
03728          _billingid = AST_AOC_BILLING_CREDIT_CARD;
03729       } else {
03730          astman_send_error(s, m, "Invalid AOC-D AOCBillingId");
03731          goto aocmessage_cleanup;
03732       }
03733    } else {
03734       if (ast_strlen_zero(aocbillingid)) {
03735          /* ignore this is optional */
03736       } else if (!strcasecmp(aocbillingid, "Normal")) {
03737          _billingid = AST_AOC_BILLING_NORMAL;
03738       } else if (!strcasecmp(aocbillingid, "ReverseCharge")) {
03739          _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
03740       } else if (!strcasecmp(aocbillingid, "CreditCard")) {
03741          _billingid = AST_AOC_BILLING_CREDIT_CARD;
03742       } else if (!strcasecmp(aocbillingid, "CallFwdUnconditional")) {
03743          _billingid = AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL;
03744       } else if (!strcasecmp(aocbillingid, "CallFwdBusy")) {
03745          _billingid = AST_AOC_BILLING_CALL_FWD_BUSY;
03746       } else if (!strcasecmp(aocbillingid, "CallFwdNoReply")) {
03747          _billingid = AST_AOC_BILLING_CALL_FWD_NO_REPLY;
03748       } else if (!strcasecmp(aocbillingid, "CallDeflection")) {
03749          _billingid = AST_AOC_BILLING_CALL_DEFLECTION;
03750       } else if (!strcasecmp(aocbillingid, "CallTransfer")) {
03751          _billingid = AST_AOC_BILLING_CALL_TRANSFER;
03752       } else {
03753          astman_send_error(s, m, "Invalid AOC-E AOCBillingId");
03754          goto aocmessage_cleanup;
03755       }
03756 
03757       if (!ast_strlen_zero(association_id) && (sscanf(association_id, "%30d", &_association_id) != 1)) {
03758          astman_send_error(s, m, "Invalid ChargingAssociationId");
03759          goto aocmessage_cleanup;
03760       }
03761       if (!ast_strlen_zero(association_plan) && (sscanf(association_plan, "%30u", &_association_plan) != 1)) {
03762          astman_send_error(s, m, "Invalid ChargingAssociationPlan");
03763          goto aocmessage_cleanup;
03764       }
03765 
03766       if (_association_id) {
03767          ast_aoc_set_association_id(decoded, _association_id);
03768       } else if (!ast_strlen_zero(association_num)) {
03769          ast_aoc_set_association_number(decoded, association_num, _association_plan);
03770       }
03771    }
03772 
03773    if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
03774       ast_aoc_set_currency_info(decoded, _currencyamount, _mult, ast_strlen_zero(currencyname) ? NULL : currencyname);
03775    } else if (_chargetype == AST_AOC_CHARGE_UNIT) {
03776       struct ast_aoc_unit_entry entry;
03777       int i;
03778 
03779       /* multiple unit entries are possible, lets get them all */
03780       for (i = 0; i < 32; i++) {
03781          if (aocmessage_get_unit_entry(m, &entry, i)) {
03782             break; /* that's the end then */
03783          }
03784 
03785          ast_aoc_add_unit_entry(decoded, entry.valid_amount, entry.amount, entry.valid_type, entry.type);
03786       }
03787 
03788       /* at least one unit entry is required */
03789       if (!i) {
03790          astman_send_error(s, m, "Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit");
03791          goto aocmessage_cleanup;
03792       }
03793 
03794    }
03795 
03796    ast_aoc_set_billing_id(decoded, _billingid);
03797    ast_aoc_set_total_type(decoded, _totaltype);
03798 
03799 
03800    if ((encoded = ast_aoc_encode(decoded, &encoded_size, NULL)) && !ast_indicate_data(chan, AST_CONTROL_AOC, encoded, encoded_size)) {
03801       astman_send_ack(s, m, "AOC Message successfully queued on channel");
03802    } else {
03803       astman_send_error(s, m, "Error encoding AOC message, could not queue onto channel");
03804    }
03805 
03806 aocmessage_cleanup:
03807 
03808    ast_aoc_destroy_decoded(decoded);
03809    ast_aoc_destroy_encoded(encoded);
03810 
03811    if (chan) {
03812       chan = ast_channel_unref(chan);
03813    }
03814    return 0;
03815 }

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

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

03380 {
03381    const char *name = astman_get_header(m, "Channel");
03382    const char *exten = astman_get_header(m, "Exten");
03383    const char *context = astman_get_header(m, "Context");
03384    struct ast_channel *chan = NULL;
03385    struct ast_call_feature *atxfer_feature = NULL;
03386    char *feature_code = NULL;
03387 
03388    if (ast_strlen_zero(name)) {
03389       astman_send_error(s, m, "No channel specified");
03390       return 0;
03391    }
03392    if (ast_strlen_zero(exten)) {
03393       astman_send_error(s, m, "No extension specified");
03394       return 0;
03395    }
03396 
03397    if (!(atxfer_feature = ast_find_call_feature("atxfer"))) {
03398       astman_send_error(s, m, "No attended transfer feature found");
03399       return 0;
03400    }
03401 
03402    if (!(chan = ast_channel_get_by_name(name))) {
03403       astman_send_error(s, m, "Channel specified does not exist");
03404       return 0;
03405    }
03406 
03407    if (!ast_strlen_zero(context)) {
03408       pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context);
03409    }
03410 
03411    for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) {
03412       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code };
03413       ast_queue_frame(chan, &f);
03414    }
03415 
03416    for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) {
03417       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code };
03418       ast_queue_frame(chan, &f);
03419    }
03420 
03421    chan = ast_channel_unref(chan);
03422 
03423    astman_send_ack(s, m, "Atxfer successfully queued");
03424 
03425    return 0;
03426 }

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

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

02949 {
02950    const char *authtype = astman_get_header(m, "AuthType");
02951 
02952    if (!strcasecmp(authtype, "MD5")) {
02953       if (ast_strlen_zero(s->session->challenge)) {
02954          snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
02955       }
02956       mansession_lock(s);
02957       astman_start_ack(s, m);
02958       astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
02959       mansession_unlock(s);
02960    } else {
02961       astman_send_error(s, m, "Must specify AuthType");
02962    }
02963    return 0;
02964 }

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

Manager command "command" - execute CLI command.

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

03465 {
03466    const char *cmd = astman_get_header(m, "Command");
03467    const char *id = astman_get_header(m, "ActionID");
03468    char *buf, *final_buf;
03469    char template[] = "/tmp/ast-ami-XXXXXX";  /* template for temporary file */
03470    int fd;
03471    off_t l;
03472 
03473    if (ast_strlen_zero(cmd)) {
03474       astman_send_error(s, m, "No command provided");
03475       return 0;
03476    }
03477 
03478    if (check_blacklist(cmd)) {
03479       astman_send_error(s, m, "Command blacklisted");
03480       return 0;
03481    }
03482 
03483    fd = mkstemp(template);
03484 
03485    astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
03486    if (!ast_strlen_zero(id)) {
03487       astman_append(s, "ActionID: %s\r\n", id);
03488    }
03489    /* FIXME: Wedge a ActionID response in here, waiting for later changes */
03490    ast_cli_command(fd, cmd);  /* XXX need to change this to use a FILE * */
03491    l = lseek(fd, 0, SEEK_END);   /* how many chars available */
03492 
03493    /* This has a potential to overflow the stack.  Hence, use the heap. */
03494    buf = ast_calloc(1, l + 1);
03495    final_buf = ast_calloc(1, l + 1);
03496    if (buf) {
03497       lseek(fd, 0, SEEK_SET);
03498       if (read(fd, buf, l) < 0) {
03499          ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
03500       }
03501       buf[l] = '\0';
03502       if (final_buf) {
03503          term_strip(final_buf, buf, l);
03504          final_buf[l] = '\0';
03505       }
03506       astman_append(s, "%s", S_OR(final_buf, buf));
03507       ast_free(buf);
03508    }
03509    close(fd);
03510    unlink(template);
03511    astman_append(s, "--END COMMAND--\r\n\r\n");
03512    if (final_buf) {
03513       ast_free(final_buf);
03514    }
03515    return 0;
03516 }

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

Show PBX core settings information.

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

04152 {
04153    const char *actionid = astman_get_header(m, "ActionID");
04154    char idText[150];
04155 
04156    if (!ast_strlen_zero(actionid)) {
04157       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
04158    } else {
04159       idText[0] = '\0';
04160    }
04161 
04162    astman_append(s, "Response: Success\r\n"
04163          "%s"
04164          "AMIversion: %s\r\n"
04165          "AsteriskVersion: %s\r\n"
04166          "SystemName: %s\r\n"
04167          "CoreMaxCalls: %d\r\n"
04168          "CoreMaxLoadAvg: %f\r\n"
04169          "CoreRunUser: %s\r\n"
04170          "CoreRunGroup: %s\r\n"
04171          "CoreMaxFilehandles: %d\r\n"
04172          "CoreRealTimeEnabled: %s\r\n"
04173          "CoreCDRenabled: %s\r\n"
04174          "CoreHTTPenabled: %s\r\n"
04175          "\r\n",
04176          idText,
04177          AMI_VERSION,
04178          ast_get_version(),
04179          ast_config_AST_SYSTEM_NAME,
04180          option_maxcalls,
04181          option_maxload,
04182          ast_config_AST_RUN_USER,
04183          ast_config_AST_RUN_GROUP,
04184          option_maxfiles,
04185          AST_CLI_YESNO(ast_realtime_enabled()),
04186          AST_CLI_YESNO(check_cdr_enabled()),
04187          AST_CLI_YESNO(check_webmanager_enabled())
04188          );
04189    return 0;
04190 }

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 4248 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::context, ast_channel::data, ast_channel::exten, ast_party_caller::id, ast_channel::name, ast_party_id::number, ast_channel::priority, S_COR, S_OR, ast_cdr::start, ast_party_number::str, ast_channel::uniqueid, and ast_party_number::valid.

Referenced by __init_manager().

04249 {
04250    const char *actionid = astman_get_header(m, "ActionID");
04251    char idText[256];
04252    struct ast_channel *c = NULL;
04253    int numchans = 0;
04254    int duration, durh, durm, durs;
04255    struct ast_channel_iterator *iter;
04256 
04257    if (!ast_strlen_zero(actionid)) {
04258       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
04259    } else {
04260       idText[0] = '\0';
04261    }
04262 
04263    if (!(iter = ast_channel_iterator_all_new())) {
04264       astman_send_error(s, m, "Memory Allocation Failure");
04265       return 1;
04266    }
04267 
04268    astman_send_listack(s, m, "Channels will follow", "start");
04269 
04270    for (; (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) {
04271       struct ast_channel *bc;
04272       char durbuf[10] = "";
04273 
04274       ast_channel_lock(c);
04275 
04276       bc = ast_bridged_channel(c);
04277       if (c->cdr && !ast_tvzero(c->cdr->start)) {
04278          duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
04279          durh = duration / 3600;
04280          durm = (duration % 3600) / 60;
04281          durs = duration % 60;
04282          snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
04283       }
04284 
04285       astman_append(s,
04286          "Event: CoreShowChannel\r\n"
04287          "%s"
04288          "Channel: %s\r\n"
04289          "UniqueID: %s\r\n"
04290          "Context: %s\r\n"
04291          "Extension: %s\r\n"
04292          "Priority: %d\r\n"
04293          "ChannelState: %d\r\n"
04294          "ChannelStateDesc: %s\r\n"
04295          "Application: %s\r\n"
04296          "ApplicationData: %s\r\n"
04297          "CallerIDnum: %s\r\n"
04298          "Duration: %s\r\n"
04299          "AccountCode: %s\r\n"
04300          "BridgedChannel: %s\r\n"
04301          "BridgedUniqueID: %s\r\n"
04302          "\r\n", idText, c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state,
04303          ast_state2str(c->_state), c->appl ? c->appl : "", c->data ? S_OR(c->data, "") : "",
04304          S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""),
04305          durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : "");
04306 
04307       ast_channel_unlock(c);
04308 
04309       numchans++;
04310    }
04311 
04312    astman_append(s,
04313       "Event: CoreShowChannelsComplete\r\n"
04314       "EventList: Complete\r\n"
04315       "ListItems: %d\r\n"
04316       "%s"
04317       "\r\n", numchans, idText);
04318 
04319    ast_channel_iterator_destroy(iter);
04320 
04321    return 0;
04322 }

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

Show PBX core status information.

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

04194 {
04195    const char *actionid = astman_get_header(m, "ActionID");
04196    char idText[150];
04197    char startuptime[150], startupdate[150];
04198    char reloadtime[150], reloaddate[150];
04199    struct ast_tm tm;
04200 
04201    if (!ast_strlen_zero(actionid)) {
04202       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
04203    } else {
04204       idText[0] = '\0';
04205    }
04206 
04207    ast_localtime(&ast_startuptime, &tm, NULL);
04208    ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm);
04209    ast_strftime(startupdate, sizeof(startupdate), "%Y-%m-%d", &tm);
04210    ast_localtime(&ast_lastreloadtime, &tm, NULL);
04211    ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm);
04212    ast_strftime(reloaddate, sizeof(reloaddate), "%Y-%m-%d", &tm);
04213 
04214    astman_append(s, "Response: Success\r\n"
04215          "%s"
04216          "CoreStartupDate: %s\r\n"
04217          "CoreStartupTime: %s\r\n"
04218          "CoreReloadDate: %s\r\n"
04219          "CoreReloadTime: %s\r\n"
04220          "CoreCurrentCalls: %d\r\n"
04221          "\r\n",
04222          idText,
04223          startupdate,
04224          startuptime,
04225          reloaddate,
04226          reloadtime,
04227          ast_active_channels()
04228          );
04229    return 0;
04230 }

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

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

02740 {
02741    int fd;
02742    const char *fn = astman_get_header(m, "Filename");
02743    struct ast_str *filepath = ast_str_alloca(PATH_MAX);
02744    ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR);
02745    ast_str_append(&filepath, 0, "%s", fn);
02746 
02747    if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
02748       close(fd);
02749       astman_send_ack(s, m, "New configuration file created successfully");
02750    } else {
02751       astman_send_error(s, m, strerror(errno));
02752    }
02753 
02754    return 0;
02755 }

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

Definition at line 2881 of file manager.c.

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

Referenced by __init_manager().

02882 {
02883    const char *mask = astman_get_header(m, "EventMask");
02884    int res, x;
02885 
02886    res = set_eventmask(s, mask);
02887    if (broken_events_action) {
02888       /* if this option is set we should not return a response on
02889        * error, or when all events are set */
02890 
02891       if (res > 0) {
02892          for (x = 0; x < ARRAY_LEN(perms); x++) {
02893             if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) {
02894                return 0;
02895             }
02896          }
02897          astman_append(s, "Response: Success\r\n"
02898                 "Events: On\r\n\r\n");
02899       } else if (res == 0)
02900          astman_append(s, "Response: Success\r\n"
02901                 "Events: Off\r\n\r\n");
02902       return 0;
02903    }
02904 
02905    if (res > 0)
02906       astman_append(s, "Response: Success\r\n"
02907              "Events: On\r\n\r\n");
02908    else if (res == 0)
02909       astman_append(s, "Response: Success\r\n"
02910              "Events: Off\r\n\r\n");
02911    else
02912       astman_send_error(s, m, "Invalid event mask");
02913 
02914    return 0;
02915 }

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

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

03991 {
03992    const char *exten = astman_get_header(m, "Exten");
03993    const char *context = astman_get_header(m, "Context");
03994    char hint[256] = "";
03995    int status;
03996    if (ast_strlen_zero(exten)) {
03997       astman_send_error(s, m, "Extension not specified");
03998       return 0;
03999    }
04000    if (ast_strlen_zero(context)) {
04001       context = "default";
04002    }
04003    status = ast_extension_state(NULL, context, exten);
04004    ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
04005    astman_start_ack(s, m);
04006    astman_append(s,   "Message: Extension Status\r\n"
04007             "Exten: %s\r\n"
04008             "Context: %s\r\n"
04009             "Hint: %s\r\n"
04010             "Status: %d\r\n\r\n",
04011             exten, context, hint, status);
04012    return 0;
04013 }

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

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

02355 {
02356    struct ast_config *cfg;
02357    const char *fn = astman_get_header(m, "Filename");
02358    const char *category = astman_get_header(m, "Category");
02359    int catcount = 0;
02360    int lineno = 0;
02361    char *cur_category = NULL;
02362    struct ast_variable *v;
02363    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02364 
02365    if (ast_strlen_zero(fn)) {
02366       astman_send_error(s, m, "Filename not specified");
02367       return 0;
02368    }
02369    cfg = ast_config_load2(fn, "manager", config_flags);
02370    if (cfg == CONFIG_STATUS_FILEMISSING) {
02371       astman_send_error(s, m, "Config file not found");
02372       return 0;
02373    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02374       astman_send_error(s, m, "Config file has invalid format");
02375       return 0;
02376    }
02377 
02378    astman_start_ack(s, m);
02379    while ((cur_category = ast_category_browse(cfg, cur_category))) {
02380       if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) {
02381          lineno = 0;
02382          astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category);
02383          for (v = ast_variable_browse(cfg, cur_category); v; v = v->next) {
02384             astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value);
02385          }
02386          catcount++;
02387       }
02388    }
02389    if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
02390       astman_append(s, "No categories found\r\n");
02391    }
02392    ast_config_destroy(cfg);
02393    astman_append(s, "\r\n");
02394 
02395    return 0;
02396 }

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

Definition at line 2446 of file manager.c.

References ast_category_browse(), 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, json_escape(), ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by __init_manager().

02447 {
02448    struct ast_config *cfg;
02449    const char *fn = astman_get_header(m, "Filename");
02450    char *category = NULL;
02451    struct ast_variable *v;
02452    int comma1 = 0;
02453    char *buf = NULL;
02454    unsigned int buf_len = 0;
02455    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02456 
02457    if (ast_strlen_zero(fn)) {
02458       astman_send_error(s, m, "Filename not specified");
02459       return 0;
02460    }
02461 
02462    if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
02463       astman_send_error(s, m, "Config file not found");
02464       return 0;
02465    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02466       astman_send_error(s, m, "Config file has invalid format");
02467       return 0;
02468    }
02469 
02470    buf_len = 512;
02471    buf = alloca(buf_len);
02472 
02473    astman_start_ack(s, m);
02474    astman_append(s, "JSON: {");
02475    while ((category = ast_category_browse(cfg, category))) {
02476       int comma2 = 0;
02477       if (buf_len < 2 * strlen(category) + 1) {
02478          buf_len *= 2;
02479          buf = alloca(buf_len);
02480       }
02481       json_escape(buf, category);
02482       astman_append(s, "%s\"%s\":[", comma1 ? "," : "", buf);
02483       if (!comma1) {
02484          comma1 = 1;
02485       }
02486       for (v = ast_variable_browse(cfg, category); v; v = v->next) {
02487          if (comma2) {
02488             astman_append(s, ",");
02489          }
02490          if (buf_len < 2 * strlen(v->name) + 1) {
02491             buf_len *= 2;
02492             buf = alloca(buf_len);
02493          }
02494          json_escape(buf, v->name);
02495          astman_append(s, "\"%s", buf);
02496          if (buf_len < 2 * strlen(v->value) + 1) {
02497             buf_len *= 2;
02498             buf = alloca(buf_len);
02499          }
02500          json_escape(buf, v->value);
02501          astman_append(s, "%s\"", buf);
02502          if (!comma2) {
02503             comma2 = 1;
02504          }
02505       }
02506       astman_append(s, "]");
02507    }
02508    astman_append(s, "}\r\n\r\n");
02509 
02510    ast_config_destroy(cfg);
02511 
02512    return 0;
02513 }

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

Definition at line 3042 of file manager.c.

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

03043 {
03044    struct ast_channel *c = NULL;
03045    const char *name = astman_get_header(m, "Channel");
03046    const char *varname = astman_get_header(m, "Variable");
03047    char *varval;
03048    char workspace[1024] = "";
03049 
03050    if (ast_strlen_zero(varname)) {
03051       astman_send_error(s, m, "No variable specified");
03052       return 0;
03053    }
03054 
03055    if (!ast_strlen_zero(name)) {
03056       if (!(c = ast_channel_get_by_name(name))) {
03057          astman_send_error(s, m, "No such channel");
03058          return 0;
03059       }
03060    }
03061 
03062    if (varname[strlen(varname) - 1] == ')') {
03063       if (!c) {
03064          c = ast_dummy_channel_alloc();
03065          if (c) {
03066             ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
03067             c = ast_channel_release(c);
03068          } else
03069             ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03070       } else {
03071          ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
03072       }
03073       varval = workspace;
03074    } else {
03075       pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
03076    }
03077 
03078    if (c) {
03079       c = ast_channel_unref(c);
03080    }
03081 
03082    astman_start_ack(s, m);
03083    astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, S_OR(varval, ""));
03084 
03085    return 0;
03086 }

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

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

02967 {
02968    struct ast_channel *c = NULL;
02969    int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */
02970    const char *name = astman_get_header(m, "Channel");
02971    const char *cause = astman_get_header(m, "Cause");
02972 
02973    if (ast_strlen_zero(name)) {
02974       astman_send_error(s, m, "No channel specified");
02975       return 0;
02976    }
02977 
02978    if (!ast_strlen_zero(cause)) {
02979       char *endptr;
02980       causecode = strtol(cause, &endptr, 10);
02981       if (causecode < 0 || causecode > 127 || *endptr != '\0') {
02982          ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause);
02983          /* keep going, better to hangup without cause than to not hang up at all */
02984          causecode = 0; /* do not set channel's hangupcause */
02985       }
02986    }
02987 
02988    if (!(c = ast_channel_get_by_name(name))) {
02989       astman_send_error(s, m, "No such channel");
02990       return 0;
02991    }
02992 
02993    ast_channel_lock(c);
02994    if (causecode > 0) {
02995       ast_debug(1, "Setting hangupcause of channel %s to %d (is %d now)\n",
02996             c->name, causecode, c->hangupcause);
02997       c->hangupcause = causecode;
02998    }
02999    ast_softhangup_nolock(c, AST_SOFTHANGUP_EXPLICIT);
03000    ast_channel_unlock(c);
03001 
03002    c = ast_channel_unref(c);
03003 
03004    astman_send_ack(s, m, "Channel Hungup");
03005 
03006    return 0;
03007 }

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

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

02399 {
02400    struct ast_config *cfg;
02401    const char *fn = astman_get_header(m, "Filename");
02402    char *category = NULL;
02403    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02404    int catcount = 0;
02405 
02406    if (ast_strlen_zero(fn)) {
02407       astman_send_error(s, m, "Filename not specified");
02408       return 0;
02409    }
02410    if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
02411       astman_send_error(s, m, "Config file not found");
02412       return 0;
02413    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02414       astman_send_error(s, m, "Config file has invalid format");
02415       return 0;
02416    }
02417    astman_start_ack(s, m);
02418    while ((category = ast_category_browse(cfg, category))) {
02419       astman_append(s, "Category-%06d: %s\r\n", catcount, category);
02420       catcount++;
02421    }
02422    if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
02423       astman_append(s, "Error: no categories found\r\n");
02424    }
02425    ast_config_destroy(cfg);
02426    astman_append(s, "\r\n");
02427 
02428    return 0;
02429 }

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

Note:
The actionlock is read-locked by the caller of this function

Definition at line 2864 of file manager.c.

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

Referenced by __init_manager().

02865 {
02866    struct manager_action *cur;
02867    struct ast_str *temp = ast_str_alloca(BUFSIZ); /* XXX very large ? */
02868 
02869    astman_start_ack(s, m);
02870    AST_RWLIST_TRAVERSE(&actions, cur, list) {
02871       if (s->session->writeperm & cur->authority || cur->authority == 0) {
02872          astman_append(s, "%s: %s (Priv: %s)\r\n",
02873             cur->action, cur->synopsis, authority_to_str(cur->authority, &temp));
02874       }
02875    }
02876    astman_append(s, "\r\n");
02877 
02878    return 0;
02879 }

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

Definition at line 2923 of file manager.c.

References ast_inet_ntoa(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, ast_test_flag, ast_verb, astman_send_ack(), astman_send_error(), authenticate(), mansession_session::authenticated, EVENT_FLAG_SYSTEM, manager_displayconnects(), manager_event, mansession_session::managerid, mansession::session, mansession_session::sin, and mansession_session::username.

Referenced by __init_manager().

02924 {
02925 
02926    /* still authenticated - don't process again */
02927    if (s->session->authenticated) {
02928       astman_send_ack(s, m, "Already authenticated");
02929       return 0;
02930    }
02931 
02932    if (authenticate(s, m)) {
02933       sleep(1);
02934       astman_send_error(s, m, "Authentication failed");
02935       return -1;
02936    }
02937    s->session->authenticated = 1;
02938    if (manager_displayconnects(s->session)) {
02939       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));
02940    }
02941    astman_send_ack(s, m, "Authentication accepted");
02942    if (ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
02943       manager_event(EVENT_FLAG_SYSTEM, "FullyBooted", "Status: Fully Booted\r\n");
02944    }
02945    return 0;
02946 }

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

Definition at line 2917 of file manager.c.

References astman_send_response().

Referenced by __init_manager().

02918 {
02919    astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
02920    return -1;
02921 }

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

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

03970 {
03971    const char *mailbox = astman_get_header(m, "Mailbox");
03972    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;;
03973 
03974    if (ast_strlen_zero(mailbox)) {
03975       astman_send_error(s, m, "Mailbox not specified");
03976       return 0;
03977    }
03978    ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs);
03979    astman_start_ack(s, m);
03980    astman_append(s,   "Message: Mailbox Message Count\r\n"
03981             "Mailbox: %s\r\n"
03982             "UrgMessages: %d\r\n"
03983             "NewMessages: %d\r\n"
03984             "OldMessages: %d\r\n"
03985             "\r\n",
03986             mailbox, urgentmsgs, newmsgs, oldmsgs);
03987    return 0;
03988 }

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

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

03953 {
03954    const char *mailbox = astman_get_header(m, "Mailbox");
03955    int ret;
03956 
03957    if (ast_strlen_zero(mailbox)) {
03958       astman_send_error(s, m, "Mailbox not specified");
03959       return 0;
03960    }
03961    ret = ast_app_has_voicemail(mailbox, NULL);
03962    astman_start_ack(s, m);
03963    astman_append(s, "Message: Mailbox Status\r\n"
03964           "Mailbox: %s\r\n"
03965           "Waiting: %d\r\n\r\n", mailbox, ret);
03966    return 0;
03967 }

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

Definition at line 3817 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_strlen_zero(), ast_true(), ast_variables_destroy(), astman_get_header(), astman_get_variables(), astman_send_ack(), astman_send_error(), context, ast_frame::data, EVENT_FLAG_SYSTEM, exten, fast_originate(), format, name, mansession::session, strcasestr(), and mansession_session::writeperm.

Referenced by __init_manager().

03818 {
03819    const char *name = astman_get_header(m, "Channel");
03820    const char *exten = astman_get_header(m, "Exten");
03821    const char *context = astman_get_header(m, "Context");
03822    const char *priority = astman_get_header(m, "Priority");
03823    const char *timeout = astman_get_header(m, "Timeout");
03824    const char *callerid = astman_get_header(m, "CallerID");
03825    const char *account = astman_get_header(m, "Account");
03826    const char *app = astman_get_header(m, "Application");
03827    const char *appdata = astman_get_header(m, "Data");
03828    const char *async = astman_get_header(m, "Async");
03829    const char *id = astman_get_header(m, "ActionID");
03830    const char *codecs = astman_get_header(m, "Codecs");
03831    struct ast_variable *vars;
03832    char *tech, *data;
03833    char *l = NULL, *n = NULL;
03834    int pi = 0;
03835    int res;
03836    int to = 30000;
03837    int reason = 0;
03838    char tmp[256];
03839    char tmp2[256];
03840    format_t format = AST_FORMAT_SLINEAR;
03841 
03842    pthread_t th;
03843    if (ast_strlen_zero(name)) {
03844       astman_send_error(s, m, "Channel not specified");
03845       return 0;
03846    }
03847    if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) {
03848       if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
03849          astman_send_error(s, m, "Invalid priority");
03850          return 0;
03851       }
03852    }
03853    if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) {
03854       astman_send_error(s, m, "Invalid timeout");
03855       return 0;
03856    }
03857    ast_copy_string(tmp, name, sizeof(tmp));
03858    tech = tmp;
03859    data = strchr(tmp, '/');
03860    if (!data) {
03861       astman_send_error(s, m, "Invalid channel");
03862       return 0;
03863    }
03864    *data++ = '\0';
03865    ast_copy_string(tmp2, callerid, sizeof(tmp2));
03866    ast_callerid_parse(tmp2, &n, &l);
03867    if (n) {
03868       if (ast_strlen_zero(n)) {
03869          n = NULL;
03870       }
03871    }
03872    if (l) {
03873       ast_shrink_phone_number(l);
03874       if (ast_strlen_zero(l)) {
03875          l = NULL;
03876       }
03877    }
03878    if (!ast_strlen_zero(codecs)) {
03879       format = 0;
03880       ast_parse_allow_disallow(NULL, &format, codecs, 1);
03881    }
03882    /* Allocate requested channel variables */
03883    vars = astman_get_variables(m);
03884 
03885    if (ast_true(async)) {
03886       struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast));
03887       if (!fast) {
03888          res = -1;
03889       } else {
03890          if (!ast_strlen_zero(id))
03891             snprintf(fast->idtext, sizeof(fast->idtext), "ActionID: %s", id);
03892          ast_copy_string(fast->tech, tech, sizeof(fast->tech));
03893          ast_copy_string(fast->data, data, sizeof(fast->data));
03894          ast_copy_string(fast->app, app, sizeof(fast->app));
03895          ast_copy_string(fast->appdata, appdata, sizeof(fast->appdata));
03896          if (l) {
03897             ast_copy_string(fast->cid_num, l, sizeof(fast->cid_num));
03898          }
03899          if (n) {
03900             ast_copy_string(fast->cid_name, n, sizeof(fast->cid_name));
03901          }
03902          fast->vars = vars;
03903          ast_copy_string(fast->context, context, sizeof(fast->context));
03904          ast_copy_string(fast->exten, exten, sizeof(fast->exten));
03905          ast_copy_string(fast->account, account, sizeof(fast->account));
03906          fast->format = format;
03907          fast->timeout = to;
03908          fast->priority = pi;
03909          if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) {
03910             ast_free(fast);
03911             res = -1;
03912          } else {
03913             res = 0;
03914          }
03915       }
03916    } else if (!ast_strlen_zero(app)) {
03917       /* To run the System application (or anything else that goes to shell), you must have the additional System privilege */
03918       if (!(s->session->writeperm & EVENT_FLAG_SYSTEM)
03919          && (
03920             strcasestr(app, "system") ||      /* System(rm -rf /)
03921                                                  TrySystem(rm -rf /)       */
03922             strcasestr(app, "exec") ||        /* Exec(System(rm -rf /))
03923                                                  TryExec(System(rm -rf /)) */
03924             strcasestr(app, "agi") ||         /* AGI(/bin/rm,-rf /)
03925                                                  EAGI(/bin/rm,-rf /)       */
03926             strstr(appdata, "SHELL") ||       /* NoOp(${SHELL(rm -rf /)})  */
03927             strstr(appdata, "EVAL")           /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
03928             )) {
03929          astman_send_error(s, m, "Originate with certain 'Application' arguments requires the additional System privilege, which you do not have.");
03930          return 0;
03931       }
03932       res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
03933    } else {
03934       if (exten && context && pi) {
03935          res = ast_pbx_outgoing_exten(tech, format, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
03936       } else {
03937          astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
03938          if (vars) {
03939             ast_variables_destroy(vars);
03940          }
03941          return 0;
03942       }
03943    }
03944    if (!res) {
03945       astman_send_ack(s, m, "Originate successfully queued");
03946    } else {
03947       astman_send_error(s, m, "Originate failed");
03948    }
03949    return 0;
03950 }

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

Definition at line 2336 of file manager.c.

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

Referenced by __init_manager().

02337 {
02338    const char *actionid = astman_get_header(m, "ActionID");
02339    struct timeval now = ast_tvnow();
02340 
02341    astman_append(s, "Response: Success\r\n");
02342    if (!ast_strlen_zero(actionid)){
02343       astman_append(s, "ActionID: %s\r\n", actionid);
02344    }
02345    astman_append(
02346       s,
02347       "Ping: Pong\r\n"
02348       "Timestamp: %ld.%06lu\r\n"
02349       "\r\n",
02350       (long) now.tv_sec, (unsigned long) now.tv_usec);
02351    return 0;
02352 }

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

action_redirect: The redirect manager command

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

03277 {
03278    const char *name = astman_get_header(m, "Channel");
03279    const char *name2 = astman_get_header(m, "ExtraChannel");
03280    const char *exten = astman_get_header(m, "Exten");
03281    const char *exten2 = astman_get_header(m, "ExtraExten");
03282    const char *context = astman_get_header(m, "Context");
03283    const char *context2 = astman_get_header(m, "ExtraContext");
03284    const char *priority = astman_get_header(m, "Priority");
03285    const char *priority2 = astman_get_header(m, "ExtraPriority");
03286    struct ast_channel *chan, *chan2 = NULL;
03287    int pi, pi2 = 0;
03288    int res;
03289 
03290    if (ast_strlen_zero(name)) {
03291       astman_send_error(s, m, "Channel not specified");
03292       return 0;
03293    }
03294 
03295    if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) {
03296       if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
03297          astman_send_error(s, m, "Invalid priority");
03298          return 0;
03299       }
03300    }
03301 
03302    if (!ast_strlen_zero(priority2) && (sscanf(priority2, "%30d", &pi2) != 1)) {
03303       if ((pi2 = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL)) < 1) {
03304          astman_send_error(s, m, "Invalid ExtraPriority");
03305          return 0;
03306       }
03307    }
03308 
03309    if (!(chan = ast_channel_get_by_name(name))) {
03310       char buf[256];
03311       snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
03312       astman_send_error(s, m, buf);
03313       return 0;
03314    }
03315 
03316    if (ast_check_hangup_locked(chan)) {
03317       astman_send_error(s, m, "Redirect failed, channel not up.");
03318       chan = ast_channel_unref(chan);
03319       return 0;
03320    }
03321 
03322    if (!ast_strlen_zero(name2)) {
03323       chan2 = ast_channel_get_by_name(name2);
03324    }
03325 
03326    if (chan2 && ast_check_hangup_locked(chan2)) {
03327       astman_send_error(s, m, "Redirect failed, extra channel not up.");
03328       chan = ast_channel_unref(chan);
03329       chan2 = ast_channel_unref(chan2);
03330       return 0;
03331    }
03332 
03333    if (chan->pbx) {
03334       ast_channel_lock(chan);
03335       ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
03336       ast_channel_unlock(chan);
03337    }
03338 
03339    res = ast_async_goto(chan, context, exten, pi);
03340    if (!res) {
03341       if (!ast_strlen_zero(name2)) {
03342          if (chan2) {
03343             if (chan2->pbx) {
03344                ast_channel_lock(chan2);
03345                ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
03346                ast_channel_unlock(chan2);
03347             }
03348             if (context2) {
03349                res = ast_async_goto(chan2, context2, exten2, pi2);
03350             } else {
03351                res = ast_async_goto(chan2, context, exten, pi);
03352             }
03353          } else {
03354             res = -1;
03355          }
03356          if (!res) {
03357             astman_send_ack(s, m, "Dual Redirect successful");
03358          } else {
03359             astman_send_error(s, m, "Secondary redirect failed");
03360          }
03361       } else {
03362          astman_send_ack(s, m, "Redirect successful");
03363       }
03364    } else {
03365       astman_send_error(s, m, "Redirect failed");
03366    }
03367 
03368    if (chan) {
03369       chan = ast_channel_unref(chan);
03370    }
03371 
03372    if (chan2) {
03373       chan2 = ast_channel_unref(chan2);
03374    }
03375 
03376    return 0;
03377 }

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

Send a reload event.

Definition at line 4233 of file manager.c.

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

Referenced by __init_manager().

04234 {
04235    const char *module = astman_get_header(m, "Module");
04236    int res = ast_module_reload(S_OR(module, NULL));
04237 
04238    if (res == 2) {
04239       astman_send_ack(s, m, "Module Reloaded");
04240    } else {
04241       astman_send_error(s, m, s == 0 ? "No such module" : "Module does not support reload");
04242    }
04243    return 0;
04244 }

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

Definition at line 3239 of file manager.c.

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

Referenced by __init_manager().

03240 {
03241    struct ast_channel *c = NULL;
03242    const char *name = astman_get_header(m, "Channel");
03243    const char *textmsg = astman_get_header(m, "Message");
03244    int res = 0;
03245 
03246    if (ast_strlen_zero(name)) {
03247       astman_send_error(s, m, "No channel specified");
03248       return 0;
03249    }
03250 
03251    if (ast_strlen_zero(textmsg)) {
03252       astman_send_error(s, m, "No Message specified");
03253       return 0;
03254    }
03255 
03256    if (!(c = ast_channel_get_by_name(name))) {
03257       astman_send_error(s, m, "No such channel");
03258       return 0;
03259    }
03260 
03261    ast_channel_lock(c);
03262    res = ast_sendtext(c, textmsg);
03263    ast_channel_unlock(c);
03264    c = ast_channel_unref(c);
03265 
03266    if (res > 0) {
03267       astman_send_ack(s, m, "Success");
03268    } else {
03269       astman_send_error(s, m, "Failure");
03270    }
03271 
03272    return res;
03273 }

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

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

03010 {
03011    struct ast_channel *c = NULL;
03012    const char *name = astman_get_header(m, "Channel");
03013    const char *varname = astman_get_header(m, "Variable");
03014    const char *varval = astman_get_header(m, "Value");
03015    int res = 0;
03016    
03017    if (ast_strlen_zero(varname)) {
03018       astman_send_error(s, m, "No variable specified");
03019       return 0;
03020    }
03021 
03022    if (!ast_strlen_zero(name)) {
03023       if (!(c = ast_channel_get_by_name(name))) {
03024          astman_send_error(s, m, "No such channel");
03025          return 0;
03026       }
03027    }
03028 
03029    res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
03030 
03031    if (c) {
03032       c = ast_channel_unref(c);
03033    }
03034    if (res == 0) {
03035       astman_send_ack(s, m, "Variable Set"); 
03036    } else {
03037       astman_send_error(s, m, "Variable not set");
03038    }
03039    return 0;
03040 }

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

Manager "status" command to show channels.

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

03091 {
03092    const char *name = astman_get_header(m, "Channel");
03093    const char *cvariables = astman_get_header(m, "Variables");
03094    char *variables = ast_strdupa(S_OR(cvariables, ""));
03095    struct ast_channel *c;
03096    char bridge[256];
03097    struct timeval now = ast_tvnow();
03098    long elapsed_seconds = 0;
03099    int channels = 0;
03100    int all = ast_strlen_zero(name); /* set if we want all channels */
03101    const char *id = astman_get_header(m, "ActionID");
03102    char idText[256];
03103    AST_DECLARE_APP_ARGS(vars,
03104       AST_APP_ARG(name)[100];
03105    );
03106    struct ast_str *str = ast_str_create(1000);
03107    struct ast_channel_iterator *iter = NULL;
03108 
03109    if (!ast_strlen_zero(id)) {
03110       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
03111    } else {
03112       idText[0] = '\0';
03113    }
03114 
03115    if (all) {
03116       if (!(iter = ast_channel_iterator_all_new())) {
03117          ast_free(str);
03118          astman_send_error(s, m, "Memory Allocation Failure");
03119          return 1;
03120       }
03121       c = ast_channel_iterator_next(iter);
03122    } else {
03123       if (!(c = ast_channel_get_by_name(name))) {
03124          astman_send_error(s, m, "No such channel");
03125          ast_free(str);
03126          return 0;
03127       }
03128    }
03129 
03130    astman_send_ack(s, m, "Channel status will follow");
03131 
03132    if (!ast_strlen_zero(cvariables)) {
03133       AST_STANDARD_APP_ARGS(vars, variables);
03134    }
03135 
03136    /* if we look by name, we break after the first iteration */
03137    for (; c; c = ast_channel_iterator_next(iter)) {
03138       ast_channel_lock(c);
03139 
03140       if (!ast_strlen_zero(cvariables)) {
03141          int i;
03142          ast_str_reset(str);
03143          for (i = 0; i < vars.argc; i++) {
03144             char valbuf[512], *ret = NULL;
03145 
03146             if (vars.name[i][strlen(vars.name[i]) - 1] == ')') {
03147                if (ast_func_read(c, vars.name[i], valbuf, sizeof(valbuf)) < 0) {
03148                   valbuf[0] = '\0';
03149                }
03150                ret = valbuf;
03151             } else {
03152                pbx_retrieve_variable(c, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL);
03153             }
03154 
03155             ast_str_append(&str, 0, "Variable: %s=%s\r\n", vars.name[i], ret);
03156          }
03157       }
03158 
03159       channels++;
03160       if (c->_bridge) {
03161          snprintf(bridge, sizeof(bridge), "BridgedChannel: %s\r\nBridgedUniqueid: %s\r\n", c->_bridge->name, c->_bridge->uniqueid);
03162       } else {
03163          bridge[0] = '\0';
03164       }
03165       if (c->pbx) {
03166          if (c->cdr) {
03167             elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
03168          }
03169          astman_append(s,
03170          "Event: Status\r\n"
03171          "Privilege: Call\r\n"
03172          "Channel: %s\r\n"
03173          "CallerIDNum: %s\r\n"
03174          "CallerIDName: %s\r\n"
03175          "Accountcode: %s\r\n"
03176          "ChannelState: %d\r\n"
03177          "ChannelStateDesc: %s\r\n"
03178          "Context: %s\r\n"
03179          "Extension: %s\r\n"
03180          "Priority: %d\r\n"
03181          "Seconds: %ld\r\n"
03182          "%s"
03183          "Uniqueid: %s\r\n"
03184          "%s"
03185          "%s"
03186          "\r\n",
03187          c->name,
03188          S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""),
03189          S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""),
03190          c->accountcode,
03191          c->_state,
03192          ast_state2str(c->_state), c->context,
03193          c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, ast_str_buffer(str), idText);
03194       } else {
03195          astman_append(s,
03196             "Event: Status\r\n"
03197             "Privilege: Call\r\n"
03198             "Channel: %s\r\n"
03199             "CallerIDNum: %s\r\n"
03200             "CallerIDName: %s\r\n"
03201             "Account: %s\r\n"
03202             "State: %s\r\n"
03203             "%s"
03204             "Uniqueid: %s\r\n"
03205             "%s"
03206             "%s"
03207             "\r\n",
03208             c->name,
03209             S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"),
03210             S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"),
03211             c->accountcode,
03212             ast_state2str(c->_state), bridge, c->uniqueid,
03213             ast_str_buffer(str), idText);
03214       }
03215 
03216       ast_channel_unlock(c);
03217       c = ast_channel_unref(c);
03218 
03219       if (!all) {
03220          break;
03221       }
03222    }
03223 
03224    if (iter) {
03225       ast_channel_iterator_destroy(iter);
03226    }
03227 
03228    astman_append(s,
03229       "Event: StatusComplete\r\n"
03230       "%s"
03231       "Items: %d\r\n"
03232       "\r\n", idText, channels);
03233 
03234    ast_free(str);
03235 
03236    return 0;
03237 }

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

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

04016 {
04017    struct ast_channel *c;
04018    const char *name = astman_get_header(m, "Channel");
04019    double timeout = atof(astman_get_header(m, "Timeout"));
04020    struct timeval when = { timeout, 0 };
04021 
04022    if (ast_strlen_zero(name)) {
04023       astman_send_error(s, m, "No channel specified");
04024       return 0;
04025    }
04026 
04027    if (!timeout || timeout < 0) {
04028       astman_send_error(s, m, "No timeout specified");
04029       return 0;
04030    }
04031 
04032    if (!(c = ast_channel_get_by_name(name))) {
04033       astman_send_error(s, m, "No such channel");
04034       return 0;
04035    }
04036 
04037    when.tv_usec = (timeout - when.tv_sec) * 1000000.0;
04038 
04039    ast_channel_lock(c);
04040    ast_channel_setwhentohangup_tv(c, when);
04041    ast_channel_unlock(c);
04042    c = ast_channel_unref(c);
04043 
04044    astman_send_ack(s, m, "Timeout Set");
04045 
04046    return 0;
04047 }

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

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

02662 {
02663    struct ast_config *cfg;
02664    const char *sfn = astman_get_header(m, "SrcFilename");
02665    const char *dfn = astman_get_header(m, "DstFilename");
02666    int res;
02667    const char *rld = astman_get_header(m, "Reload");
02668    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02669    enum error_type result;
02670 
02671    if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) {
02672       astman_send_error(s, m, "Filename not specified");
02673       return 0;
02674    }
02675    if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) {
02676       astman_send_error(s, m, "Config file not found");
02677       return 0;
02678    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02679       astman_send_error(s, m, "Config file has invalid format");
02680       return 0;
02681    }
02682    result = handle_updates(s, m, cfg, dfn);
02683    if (!result) {
02684       ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */
02685       res = ast_config_text_file_save(dfn, cfg, "Manager");
02686       ast_config_destroy(cfg);
02687       if (res) {
02688          astman_send_error(s, m, "Save of config failed");
02689          return 0;
02690       }
02691       astman_send_ack(s, m, NULL);
02692       if (!ast_strlen_zero(rld)) {
02693          if (ast_true(rld)) {
02694             rld = NULL;
02695          }
02696          ast_module_reload(rld);
02697       }
02698    } else {
02699       ast_config_destroy(cfg);
02700       switch(result) {
02701       case UNKNOWN_ACTION:
02702          astman_send_error(s, m, "Unknown action command");
02703          break;
02704       case UNKNOWN_CATEGORY:
02705          astman_send_error(s, m, "Given category does not exist");
02706          break;
02707       case UNSPECIFIED_CATEGORY:
02708          astman_send_error(s, m, "Category not specified");
02709          break;
02710       case UNSPECIFIED_ARGUMENT:
02711          astman_send_error(s, m, "Problem with category, value, or line (if required)");
02712          break;
02713       case FAILURE_ALLOCATION:
02714          astman_send_error(s, m, "Memory allocation failure, this should not happen");
02715          break;
02716       case FAILURE_NEWCAT:
02717          astman_send_error(s, m, "Create category did not complete successfully");
02718          break;
02719       case FAILURE_DELCAT:
02720          astman_send_error(s, m, "Delete category did not complete successfully");
02721          break;
02722       case FAILURE_EMPTYCAT:
02723          astman_send_error(s, m, "Empty category did not complete successfully");
02724          break;
02725       case FAILURE_UPDATE:
02726          astman_send_error(s, m, "Update did not complete successfully");
02727          break;
02728       case FAILURE_DELETE:
02729          astman_send_error(s, m, "Delete did not complete successfully");
02730          break;
02731       case FAILURE_APPEND:
02732          astman_send_error(s, m, "Append did not complete successfully");
02733          break;
02734       }
02735    }
02736    return 0;
02737 }

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

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

04132 {
04133    const char *event = astman_get_header(m, "UserEvent");
04134    struct ast_str *body = ast_str_thread_get(&userevent_buf, 16);
04135    int x;
04136 
04137    ast_str_reset(body);
04138 
04139    for (x = 0; x < m->hdrcount; x++) {
04140       if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) {
04141          ast_str_append(&body, 0, "%s\r\n", m->headers[x]);
04142       }
04143    }
04144 
04145    astman_send_ack(s, m, "Event Sent");   
04146    manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, ast_str_buffer(body));
04147    return 0;
04148 }

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

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

02758 {
02759    const char *timeouts = astman_get_header(m, "Timeout");
02760    int timeout = -1;
02761    int x;
02762    int needexit = 0;
02763    const char *id = astman_get_header(m, "ActionID");
02764    char idText[256];
02765 
02766    if (!ast_strlen_zero(id)) {
02767       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
02768    } else {
02769       idText[0] = '\0';
02770    }
02771 
02772    if (!ast_strlen_zero(timeouts)) {
02773       sscanf(timeouts, "%30i", &timeout);
02774       if (timeout < -1) {
02775          timeout = -1;
02776       }
02777       /* XXX maybe put an upper bound, or prevent the use of 0 ? */
02778    }
02779 
02780    ao2_lock(s->session);
02781    if (s->session->waiting_thread != AST_PTHREADT_NULL) {
02782       pthread_kill(s->session->waiting_thread, SIGURG);
02783    }
02784 
02785    if (s->session->managerid) { /* AMI-over-HTTP session */
02786       /*
02787        * Make sure the timeout is within the expire time of the session,
02788        * as the client will likely abort the request if it does not see
02789        * data coming after some amount of time.
02790        */
02791       time_t now = time(NULL);
02792       int max = s->session->sessiontimeout - now - 10;
02793 
02794       if (max < 0) { /* We are already late. Strange but possible. */
02795          max = 0;
02796       }
02797       if (timeout < 0 || timeout > max) {
02798          timeout = max;
02799       }
02800       if (!s->session->send_events) {  /* make sure we record events */
02801          s->session->send_events = -1;
02802       }
02803    }
02804    ao2_unlock(s->session);
02805 
02806    /* XXX should this go inside the lock ? */
02807    s->session->waiting_thread = pthread_self(); /* let new events wake up this thread */
02808    ast_debug(1, "Starting waiting for an event!\n");
02809 
02810    for (x = 0; x < timeout || timeout < 0; x++) {
02811       ao2_lock(s->session);
02812       if (AST_RWLIST_NEXT(s->session->last_ev, eq_next)) {
02813          needexit = 1;
02814       }
02815       /* We can have multiple HTTP session point to the same mansession entry.
02816        * The way we deal with it is not very nice: newcomers kick out the previous
02817        * HTTP session. XXX this needs to be improved.
02818        */
02819       if (s->session->waiting_thread != pthread_self()) {
02820          needexit = 1;
02821       }
02822       if (s->session->needdestroy) {
02823          needexit = 1;
02824       }
02825       ao2_unlock(s->session);
02826       if (needexit) {
02827          break;
02828       }
02829       if (s->session->managerid == 0) {   /* AMI session */
02830          if (ast_wait_for_input(s->session->fd, 1000)) {
02831             break;
02832          }
02833       } else { /* HTTP session */
02834          sleep(1);
02835       }
02836    }
02837    ast_debug(1, "Finished waiting for an event!\n");
02838 
02839    ao2_lock(s->session);
02840    if (s->session->waiting_thread == pthread_self()) {
02841       struct eventqent *eqe = s->session->last_ev;
02842       astman_send_response(s, m, "Success", "Waiting for Event completed.");
02843       while ((eqe = advance_event(eqe))) {
02844          if (((s->session->readperm & eqe->category) == eqe->category) &&
02845              ((s->session->send_events & eqe->category) == eqe->category)) {
02846             astman_append(s, "%s", eqe->eventdata);
02847          }
02848          s->session->last_ev = eqe;
02849       }
02850       astman_append(s,
02851          "Event: WaitEventComplete\r\n"
02852          "%s"
02853          "\r\n", idText);
02854       s->session->waiting_thread = AST_PTHREADT_NULL;
02855    } else {
02856       ast_debug(1, "Abandoning event request!\n");
02857    }
02858    ao2_unlock(s->session);
02859 
02860    return 0;
02861 }

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

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

01683 {
01684    struct eventqent *next;
01685 
01686    AST_RWLIST_RDLOCK(&all_events);
01687    if ((next = AST_RWLIST_NEXT(e, eq_next))) {
01688       ast_atomic_fetchadd_int(&next->usecount, 1);
01689       ast_atomic_fetchadd_int(&e->usecount, -1);
01690    }
01691    AST_RWLIST_UNLOCK(&all_events);
01692    return next;
01693 }

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

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

03588 {
03589    const char *unitamount;
03590    const char *unittype;
03591    struct ast_str *str = ast_str_alloca(32);
03592 
03593    memset(entry, 0, sizeof(*entry));
03594 
03595    ast_str_set(&str, 0, "UnitAmount(%u)", entry_num);
03596    unitamount = astman_get_header(m, ast_str_buffer(str));
03597 
03598    ast_str_set(&str, 0, "UnitType(%u)", entry_num);
03599    unittype = astman_get_header(m, ast_str_buffer(str));
03600 
03601    if (!ast_strlen_zero(unitamount) && (sscanf(unitamount, "%30u", &entry->amount) == 1)) {
03602       entry->valid_amount = 1;
03603    }
03604 
03605    if (!ast_strlen_zero(unittype) && sscanf(unittype, "%30u", &entry->type) == 1) {
03606       entry->valid_type = 1;
03607    }
03608 
03609    return 0;
03610 }

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

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

04762 {
04763    struct manager_channel_variable *var;
04764    AST_RWLIST_RDLOCK(&channelvars);
04765    AST_LIST_TRAVERSE(&channelvars, var, entry) {
04766       const char *val = "";
04767       if (var->isfunc) {
04768          struct ast_str *res = ast_str_thread_get(&manager_event_funcbuf, 16);
04769          int ret;
04770          if (res && (ret = ast_func_read2(chan, var->name, &res, 0)) == 0) {
04771             val = ast_str_buffer(res);
04772          }
04773       } else {
04774          val = pbx_builtin_getvar_helper(chan, var->name);
04775       }
04776       ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", chan->name, var->name, val ? val : "");
04777    }
04778    AST_RWLIST_UNLOCK(&channelvars);
04779 }

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

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

04736 {
04737    struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str));
04738    static int seq;   /* sequence number */
04739 
04740    if (!tmp) {
04741       return -1;
04742    }
04743 
04744    /* need to init all fields, because ast_malloc() does not */
04745    tmp->usecount = 0;
04746    tmp->category = category;
04747    tmp->seq = ast_atomic_fetchadd_int(&seq, 1);
04748    tmp->tv = ast_tvnow();
04749    AST_RWLIST_NEXT(tmp, eq_next) = NULL;
04750    strcpy(tmp->eventdata, str);
04751 
04752    AST_RWLIST_WRLOCK(&all_events);
04753    AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next);
04754    AST_RWLIST_UNLOCK(&all_events);
04755 
04756    return 0;
04757 }

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

References manager_action::action, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdupa, astman_get_header(), mansession::f, manager_action::func, message::hdrcount, message::headers, mansession::hook, and mansession::session.

01782 {
01783    const char *action;
01784    int ret = 0;
01785    struct manager_action *tmp;
01786    struct mansession s = {.session = NULL, };
01787    struct message m = { 0 };
01788    char header_buf[1025] = { '\0' };
01789    const char *src = msg;
01790    int x = 0;
01791    int curlen;
01792 
01793    if (hook == NULL) {
01794       return -1;
01795    }
01796 
01797    /* convert msg string to message struct */
01798    curlen = strlen(msg);
01799    for (x = 0; x < curlen; x++) {
01800       int cr;  /* set if we have \r */
01801       if (src[x] == '\r' && x+1 < curlen && src[x+1] == '\n')
01802          cr = 2;  /* Found. Update length to include \r\n */
01803       else if (src[x] == '\n')
01804          cr = 1;  /* also accept \n only */
01805       else
01806          continue;
01807       /* don't copy empty lines */
01808       if (x) {
01809          memmove(header_buf, src, x);  /*... but trim \r\n */
01810          header_buf[x] = '\0';      /* terminate the string */
01811          m.headers[m.hdrcount++] = ast_strdupa(header_buf);
01812       }
01813       x += cr;
01814       curlen -= x;      /* remaining size */
01815       src += x;      /* update pointer */
01816       x = -1;        /* reset loop */
01817    }
01818 
01819    action = astman_get_header(&m,"Action");
01820    if (action && strcasecmp(action,"login")) {
01821 
01822       AST_RWLIST_RDLOCK(&actions);
01823       AST_RWLIST_TRAVERSE(&actions, tmp, list) {
01824          if (strcasecmp(action, tmp->action))
01825             continue;
01826          /*
01827          * we have to simulate a session for this action request
01828          * to be able to pass it down for processing
01829          * This is necessary to meet the previous design of manager.c
01830          */
01831          s.hook = hook;
01832          s.f = (void*)1; /* set this to something so our request will make it through all functions that test it*/
01833          ret = tmp->func(&s, &m);
01834          break;
01835       }
01836       AST_RWLIST_UNLOCK(&actions);
01837    }
01838    return ret;
01839 }

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

References eventqent::next.

Referenced by get_perm().

01153 {
01154    const char *val = bigstr, *next;
01155 
01156    do {
01157       if ((next = strchr(val, delim))) {
01158          if (!strncmp(val, smallstr, (next - val))) {
01159             return 1;
01160          } else {
01161             continue;
01162          }
01163       } else {
01164          return !strcmp(smallstr, val);
01165       }
01166    } while (*(val = (next + 1)));
01167 
01168    return 0;
01169 }

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

References manager_action::action, ast_calloc_with_stringfields, ast_free, ast_manager_register_struct(), AST_STATIC_DOC, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), manager_action::authority, manager_action::docsrc, and manager_action::func.

Referenced by load_module().

04944 {
04945    struct manager_action *cur = NULL;
04946 #ifdef AST_XML_DOCS
04947    char *tmpxml;
04948 #endif
04949 
04950    if (!(cur = ast_calloc_with_stringfields(1, struct manager_action, 128))) {
04951       return -1;
04952    }
04953 
04954    cur->action = action;
04955    cur->authority = auth;
04956    cur->func = func;
04957 #ifdef AST_XML_DOCS
04958    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
04959       tmpxml = ast_xmldoc_build_synopsis("manager", action);
04960       ast_string_field_set(cur, synopsis, tmpxml);
04961       ast_free(tmpxml);
04962 
04963       tmpxml = ast_xmldoc_build_syntax("manager", action);
04964       ast_string_field_set(cur, syntax, tmpxml);
04965       ast_free(tmpxml);
04966 
04967       tmpxml = ast_xmldoc_build_description("manager", action);
04968       ast_string_field_set(cur, description, tmpxml);
04969       ast_free(tmpxml);
04970 
04971       tmpxml = ast_xmldoc_build_seealso("manager", action);
04972       ast_string_field_set(cur, seealso, tmpxml);
04973       ast_free(tmpxml);
04974 
04975       tmpxml = ast_xmldoc_build_arguments("manager", action);
04976       ast_string_field_set(cur, arguments, tmpxml);
04977       ast_free(tmpxml);
04978 
04979       cur->docsrc = AST_XML_DOC;
04980    } else {
04981 #endif
04982       ast_string_field_set(cur, synopsis, synopsis);
04983       ast_string_field_set(cur, description, description);
04984 #ifdef AST_XML_DOCS
04985       cur->docsrc = AST_STATIC_DOC;
04986    }
04987 #endif
04988    if (ast_manager_register_struct(cur)) {
04989       ast_free(cur);
04990       return -1;
04991    }
04992 
04993    return 0;
04994 }

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

References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

static int ast_manager_register_struct ( struct manager_action act  )  [static]

Definition at line 4906 of file manager.c.

References manager_action::action, ast_log(), AST_RWLIST_INSERT_AFTER, AST_RWLIST_INSERT_HEAD, AST_RWLIST_TIMEDWRLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_verb, LOG_ERROR, LOG_WARNING, and tv.

Referenced by ast_manager_register2().

04907 {
04908    struct manager_action *cur, *prev = NULL;
04909    struct timespec tv = { 5, };
04910 
04911    if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) {
04912       ast_log(LOG_ERROR, "Could not obtain lock on manager list\n");
04913       return -1;
04914    }
04915    AST_RWLIST_TRAVERSE(&actions, cur, list) {
04916       int ret = strcasecmp(cur->action, act->action);
04917       if (ret == 0) {
04918          ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action);
04919          AST_RWLIST_UNLOCK(&actions);
04920          return -1;
04921       }
04922       if (ret > 0) { /* Insert these alphabetically */
04923          prev = cur;
04924          break;
04925       }
04926    }
04927 
04928    if (prev) {
04929       AST_RWLIST_INSERT_AFTER(&actions, prev, act, list);
04930    } else {
04931       AST_RWLIST_INSERT_HEAD(&actions, act, list);
04932    }
04933 
04934    ast_verb(2, "Manager registered action %s\n", act->action);
04935 
04936    AST_RWLIST_UNLOCK(&actions);
04937 
04938    return 0;
04939 }

int ast_manager_unregister ( char *  action  ) 

Unregister a registered manager command.

Parameters:
action Name of registered Action:

Definition at line 4872 of file manager.c.

References manager_action::action, ast_free, ast_log(), AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TIMEDWRLOCK, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, ast_string_field_free_memory, ast_verb, LOG_ERROR, and tv.

Referenced by __unload_module(), and unload_module().

04873 {
04874    struct manager_action *cur;
04875    struct timespec tv = { 5, };
04876 
04877    if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) {
04878       ast_log(LOG_ERROR, "Could not obtain lock on manager list\n");
04879       return -1;
04880    }
04881    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) {
04882       if (!strcasecmp(action, cur->action)) {
04883          AST_RWLIST_REMOVE_CURRENT(list);
04884          ast_string_field_free_memory(cur);
04885          ast_free(cur);
04886          ast_verb(2, "Manager unregistered action %s\n", action);
04887          break;
04888       }
04889    }
04890    AST_RWLIST_TRAVERSE_SAFE_END;
04891    AST_RWLIST_UNLOCK(&actions);
04892 
04893    return 0;
04894 }

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

01031 {
01032    AST_RWLIST_WRLOCK(&manager_hooks);
01033    AST_RWLIST_REMOVE(&manager_hooks, hook, list);
01034    AST_RWLIST_UNLOCK(&manager_hooks);
01035 }

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

utility functions for creating AMI replies

Definition at line 1885 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_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_ping(), ast_cli_netstats(), 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().

01886 {
01887    va_list ap;
01888    struct ast_str *buf;
01889 
01890    if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
01891       return;
01892    }
01893 
01894    va_start(ap, fmt);
01895    ast_str_set_va(&buf, 0, fmt, ap);
01896    va_end(ap);
01897 
01898    if (s->f != NULL || s->session->f != NULL) {
01899       send_string(s, ast_str_buffer(buf));
01900    } else {
01901       ast_verbose("fd == -1 in astman_append, should not happen\n");
01902    }
01903 }

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

Get header from mananger transaction.

Definition at line 1732 of file manager.c.

References __astman_get_header(), and GET_HEADER_FIRST_MATCH.

Referenced by _sip_show_peer(), _sip_show_peers(), _skinny_show_devices(), _skinny_show_lines(), action_add_agi_cmd(), action_agent_logoff(), action_agents(), action_aocmessage(), action_atxfer(), action_bridge(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdishowchannels(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_originate(), action_ping(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), action_waitevent(), aocmessage_get_unit_entry(), ast_hook_send_action(), astman_send_response_full(), authenticate(), change_monitor_action(), do_pause_or_unpause(), handle_updates(), manager_add_queue_member(), manager_data_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_jabber_send(), manager_list_voicemail_users(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_optimize_away(), manager_park(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_queue_rule_show(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), manager_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().

01733 {
01734    return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH);
01735 }

struct ast_variable* astman_get_variables ( const struct message m  ) 

Get a linked list of the Variable: headers.

Definition at line 1738 of file manager.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_variable_new(), message::hdrcount, message::headers, parse(), strsep(), and var.

Referenced by action_originate(), and manager_sipnotify().

01739 {
01740    int varlen, x, y;
01741    struct ast_variable *head = NULL, *cur;
01742 
01743    AST_DECLARE_APP_ARGS(args,
01744       AST_APP_ARG(vars)[32];
01745    );
01746 
01747    varlen = strlen("Variable: ");
01748 
01749    for (x = 0; x < m->hdrcount; x++) {
01750       char *parse, *var, *val;
01751 
01752       if (strncasecmp("Variable: ", m->headers[x], varlen)) {
01753          continue;
01754       }
01755       parse = ast_strdupa(m->headers[x] + varlen);
01756 
01757       AST_STANDARD_APP_ARGS(args, parse);
01758       if (!args.argc) {
01759          continue;
01760       }
01761       for (y = 0; y < args.argc; y++) {
01762          if (!args.vars[y]) {
01763             continue;
01764          }
01765          var = val = ast_strdupa(args.vars[y]);
01766          strsep(&val, "=");
01767          if (!val || ast_strlen_zero(var)) {
01768             continue;
01769          }
01770          cur = ast_variable_new(var, val, "");
01771          cur->next = head;
01772          head = cur;
01773       }
01774    }
01775 
01776    return head;
01777 }

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

Send ack in manager transaction.

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

01953 {
01954    astman_send_response_full(s, m, "Success", msg, NULL);
01955 }

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

Send error in manager transaction.

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

01948 {
01949    astman_send_response_full(s, m, "Error", error, NULL);
01950 }

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

Send ack in manager list transaction.

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

01963 {
01964    astman_send_response_full(s, m, "Success", msg, listflag);
01965 }

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

Send response in manager transaction.

Definition at line 1942 of file manager.c.

References astman_send_response_full().

Referenced by action_logoff().

01943 {
01944    astman_send_response_full(s, m, resp, msg, NULL);
01945 }

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

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

01923 {
01924    const char *id = astman_get_header(m, "ActionID");
01925 
01926    astman_append(s, "Response: %s\r\n", resp);
01927    if (!ast_strlen_zero(id)) {
01928       astman_append(s, "ActionID: %s\r\n", id);
01929    }
01930    if (listflag) {
01931       astman_append(s, "EventList: %s\r\n", listflag);   /* Start, complete, cancelled */
01932    }
01933    if (msg == MSG_MOREDATA) {
01934       return;
01935    } else if (msg) {
01936       astman_append(s, "Message: %s\r\n\r\n", msg);
01937    } else {
01938       astman_append(s, "\r\n");
01939    }
01940 }

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

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

01958 {
01959    astman_send_response_full(s, m, "Success", MSG_MOREDATA, NULL);
01960 }

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

Definition at line 2239 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.

02240 {
02241    const char *username = astman_get_header(m, "Username");
02242    const char *password = astman_get_header(m, "Secret");
02243    int error = -1;
02244    struct ast_manager_user *user = NULL;
02245    regex_t *regex_filter;
02246    struct ao2_iterator filter_iter;
02247    struct ast_sockaddr addr;
02248 
02249    if (ast_strlen_zero(username)) { /* missing username */
02250       return -1;
02251    }
02252 
02253    /* locate user in locked state */
02254    AST_RWLIST_WRLOCK(&users);
02255 
02256    ast_sockaddr_from_sin(&addr, &s->session->sin);
02257 
02258    if (!(user = get_manager_by_name_locked(username))) {
02259       report_invalid_user(s, username);
02260       ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
02261    } else if (user->ha && !ast_apply_ha(user->ha, &addr)) {
02262       report_failed_acl(s, username);
02263       ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
02264    } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) {
02265       const char *key = astman_get_header(m, "Key");
02266       if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) {
02267          int x;
02268          int len = 0;
02269          char md5key[256] = "";
02270          struct MD5Context md5;
02271          unsigned char digest[16];
02272 
02273          MD5Init(&md5);
02274          MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge));
02275          MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret));
02276          MD5Final(digest, &md5);
02277          for (x = 0; x < 16; x++)
02278             len += sprintf(md5key + len, "%2.2x", digest[x]);
02279          if (!strcmp(md5key, key)) {
02280             error = 0;
02281          } else {
02282             report_failed_challenge_response(s, key, md5key);
02283          }
02284       } else {
02285          ast_debug(1, "MD5 authentication is not possible.  challenge: '%s'\n",
02286             S_OR(s->session->challenge, ""));
02287       }
02288    } else if (user->secret) {
02289       if (!strcmp(password, user->secret)) {
02290          error = 0;
02291       } else {
02292          report_inval_password(s, username);
02293       }
02294    }
02295 
02296    if (error) {
02297       ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
02298       AST_RWLIST_UNLOCK(&users);
02299       return -1;
02300    }
02301 
02302    /* auth complete */
02303 
02304    /* All of the user parameters are copied to the session so that in the event
02305      * of a reload and a configuration change, the session parameters are not
02306      * changed. */
02307    ast_copy_string(s->session->username, username, sizeof(s->session->username));
02308    s->session->readperm = user->readperm;
02309    s->session->writeperm = user->writeperm;
02310    s->session->writetimeout = user->writetimeout;
02311 
02312    filter_iter = ao2_iterator_init(user->whitefilters, 0);
02313    while ((regex_filter = ao2_iterator_next(&filter_iter))) {
02314       ao2_t_link(s->session->whitefilters, regex_filter, "add white user filter to session");
02315       ao2_t_ref(regex_filter, -1, "remove iterator ref");
02316    }
02317    ao2_iterator_destroy(&filter_iter);
02318 
02319    filter_iter = ao2_iterator_init(user->blackfilters, 0);
02320    while ((regex_filter = ao2_iterator_next(&filter_iter))) {
02321       ao2_t_link(s->session->blackfilters, regex_filter, "add black user filter to session");
02322       ao2_t_ref(regex_filter, -1, "remove iterator ref");
02323    }
02324    ao2_iterator_destroy(&filter_iter);
02325 
02326    s->session->sessionstart = time(NULL);
02327    s->session->sessionstart_tv = ast_tvnow();
02328    set_eventmask(s, astman_get_header(m, "Events"));
02329 
02330    report_auth_success(s);
02331 
02332    AST_RWLIST_UNLOCK(&users);
02333    return 0;
02334 }

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

Convert authority code to a list of options.

Definition at line 1128 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(), handle_showmanager(), handle_showmancmd(), and handle_showmancmds().

01129 {
01130    int i;
01131    char *sep = "";
01132 
01133    ast_str_reset(*res);
01134    for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
01135       if (authority & perms[i].num) {
01136          ast_str_append(res, 0, "%s%s", sep, perms[i].label);
01137          sep = ",";
01138       }
01139    }
01140 
01141    if (ast_str_strlen(*res) == 0)   /* replace empty string with something sensible */
01142       ast_str_append(res, 0, "<none>");
01143 
01144    return ast_str_buffer(*res);
01145 }

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

Definition at line 4063 of file manager.c.

References CMP_MATCH, and CMP_STOP.

Referenced by match_filter().

04064 {
04065    regex_t *regex_filter = obj;
04066    const char *eventdata = arg;
04067    int *result = data;
04068 
04069    if (regexec(regex_filter, eventdata, 0, NULL, 0)) {
04070       *result = 1;
04071       return (CMP_MATCH | CMP_STOP);
04072    }
04073 
04074    return 0;
04075 }

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

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

Referenced by session_do().

01270 {
01271    struct mansession_session *newsession;
01272 
01273    if (!(newsession = ao2_alloc(sizeof(*newsession), session_destructor))) {
01274       return NULL;
01275    }
01276 
01277    if (!(newsession->whitefilters = ao2_container_alloc(1, NULL, NULL))) {
01278       ao2_ref(newsession, -1);
01279       return NULL;
01280    }
01281 
01282    if (!(newsession->blackfilters = ao2_container_alloc(1, NULL, NULL))) {
01283       ao2_ref(newsession, -1); /* session_destructor will cleanup the other filter */
01284       return NULL;
01285    }
01286 
01287    newsession->fd = -1;
01288    newsession->waiting_thread = AST_PTHREADT_NULL;
01289    newsession->writetimeout = 100;
01290    newsession->send_events = -1;
01291    newsession->sin = sin;
01292 
01293    ao2_link(sessions, newsession);
01294 
01295    return newsession;
01296 }

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

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

03429 {
03430    char *cmd_copy, *cur_cmd;
03431    char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, };
03432    int i;
03433 
03434    cmd_copy = ast_strdupa(cmd);
03435    for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) {
03436       cur_cmd = ast_strip(cur_cmd);
03437       if (ast_strlen_zero(cur_cmd)) {
03438          i--;
03439          continue;
03440       }
03441 
03442       cmd_words[i] = cur_cmd;
03443    }
03444 
03445    for (i = 0; i < ARRAY_LEN(command_blacklist); i++) {
03446       int j, match = 1;
03447 
03448       for (j = 0; command_blacklist[i].words[j]; j++) {
03449          if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) {
03450             match = 0;
03451             break;
03452          }
03453       }
03454 
03455       if (match) {
03456          return 1;
03457       }
03458    }
03459 
03460    return 0;
03461 }

int check_manager_enabled ( void   ) 

Check if AMI is enabled.

Definition at line 1037 of file manager.c.

Referenced by handle_show_settings().

01038 {
01039    return manager_enabled;
01040 }

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

Definition at line 1312 of file manager.c.

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

Referenced by process_message().

01313 {
01314    struct mansession_session *session = ao2_find(sessions, (char *) name, 0);
01315    int inuse = 0;
01316 
01317    if (session) {
01318       inuse = 1;
01319       unref_mansession(session);
01320    }
01321    return inuse;
01322 }

int check_webmanager_enabled ( void   ) 

Check if AMI/HTTP is enabled.

Definition at line 1042 of file manager.c.

Referenced by action_coresettings(), and handle_show_settings().

01043 {
01044    return (webmanager_enabled && manager_enabled);
01045 }

static int do_message ( struct mansession s  )  [static]

Definition at line 4590 of file manager.c.

References AST_MAX_MANHEADERS, ast_strdupa, ast_strlen_zero(), get_input(), message::hdrcount, message::headers, mansession_session::inbuf, process_events(), process_message(), and mansession::session.

Referenced by session_do().

04591 {
04592    struct message m = { 0 };
04593    char header_buf[sizeof(s->session->inbuf)] = { '\0' };
04594    int res;
04595 
04596    for (;;) {
04597       /* Check if any events are pending and do them if needed */
04598       if (process_events(s)) {
04599          return -1;
04600       }
04601       res = get_input(s, header_buf);
04602       if (res == 0) {
04603          continue;
04604       } else if (res > 0) {
04605          if (ast_strlen_zero(header_buf)) {
04606             return process_message(s, &m) ? -1 : 0;
04607          } else if (m.hdrcount < (AST_MAX_MANHEADERS - 1)) {
04608             m.headers[m.hdrcount++] = ast_strdupa(header_buf);
04609          }
04610       } else {
04611          return res;
04612       }
04613    }
04614 }

static void event_filter_destructor ( void *  obj  )  [static]

Definition at line 1232 of file manager.c.

01233 {
01234    regex_t *regex_filter = obj;
01235    regfree(regex_filter);
01236 }

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

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

03538 {
03539    struct fast_originate_helper *in = data;
03540    int res;
03541    int reason = 0;
03542    struct ast_channel *chan = NULL, *chans[1];
03543    char requested_channel[AST_CHANNEL_NAME];
03544 
03545    if (!ast_strlen_zero(in->app)) {
03546       res = ast_pbx_outgoing_app(in->tech, in->format, in->data, in->timeout, in->app, in->appdata, &reason, 1,
03547          S_OR(in->cid_num, NULL),
03548          S_OR(in->cid_name, NULL),
03549          in->vars, in->account, &chan);
03550    } else {
03551       res = ast_pbx_outgoing_exten(in->tech, in->format, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1,
03552          S_OR(in->cid_num, NULL),
03553          S_OR(in->cid_name, NULL),
03554          in->vars, in->account, &chan);
03555    }
03556 
03557    if (!chan) {
03558       snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);
03559    }
03560    /* Tell the manager what happened with the channel */
03561    chans[0] = chan;
03562    ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans,
03563       "%s%s"
03564       "Response: %s\r\n"
03565       "Channel: %s\r\n"
03566       "Context: %s\r\n"
03567       "Exten: %s\r\n"
03568       "Reason: %d\r\n"
03569       "Uniqueid: %s\r\n"
03570       "CallerIDNum: %s\r\n"
03571       "CallerIDName: %s\r\n",
03572       in->idtext, ast_strlen_zero(in->idtext) ? "" : "\r\n", res ? "Failure" : "Success",
03573       chan ? chan->name : requested_channel, in->context, in->exten, reason,
03574       chan ? chan->uniqueid : "<null>",
03575       S_OR(in->cid_num, "<unknown>"),
03576       S_OR(in->cid_name, "<unknown>")
03577       );
03578 
03579    /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
03580    if (chan) {
03581       ast_channel_unlock(chan);
03582    }
03583    ast_free(in);
03584    return NULL;
03585 }

static void free_channelvars ( void   )  [static]

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

06559 {
06560    struct manager_channel_variable *var;
06561    AST_RWLIST_WRLOCK(&channelvars);
06562    while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) {
06563       ast_free(var);
06564    }
06565    AST_RWLIST_UNLOCK(&channelvars);
06566 }

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

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

04519 {
04520    int res, x;
04521    int maxlen = sizeof(s->session->inbuf) - 1;
04522    char *src = s->session->inbuf;
04523 
04524    /*
04525     * Look for \r\n within the buffer. If found, copy to the output
04526     * buffer and return, trimming the \r\n (not used afterwards).
04527     */
04528    for (x = 0; x < s->session->inlen; x++) {
04529       int cr;  /* set if we have \r */
04530       if (src[x] == '\r' && x+1 < s->session->inlen && src[x + 1] == '\n') {
04531          cr = 2;  /* Found. Update length to include \r\n */
04532       } else if (src[x] == '\n') {
04533          cr = 1;  /* also accept \n only */
04534       } else {
04535          continue;
04536       }
04537       memmove(output, src, x);   /*... but trim \r\n */
04538       output[x] = '\0';    /* terminate the string */
04539       x += cr;       /* number of bytes used */
04540       s->session->inlen -= x;       /* remaining size */
04541       memmove(src, src + x, s->session->inlen); /* remove used bytes */
04542       return 1;
04543    }
04544    if (s->session->inlen >= maxlen) {
04545       /* no crlf found, and buffer full - sorry, too long for us */
04546       ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", ast_inet_ntoa(s->session->sin.sin_addr), src);
04547       s->session->inlen = 0;
04548    }
04549    res = 0;
04550    while (res == 0) {
04551       ao2_lock(s->session);
04552       if (s->session->pending_event) {
04553          s->session->pending_event = 0;
04554          ao2_unlock(s->session);
04555          return 0;
04556       }
04557       s->session->waiting_thread = pthread_self();
04558       ao2_unlock(s->session);
04559 
04560       res = ast_wait_for_input(s->session->fd, -1);   /* return 0 on timeout ? */
04561 
04562       ao2_lock(s->session);
04563       s->session->waiting_thread = AST_PTHREADT_NULL;
04564       ao2_unlock(s->session);
04565    }
04566    if (res < 0) {
04567       /* If we get a signal from some other thread (typically because
04568        * there are new events queued), return 0 to notify the caller.
04569        */
04570       if (errno == EINTR || errno == EAGAIN) {
04571          return 0;
04572       }
04573       ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno));
04574       return -1;
04575    }
04576 
04577    ao2_lock(s->session);
04578    res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f);
04579    if (res < 1) {
04580       res = -1;   /* error return */
04581    } else {
04582       s->session->inlen += res;
04583       src[s->session->inlen] = '\0';
04584       res = 0;
04585    }
04586    ao2_unlock(s->session);
04587    return res;
04588 }

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

References AST_RWLIST_TRAVERSE, ast_manager_user::list, and user.

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

01330 {
01331    struct ast_manager_user *user = NULL;
01332 
01333    AST_RWLIST_TRAVERSE(&users, user, list) {
01334       if (!strcasecmp(user->username, name)) {
01335          break;
01336       }
01337    }
01338 
01339    return user;
01340 }

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

Definition at line 1171 of file manager.c.

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

Referenced by strings_to_mask().

01172 {
01173    int x = 0, ret = 0;
01174 
01175    if (!instr) {
01176       return 0;
01177    }
01178 
01179    for (x = 0; x < ARRAY_LEN(perms); x++) {
01180       if (ast_instring(instr, perms[x].label, ',')) {
01181          ret |= perms[x].num;
01182       }
01183    }
01184 
01185    return ret;
01186 }

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

01052 {
01053    struct eventqent *ret;
01054 
01055    AST_RWLIST_WRLOCK(&all_events);
01056    ret = AST_RWLIST_LAST(&all_events);
01057    /* the list is never empty now, but may become so when
01058     * we optimize it in the future, so be prepared.
01059     */
01060    if (ret) {
01061       ast_atomic_fetchadd_int(&ret->usecount, 1);
01062    }
01063    AST_RWLIST_UNLOCK(&all_events);
01064    return ret;
01065 }

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 1663 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.

01664 {
01665    switch (cmd) {
01666    case CLI_INIT:
01667       e->command = "manager reload";
01668       e->usage =
01669          "Usage: manager reload\n"
01670          "       Reloads the manager configuration.\n";
01671       return NULL;
01672    case CLI_GENERATE:
01673       return NULL;
01674    }
01675    if (a->argc > 2) {
01676       return CLI_SHOWUSAGE;
01677    }
01678    reload_manager();
01679    return CLI_SUCCESS;
01680 }

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

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

01439 {
01440    switch (cmd) {
01441    case CLI_INIT:
01442       e->command = "manager set debug [on|off]";
01443       e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n";
01444       return NULL;
01445    case CLI_GENERATE:
01446       return NULL;
01447    }
01448 
01449    if (a->argc == 3) {
01450       ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off");
01451    } else if (a->argc == 4) {
01452       if (!strcasecmp(a->argv[3], "on")) {
01453          manager_debug = 1;
01454       } else if (!strcasecmp(a->argv[3], "off")) {
01455          manager_debug = 0;
01456       } else {
01457          return CLI_SHOWUSAGE;
01458       }
01459    }
01460    return CLI_SUCCESS;
01461 }

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

Definition at line 1463 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.

01464 {
01465    struct ast_manager_user *user = NULL;
01466    int l, which;
01467    char *ret = NULL;
01468    struct ast_str *rauthority = ast_str_alloca(128);
01469    struct ast_str *wauthority = ast_str_alloca(128);
01470 
01471    switch (cmd) {
01472    case CLI_INIT:
01473       e->command = "manager show user";
01474       e->usage =
01475          " Usage: manager show user <user>\n"
01476          "        Display all information related to the manager user specified.\n";
01477       return NULL;
01478    case CLI_GENERATE:
01479       l = strlen(a->word);
01480       which = 0;
01481       if (a->pos != 3) {
01482          return NULL;
01483       }
01484       AST_RWLIST_RDLOCK(&users);
01485       AST_RWLIST_TRAVERSE(&users, user, list) {
01486          if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) {
01487             ret = ast_strdup(user->username);
01488             break;
01489          }
01490       }
01491       AST_RWLIST_UNLOCK(&users);
01492       return ret;
01493    }
01494 
01495    if (a->argc != 4) {
01496       return CLI_SHOWUSAGE;
01497    }
01498 
01499    AST_RWLIST_RDLOCK(&users);
01500 
01501    if (!(user = get_manager_by_name_locked(a->argv[3]))) {
01502       ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]);
01503       AST_RWLIST_UNLOCK(&users);
01504       return CLI_SUCCESS;
01505    }
01506 
01507    ast_cli(a->fd, "\n");
01508    ast_cli(a->fd,
01509       "       username: %s\n"
01510       "         secret: %s\n"
01511       "            acl: %s\n"
01512       "      read perm: %s\n"
01513       "     write perm: %s\n"
01514       "displayconnects: %s\n",
01515       (user->username ? user->username : "(N/A)"),
01516       (user->secret ? "<Set>" : "(N/A)"),
01517       (user->ha ? "yes" : "no"),
01518       authority_to_str(user->readperm, &rauthority),
01519       authority_to_str(user->writeperm, &wauthority),
01520       (user->displayconnects ? "yes" : "no"));
01521 
01522    AST_RWLIST_UNLOCK(&users);
01523 
01524    return CLI_SUCCESS;
01525 }

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

Definition at line 1527 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.

01528 {
01529    struct ast_manager_user *user = NULL;
01530    int count_amu = 0;
01531    switch (cmd) {
01532    case CLI_INIT:
01533       e->command = "manager show users";
01534       e->usage =
01535          "Usage: manager show users\n"
01536          "       Prints a listing of all managers that are currently configured on that\n"
01537          " system.\n";
01538       return NULL;
01539    case CLI_GENERATE:
01540       return NULL;
01541    }
01542    if (a->argc != 3) {
01543       return CLI_SHOWUSAGE;
01544    }
01545 
01546    AST_RWLIST_RDLOCK(&users);
01547 
01548    /* If there are no users, print out something along those lines */
01549    if (AST_RWLIST_EMPTY(&users)) {
01550       ast_cli(a->fd, "There are no manager users.\n");
01551       AST_RWLIST_UNLOCK(&users);
01552       return CLI_SUCCESS;
01553    }
01554 
01555    ast_cli(a->fd, "\nusername\n--------\n");
01556 
01557    AST_RWLIST_TRAVERSE(&users, user, list) {
01558       ast_cli(a->fd, "%s\n", user->username);
01559       count_amu++;
01560    }
01561 
01562    AST_RWLIST_UNLOCK(&users);
01563 
01564    ast_cli(a->fd,"-------------------\n"
01565             "%d manager users configured.\n", count_amu);
01566    return CLI_SUCCESS;
01567 }

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

Definition at line 1360 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.

01361 {
01362    struct manager_action *cur;
01363    struct ast_str *authority;
01364    int num, l, which;
01365    char *ret = NULL;
01366 #ifdef AST_XML_DOCS
01367    char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64];
01368 #endif
01369 
01370    switch (cmd) {
01371    case CLI_INIT:
01372       e->command = "manager show command";
01373       e->usage =
01374          "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n"
01375          "  Shows the detailed description for a specific Asterisk manager interface command.\n";
01376       return NULL;
01377    case CLI_GENERATE:
01378       l = strlen(a->word);
01379       which = 0;
01380       AST_RWLIST_RDLOCK(&actions);
01381       AST_RWLIST_TRAVERSE(&actions, cur, list) {
01382          if (!strncasecmp(a->word, cur->action, l) && ++which > a->n) {
01383             ret = ast_strdup(cur->action);
01384             break;   /* make sure we exit even if ast_strdup() returns NULL */
01385          }
01386       }
01387       AST_RWLIST_UNLOCK(&actions);
01388       return ret;
01389    }
01390    authority = ast_str_alloca(80);
01391    if (a->argc < 4) {
01392       return CLI_SHOWUSAGE;
01393    }
01394 
01395 #ifdef AST_XML_DOCS
01396    /* setup the titles */
01397    term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
01398    term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40);
01399    term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
01400    term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40);
01401    term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
01402 #endif
01403 
01404    AST_RWLIST_RDLOCK(&actions);
01405    AST_RWLIST_TRAVERSE(&actions, cur, list) {
01406       for (num = 3; num < a->argc; num++) {
01407          if (!strcasecmp(cur->action, a->argv[num])) {
01408 #ifdef AST_XML_DOCS
01409             if (cur->docsrc == AST_XML_DOC) {
01410                ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n",
01411                   syntax_title,
01412                   ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1),
01413                   synopsis_title,
01414                   ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1),
01415                   description_title,
01416                   ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1),
01417                   arguments_title,
01418                   ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1),
01419                   seealso_title,
01420                   ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1));
01421             } else {
01422 #endif
01423                ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
01424                      cur->action, cur->synopsis,
01425                      authority_to_str(cur->authority, &authority),
01426                      S_OR(cur->description, ""));
01427 #ifdef AST_XML_DOCS
01428             }
01429 #endif
01430          }
01431       }
01432    }
01433    AST_RWLIST_UNLOCK(&actions);
01434 
01435    return CLI_SUCCESS;
01436 }

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 1570 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.

01571 {
01572    struct manager_action *cur;
01573    struct ast_str *authority;
01574 #define HSMC_FORMAT "  %-15.15s  %-15.15s  %-55.55s\n"
01575    switch (cmd) {
01576    case CLI_INIT:
01577       e->command = "manager show commands";
01578       e->usage =
01579          "Usage: manager show commands\n"
01580          "  Prints a listing of all the available Asterisk manager interface commands.\n";
01581       return NULL;
01582    case CLI_GENERATE:
01583       return NULL;
01584    }
01585    authority = ast_str_alloca(80);
01586    ast_cli(a->fd, HSMC_FORMAT, "Action", "Privilege", "Synopsis");
01587    ast_cli(a->fd, HSMC_FORMAT, "------", "---------", "--------");
01588 
01589    AST_RWLIST_RDLOCK(&actions);
01590    AST_RWLIST_TRAVERSE(&actions, cur, list)
01591       ast_cli(a->fd, HSMC_FORMAT, cur->action, authority_to_str(cur->authority, &authority), cur->synopsis);
01592    AST_RWLIST_UNLOCK(&actions);
01593 
01594    return CLI_SUCCESS;
01595 }

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 1598 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.

01599 {
01600    struct mansession_session *session;
01601    time_t now = time(NULL);
01602 #define HSMCONN_FORMAT1 "  %-15.15s  %-15.15s  %-10.10s  %-10.10s  %-8.8s  %-8.8s  %-5.5s  %-5.5s\n"
01603 #define HSMCONN_FORMAT2 "  %-15.15s  %-15.15s  %-10d  %-10d  %-8d  %-8d  %-5.5d  %-5.5d\n"
01604    int count = 0;
01605    struct ao2_iterator i;
01606 
01607    switch (cmd) {
01608    case CLI_INIT:
01609       e->command = "manager show connected";
01610       e->usage =
01611          "Usage: manager show connected\n"
01612          "  Prints a listing of the users that are currently connected to the\n"
01613          "Asterisk manager interface.\n";
01614       return NULL;
01615    case CLI_GENERATE:
01616       return NULL;
01617    }
01618 
01619    ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write");
01620 
01621    i = ao2_iterator_init(sessions, 0);
01622    while ((session = ao2_iterator_next(&i))) {
01623       ao2_lock(session);
01624       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);
01625       count++;
01626       ao2_unlock(session);
01627       unref_mansession(session);
01628    }
01629    ao2_iterator_destroy(&i);
01630    ast_cli(a->fd, "%d users connected.\n", count);
01631 
01632    return CLI_SUCCESS;
01633 }

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 1637 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.

01638 {
01639    struct eventqent *s;
01640    switch (cmd) {
01641    case CLI_INIT:
01642       e->command = "manager show eventq";
01643       e->usage =
01644          "Usage: manager show eventq\n"
01645          "  Prints a listing of all events pending in the Asterisk manger\n"
01646          "event queue.\n";
01647       return NULL;
01648    case CLI_GENERATE:
01649       return NULL;
01650    }
01651    AST_RWLIST_RDLOCK(&all_events);
01652    AST_RWLIST_TRAVERSE(&all_events, s, eq_next) {
01653       ast_cli(a->fd, "Usecount: %d\n", s->usecount);
01654       ast_cli(a->fd, "Category: %d\n", s->category);
01655       ast_cli(a->fd, "Event:\n%s", s->eventdata);
01656    }
01657    AST_RWLIST_UNLOCK(&all_events);
01658 
01659    return CLI_SUCCESS;
01660 }

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

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

02517 {
02518    int x;
02519    char hdr[40];
02520    const char *action, *cat, *var, *value, *match, *line;
02521    struct ast_category *category;
02522    struct ast_variable *v;
02523    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
02524    enum error_type result = 0;
02525 
02526    for (x = 0; x < 100000; x++) {   /* 100000 = the max number of allowed updates + 1 */
02527       unsigned int object = 0;
02528 
02529       snprintf(hdr, sizeof(hdr), "Action-%06d", x);
02530       action = astman_get_header(m, hdr);
02531       if (ast_strlen_zero(action))     /* breaks the for loop if no action header */
02532          break;                        /* this could cause problems if actions come in misnumbered */
02533 
02534       snprintf(hdr, sizeof(hdr), "Cat-%06d", x);
02535       cat = astman_get_header(m, hdr);
02536       if (ast_strlen_zero(cat)) {      /* every action needs a category */
02537          result =  UNSPECIFIED_CATEGORY;
02538          break;
02539       }
02540 
02541       snprintf(hdr, sizeof(hdr), "Var-%06d", x);
02542       var = astman_get_header(m, hdr);
02543 
02544       snprintf(hdr, sizeof(hdr), "Value-%06d", x);
02545       value = astman_get_header(m, hdr);
02546 
02547       if (!ast_strlen_zero(value) && *value == '>') {
02548          object = 1;
02549          value++;
02550       }
02551 
02552       snprintf(hdr, sizeof(hdr), "Match-%06d", x);
02553       match = astman_get_header(m, hdr);
02554 
02555       snprintf(hdr, sizeof(hdr), "Line-%06d", x);
02556       line = astman_get_header(m, hdr);
02557 
02558       if (!strcasecmp(action, "newcat")) {
02559          if (ast_category_get(cfg,cat)) { /* check to make sure the cat doesn't */
02560             result = FAILURE_NEWCAT;   /* already exist */
02561             break;
02562          }
02563          if (!(category = ast_category_new(cat, dfn, -1))) {
02564             result = FAILURE_ALLOCATION;
02565             break;
02566          }
02567          if (ast_strlen_zero(match)) {
02568             ast_category_append(cfg, category);
02569          } else {
02570             ast_category_insert(cfg, category, match);
02571          }
02572       } else if (!strcasecmp(action, "renamecat")) {
02573          if (ast_strlen_zero(value)) {
02574             result = UNSPECIFIED_ARGUMENT;
02575             break;
02576          }
02577          if (!(category = ast_category_get(cfg, cat))) {
02578             result = UNKNOWN_CATEGORY;
02579             break;
02580          }
02581          ast_category_rename(category, value);
02582       } else if (!strcasecmp(action, "delcat")) {
02583          if (ast_category_delete(cfg, cat)) {
02584             result = FAILURE_DELCAT;
02585             break;
02586          }
02587       } else if (!strcasecmp(action, "emptycat")) {
02588          if (ast_category_empty(cfg, cat)) {
02589             result = FAILURE_EMPTYCAT;
02590             break;
02591          }
02592       } else if (!strcasecmp(action, "update")) {
02593          if (ast_strlen_zero(var)) {
02594             result = UNSPECIFIED_ARGUMENT;
02595             break;
02596          }
02597          if (!(category = ast_category_get(cfg,cat))) {
02598             result = UNKNOWN_CATEGORY;
02599             break;
02600          }
02601          if (ast_variable_update(category, var, value, match, object)) {
02602             result = FAILURE_UPDATE;
02603             break;
02604          }
02605       } else if (!strcasecmp(action, "delete")) {
02606          if ((ast_strlen_zero(var) && ast_strlen_zero(line))) {
02607             result = UNSPECIFIED_ARGUMENT;
02608             break;
02609          }
02610          if (!(category = ast_category_get(cfg, cat))) {
02611             result = UNKNOWN_CATEGORY;
02612             break;
02613          }
02614          if (ast_variable_delete(category, var, match, line)) {
02615             result = FAILURE_DELETE;
02616             break;
02617          }
02618       } else if (!strcasecmp(action, "append")) {
02619          if (ast_strlen_zero(var)) {
02620             result = UNSPECIFIED_ARGUMENT;
02621             break;
02622          }
02623          if (!(category = ast_category_get(cfg, cat))) {
02624             result = UNKNOWN_CATEGORY;
02625             break;
02626          }
02627          if (!(v = ast_variable_new(var, value, dfn))) {
02628             result = FAILURE_ALLOCATION;
02629             break;
02630          }
02631          if (object || (match && !strcasecmp(match, "object"))) {
02632             v->object = 1;
02633          }
02634          ast_variable_append(category, v);
02635       } else if (!strcasecmp(action, "insert")) {
02636          if (ast_strlen_zero(var) || ast_strlen_zero(line)) {
02637             result = UNSPECIFIED_ARGUMENT;
02638             break;
02639          }
02640          if (!(category = ast_category_get(cfg, cat))) {
02641             result = UNKNOWN_CATEGORY;
02642             break;
02643          }
02644          if (!(v = ast_variable_new(var, value, dfn))) {
02645             result = FAILURE_ALLOCATION;
02646             break;
02647          }
02648          ast_variable_insert(category, v, line);
02649       }
02650       else {
02651          ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action);
02652          result = UNKNOWN_ACTION;
02653          break;
02654       }
02655    }
02656    ast_free(str1);
02657    ast_free(str2);
02658    return result;
02659 }

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

Referenced by action_getconfigjson().

02436 {
02437    for (; *in; in++) {
02438       if (*in == '\\' || *in == '\"') {
02439          *out++ = '\\';
02440       }
02441       *out++ = *in;
02442    }
02443    *out = '\0';
02444 }

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

01347 {
01348    struct ast_manager_user *user = NULL;
01349    int ret = 0;
01350 
01351    AST_RWLIST_RDLOCK(&users);
01352    if ((user = get_manager_by_name_locked (session->username))) {
01353       ret = user->displayconnects;
01354    }
01355    AST_RWLIST_UNLOCK(&users);
01356 
01357    return ret;
01358 }

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

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

04326 {
04327    int res;
04328    const char *module = astman_get_header(m, "Module");
04329    const char *id = astman_get_header(m, "ActionID");
04330    char idText[256];
04331 #if !defined(LOW_MEMORY)
04332    const char *version;
04333 #endif
04334    char filename[PATH_MAX];
04335    char *cut;
04336 
04337    ast_copy_string(filename, module, sizeof(filename));
04338    if ((cut = strchr(filename, '.'))) {
04339       *cut = '\0';
04340    } else {
04341       cut = filename + strlen(filename);
04342    }
04343    snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".so");
04344    ast_log(LOG_DEBUG, "**** ModuleCheck .so file %s\n", filename);
04345    res = ast_module_check(filename);
04346    if (!res) {
04347       astman_send_error(s, m, "Module not loaded");
04348       return 0;
04349    }
04350    snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".c");
04351    ast_log(LOG_DEBUG, "**** ModuleCheck .c file %s\n", filename);
04352 #if !defined(LOW_MEMORY)
04353    version = ast_file_version_find(filename);
04354 #endif
04355 
04356    if (!ast_strlen_zero(id)) {
04357       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
04358    } else {
04359       idText[0] = '\0';
04360    }
04361    astman_append(s, "Response: Success\r\n%s", idText);
04362 #if !defined(LOW_MEMORY)
04363    astman_append(s, "Version: %s\r\n\r\n", version ? version : "");
04364 #endif
04365    return 0;
04366 }

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

Definition at line 4368 of file manager.c.

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

Referenced by __init_manager().

04369 {
04370    int res;
04371    const char *module = astman_get_header(m, "Module");
04372    const char *loadtype = astman_get_header(m, "LoadType");
04373 
04374    if (!loadtype || strlen(loadtype) == 0) {
04375       astman_send_error(s, m, "Incomplete ModuleLoad action.");
04376    }
04377    if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0) {
04378       astman_send_error(s, m, "Need module name");
04379    }
04380 
04381    if (!strcasecmp(loadtype, "load")) {
04382       res = ast_load_resource(module);
04383       if (res) {
04384          astman_send_error(s, m, "Could not load module.");
04385       } else {
04386          astman_send_ack(s, m, "Module loaded.");
04387       }
04388    } else if (!strcasecmp(loadtype, "unload")) {
04389       res = ast_unload_resource(module, AST_FORCE_SOFT);
04390       if (res) {
04391          astman_send_error(s, m, "Could not unload module.");
04392       } else {
04393          astman_send_ack(s, m, "Module unloaded.");
04394       }
04395    } else if (!strcasecmp(loadtype, "reload")) {
04396       if (module != NULL) {
04397          res = ast_module_reload(module);
04398          if (res == 0) {
04399             astman_send_error(s, m, "No such module.");
04400          } else if (res == 1) {
04401             astman_send_error(s, m, "Module does not support reload action.");
04402          } else {
04403             astman_send_ack(s, m, "Module reloaded.");
04404          }
04405       } else {
04406          ast_module_reload(NULL);   /* Reload all modules */
04407          astman_send_ack(s, m, "All modules reloaded");
04408       }
04409    } else
04410       astman_send_error(s, m, "Incomplete ModuleLoad action.");
04411    return 0;
04412 }

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

Definition at line 4896 of file manager.c.

References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.

Referenced by __init_manager().

04897 {
04898    /* Notify managers of change */
04899    char hint[512];
04900    ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten);
04901 
04902    manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state);
04903    return 0;
04904 }

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

Definition at line 1298 of file manager.c.

References CMP_MATCH, str, and mansession_session::username.

01299 {
01300    struct mansession_session *s = obj;
01301    char *str = arg;
01302    return !strcasecmp(s->username, str) ? CMP_MATCH : 0;
01303 }

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

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

02004 {
02005    ast_sockaddr_to_sin(&s->tcptls_session->parent->local_address,
02006              sin_local);
02007 
02008    return sin_local;
02009 }

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

Definition at line 1996 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 1968 of file manager.c.

References ast_mutex_lock, and mansession::lock.

Referenced by action_challenge(), and process_message().

01969 {
01970    ast_mutex_lock(&s->lock);
01971 }

static void mansession_unlock ( struct mansession s  )  [static]

Unlock the 'mansession' structure.

Definition at line 1974 of file manager.c.

References ast_mutex_unlock, and mansession::lock.

Referenced by action_challenge(), and process_message().

01975 {
01976    ast_mutex_unlock(&s->lock);
01977 }

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

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

04078 {
04079    int result = 0;
04080 
04081    ast_debug(3, "Examining event:\n%s\n", eventdata);
04082    if (!ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) {
04083       return 1; /* no filtering means match all */
04084    } else if (ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) {
04085       /* white filters only: implied black all filter processed first, then white filters */
04086       ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04087    } else if (!ao2_container_count(s->session->whitefilters) && ao2_container_count(s->session->blackfilters)) {
04088       /* black filters only: implied white all filter processed first, then black filters */
04089       ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04090    } else {
04091       /* white and black filters: implied black all filter processed first, then white filters, and lastly black filters */
04092       ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04093       if (result) {
04094          result = 0;
04095          ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04096       }
04097    }
04098 
04099    return result;
04100 }

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

04108 {
04109    int ret = 0;
04110 
04111    ao2_lock(s->session);
04112    if (s->session->f != NULL) {
04113       struct eventqent *eqe = s->session->last_ev;
04114 
04115       while ((eqe = advance_event(eqe))) {
04116          if (!ret && s->session->authenticated &&
04117              (s->session->readperm & eqe->category) == eqe->category &&
04118              (s->session->send_events & eqe->category) == eqe->category) {
04119                if (match_filter(s, eqe->eventdata)) {
04120                   if (send_string(s, eqe->eventdata) < 0)
04121                      ret = -1;   /* don't send more */
04122                }
04123          }
04124          s->session->last_ev = eqe;
04125       }
04126    }
04127    ao2_unlock(s->session);
04128    return ret;
04129 }

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

Definition at line 4427 of file manager.c.

References __astman_get_header(), manager_action::action, allowmultiplelogin, ast_copy_string(), ast_debug, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, 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(), report_req_bad_format(), report_req_not_allowed(), report_session_limit(), mansession::session, and mansession_session::writeperm.

Referenced by do_message().

04428 {
04429    char action[80] = "";
04430    int ret = 0;
04431    struct manager_action *tmp;
04432    const char *user = astman_get_header(m, "Username");
04433    int (*call_func)(struct mansession *s, const struct message *m) = NULL;
04434 
04435    ast_copy_string(action, __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY), sizeof(action));
04436 
04437    if (ast_strlen_zero(action)) {
04438       report_req_bad_format(s, "NONE");
04439       mansession_lock(s);
04440       astman_send_error(s, m, "Missing action in request");
04441       mansession_unlock(s);
04442       return 0;
04443    }
04444 
04445    if (!s->session->authenticated && strcasecmp(action, "Login") && strcasecmp(action, "Logoff") && strcasecmp(action, "Challenge")) {
04446       if (!s->session->authenticated) {
04447          report_req_not_allowed(s, action);
04448       }
04449       mansession_lock(s);
04450       astman_send_error(s, m, "Permission denied");
04451       mansession_unlock(s);
04452       return 0;
04453    }
04454 
04455    if (!allowmultiplelogin && !s->session->authenticated && user &&
04456       (!strcasecmp(action, "Login") || !strcasecmp(action, "Challenge"))) {
04457       if (check_manager_session_inuse(user)) {
04458          report_session_limit(s);
04459          sleep(1);
04460          mansession_lock(s);
04461          astman_send_error(s, m, "Login Already In Use");
04462          mansession_unlock(s);
04463          return -1;
04464       }
04465    }
04466 
04467    AST_RWLIST_RDLOCK(&actions);
04468    AST_RWLIST_TRAVERSE(&actions, tmp, list) {
04469       if (strcasecmp(action, tmp->action)) {
04470          continue;
04471       }
04472       if (s->session->writeperm & tmp->authority || tmp->authority == 0) {
04473          call_func = tmp->func;
04474       } else {
04475          astman_send_error(s, m, "Permission denied");
04476          report_req_not_allowed(s, action);
04477       }
04478       break;
04479    }
04480    AST_RWLIST_UNLOCK(&actions);
04481 
04482    if (tmp && call_func) {
04483       /* call AMI function after actions list are unlocked */
04484       ast_debug(1, "Running action '%s'\n", tmp->action);
04485       ret = call_func(s, m);
04486    } else {
04487       char buf[512];
04488       if (!tmp) {
04489          report_req_bad_format(s, action);
04490       }
04491       snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action);
04492       mansession_lock(s);
04493       astman_send_error(s, m, buf);
04494       mansession_unlock(s);
04495    }
04496    if (ret) {
04497       return ret;
04498    }
04499    /* Once done with our message, deliver any pending events unless the
04500       requester doesn't want them as part of this response.
04501    */
04502    if (ast_strlen_zero(astman_get_header(m, "SuppressEvents"))) {
04503       return process_events(s);
04504    } else {
04505       return ret;
04506    }
04507 }

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

01072 {
01073    struct eventqent *ev;
01074    struct timeval now = ast_tvnow();
01075 
01076    AST_RWLIST_WRLOCK(&all_events);
01077    while ( (ev = AST_RWLIST_FIRST(&all_events)) &&
01078        ev->usecount == 0 && AST_RWLIST_NEXT(ev, eq_next)) {
01079       AST_RWLIST_REMOVE_HEAD(&all_events, eq_next);
01080       ast_free(ev);
01081    }
01082 
01083    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&all_events, ev, eq_next) {
01084       /* Never release the last event */
01085       if (!AST_RWLIST_NEXT(ev, eq_next)) {
01086          break;
01087       }
01088 
01089       /* 2.5 times whatever the HTTP timeout is (maximum 2.5 hours) is the maximum time that we will definitely cache an event */
01090       if (ev->usecount == 0 && ast_tvdiff_sec(now, ev->tv) > (httptimeout > 3600 ? 3600 : httptimeout) * 2.5) {
01091          AST_RWLIST_REMOVE_CURRENT(eq_next);
01092          ast_free(ev);
01093       }
01094    }
01095    AST_RWLIST_TRAVERSE_SAFE_END;
01096    AST_RWLIST_UNLOCK(&all_events);
01097 }

static void purge_sessions ( int  n_max  )  [static]

remove at most n_max stale session from the list.

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

04707 {
04708    struct mansession_session *session;
04709    time_t now = time(NULL);
04710    struct ao2_iterator i;
04711 
04712    i = ao2_iterator_init(sessions, 0);
04713    while ((session = ao2_iterator_next(&i)) && n_max > 0) {
04714       ao2_lock(session);
04715       if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) {
04716          if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) {
04717             ast_verb(2, "HTTP Manager '%s' timed out from %s\n",
04718                session->username, ast_inet_ntoa(session->sin.sin_addr));
04719          }
04720          ao2_unlock(session);
04721          session_destroy(session);
04722          n_max--;
04723       } else {
04724          ao2_unlock(session);
04725          unref_mansession(session);
04726       }
04727    }
04728    ao2_iterator_destroy(&i);
04729 }

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

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

02090 {
02091    struct sockaddr_in sin_local;
02092    char session_id[32];
02093    struct ast_security_event_successful_auth successful_auth = {
02094       .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH,
02095       .common.version    = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
02096       .common.service    = "AMI",
02097       .common.account_id = s->session->username,
02098       .common.session_tv = &s->session->sessionstart_tv,
02099       .common.local_addr = {
02100          .sin       = mansession_encode_sin_local(s, &sin_local),
02101          .transport = mansession_get_transport(s),
02102       },
02103       .common.remote_addr = {
02104          .sin       = &s->session->sin,
02105          .transport = mansession_get_transport(s),
02106       },
02107       .common.session_id = session_id,
02108    };
02109 
02110    snprintf(session_id, sizeof(session_id), "%p", s->session);
02111 
02112    ast_security_event_report(AST_SEC_EVT(&successful_auth));
02113 }

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

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

02038 {
02039    struct sockaddr_in sin_local;
02040    char session_id[32];
02041    struct ast_security_event_failed_acl failed_acl_event = {
02042       .common.event_type = AST_SECURITY_EVENT_FAILED_ACL,
02043       .common.version    = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
02044       .common.service    = "AMI",
02045       .common.account_id = username,
02046       .common.session_tv = &s->session->sessionstart_tv,
02047       .common.local_addr = {
02048          .sin       = mansession_encode_sin_local(s, &sin_local),
02049          .transport = mansession_get_transport(s),
02050       },
02051       .common.remote_addr = {
02052          .sin       = &s->session->sin,
02053          .transport = mansession_get_transport(s),
02054       },
02055       .common.session_id = session_id,
02056    };
02057 
02058    snprintf(session_id, sizeof(session_id), "%p", s->session);
02059 
02060    ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
02061 }

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

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

02177 {
02178    struct sockaddr_in sin_local;
02179    char session_id[32];
02180    struct ast_security_event_chal_resp_failed chal_resp_failed = {
02181       .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED,
02182       .common.version    = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
02183       .common.service    = "AMI",
02184       .common.account_id = s->session->username,
02185       .common.session_tv = &s->session->sessionstart_tv,
02186       .common.local_addr = {
02187          .sin       = mansession_encode_sin_local(s, &sin_local),
02188          .transport = mansession_get_transport(s),
02189       },
02190       .common.remote_addr = {
02191          .sin       = &s->session->sin,
02192          .transport = mansession_get_transport(s),
02193       },
02194       .common.session_id = session_id,
02195 
02196       .challenge         = s->session->challenge,
02197       .response          = response,
02198       .expected_response = expected_response,
02199    };
02200 
02201    snprintf(session_id, sizeof(session_id), "%p", s->session);
02202 
02203    ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
02204 }

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

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

02064 {
02065    struct sockaddr_in sin_local;
02066    char session_id[32];
02067    struct ast_security_event_inval_password inval_password = {
02068       .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD,
02069       .common.version    = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
02070       .common.service    = "AMI",
02071       .common.account_id = username,
02072       .common.session_tv = &s->session->sessionstart_tv,
02073       .common.local_addr = {
02074          .sin       = mansession_encode_sin_local(s, &sin_local),
02075          .transport = mansession_get_transport(s),
02076       },
02077       .common.remote_addr = {
02078          .sin       = &s->session->sin,
02079          .transport = mansession_get_transport(s),
02080       },
02081       .common.session_id = session_id,
02082    };
02083 
02084    snprintf(session_id, sizeof(session_id), "%p", s->session);
02085 
02086    ast_security_event_report(AST_SEC_EVT(&inval_password));
02087 }

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

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

02012 {
02013    struct sockaddr_in sin_local;
02014    char session_id[32];
02015    struct ast_security_event_inval_acct_id inval_acct_id = {
02016       .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID,
02017       .common.version    = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
02018       .common.service    = "AMI",
02019       .common.account_id = username,
02020       .common.session_tv = &s->session->sessionstart_tv,
02021       .common.local_addr = {
02022          .sin       = mansession_encode_sin_local(s, &sin_local),
02023          .transport = mansession_get_transport(s),
02024       },
02025       .common.remote_addr = {
02026          .sin       = &s->session->sin,
02027          .transport = mansession_get_transport(s),
02028       },
02029       .common.session_id = session_id,
02030    };
02031 
02032    snprintf(session_id, sizeof(session_id), "%p", s);
02033 
02034    ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
02035 }

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

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

02146 {
02147    struct sockaddr_in sin_local;
02148    char session_id[32];
02149    char request_type[64];
02150    struct ast_security_event_req_bad_format req_bad_format = {
02151       .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT,
02152       .common.version    = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
02153       .common.service    = "AMI",
02154       .common.account_id = s->session->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       .request_type      = request_type,
02167    };
02168 
02169    snprintf(session_id, sizeof(session_id), "%p", s->session);
02170    snprintf(request_type, sizeof(request_type), "Action: %s", action);
02171 
02172    ast_security_event_report(AST_SEC_EVT(&req_bad_format));
02173 }

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

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

02116 {
02117    struct sockaddr_in sin_local;
02118    char session_id[32];
02119    char request_type[64];
02120    struct ast_security_event_req_not_allowed req_not_allowed = {
02121       .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED,
02122       .common.version    = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
02123       .common.service    = "AMI",
02124       .common.account_id = s->session->username,
02125       .common.session_tv = &s->session->sessionstart_tv,
02126       .common.local_addr = {
02127          .sin       = mansession_encode_sin_local(s, &sin_local),
02128          .transport = mansession_get_transport(s),
02129       },
02130       .common.remote_addr = {
02131          .sin       = &s->session->sin,
02132          .transport = mansession_get_transport(s),
02133       },
02134       .common.session_id = session_id,
02135 
02136       .request_type      = request_type,
02137    };
02138 
02139    snprintf(session_id, sizeof(session_id), "%p", s->session);
02140    snprintf(request_type, sizeof(request_type), "Action: %s", action);
02141 
02142    ast_security_event_report(AST_SEC_EVT(&req_not_allowed));
02143 }

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

Definition at line 2206 of file manager.c.

References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_SESSION_LIMIT, AST_SECURITY_EVENT_SESSION_LIMIT_VERSION, ast_security_event_session_limit::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.

Referenced by process_message().

02207 {
02208    struct sockaddr_in sin_local;
02209    char session_id[32];
02210    struct ast_security_event_session_limit session_limit = {
02211       .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT,
02212       .common.version    = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
02213       .common.service    = "AMI",
02214       .common.account_id = s->session->username,
02215       .common.session_tv = &s->session->sessionstart_tv,
02216       .common.local_addr = {
02217          .sin       = mansession_encode_sin_local(s, &sin_local),
02218          .transport = mansession_get_transport(s),
02219       },
02220       .common.remote_addr = {
02221          .sin       = &s->session->sin,
02222          .transport = mansession_get_transport(s),
02223       },
02224       .common.session_id = session_id,
02225    };
02226 
02227    snprintf(session_id, sizeof(session_id), "%p", s->session);
02228 
02229    ast_security_event_report(AST_SEC_EVT(&session_limit));
02230 }

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

01847 {
01848    int res;
01849    FILE *f = s->f ? s->f : s->session->f;
01850    int fd = s->f ? s->fd : s->session->fd;
01851 
01852    /* It's a result from one of the hook's action invocation */
01853    if (s->hook) {
01854       /*
01855        * to send responses, we're using the same function
01856        * as for receiving events. We call the event "HookResponse"
01857        */
01858       s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string);
01859       return 0;
01860    }
01861        
01862    if ((res = ast_careful_fwrite(f, fd, string, strlen(string), s->session->writetimeout))) {
01863       s->write_error = 1;
01864    }
01865 
01866    return res;
01867 }

static void session_destroy ( struct mansession_session s  )  [static]

Definition at line 1305 of file manager.c.

References ao2_unlink, and unref_mansession().

Referenced by purge_sessions(), and spandsp_fax_destroy().

01306 {
01307    unref_mansession(s);
01308    ao2_unlink(sessions, s);
01309 }

static void session_destructor ( void *  obj  )  [static]

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

01239 {
01240    struct mansession_session *session = obj;
01241    struct eventqent *eqe = session->last_ev;
01242    struct ast_datastore *datastore;
01243 
01244    /* Get rid of each of the data stores on the session */
01245    while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) {
01246       /* Free the data store */
01247       ast_datastore_free(datastore);
01248    }
01249 
01250    if (session->f != NULL) {
01251       fclose(session->f);
01252    }
01253    if (eqe) {
01254       ast_atomic_fetchadd_int(&eqe->usecount, -1);
01255    }
01256 
01257    if (session->whitefilters) {
01258       ao2_t_callback(session->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters");
01259       ao2_t_ref(session->whitefilters, -1 , "decrement ref for white container, should be last one");
01260    }
01261 
01262    if (session->blackfilters) {
01263       ao2_t_callback(session->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters");
01264       ao2_t_ref(session->blackfilters, -1 , "decrement ref for black container, should be last one");
01265    }
01266 }

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

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

04625 {
04626    struct ast_tcptls_session_instance *ser = data;
04627    struct mansession_session *session;
04628    struct mansession s = {
04629       .tcptls_session = data,
04630    };
04631    int flags;
04632    int res;
04633    struct sockaddr_in ser_remote_address_tmp;
04634    struct protoent *p;
04635 
04636    ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
04637    session = build_mansession(ser_remote_address_tmp);
04638 
04639    if (session == NULL) {
04640       goto done;
04641    }
04642 
04643    /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
04644     * This is necessary to prevent delays (caused by buffering) as we
04645     * write to the socket in bits and peices. */
04646    p = getprotobyname("tcp");
04647    if (p) {
04648       int arg = 1;
04649       if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
04650          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));
04651       }
04652    } else {
04653       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");
04654    }
04655 
04656    flags = fcntl(ser->fd, F_GETFL);
04657    if (!block_sockets) { /* make sure socket is non-blocking */
04658       flags |= O_NONBLOCK;
04659    } else {
04660       flags &= ~O_NONBLOCK;
04661    }
04662    fcntl(ser->fd, F_SETFL, flags);
04663 
04664    ao2_lock(session);
04665    /* Hook to the tail of the event queue */
04666    session->last_ev = grab_last();
04667 
04668    ast_mutex_init(&s.lock);
04669 
04670    /* these fields duplicate those in the 'ser' structure */
04671    session->fd = s.fd = ser->fd;
04672    session->f = s.f = ser->f;
04673    session->sin = ser_remote_address_tmp;
04674    s.session = session;
04675 
04676    AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
04677 
04678    ao2_unlock(session);
04679    astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION);   /* welcome prompt */
04680    for (;;) {
04681       if ((res = do_message(&s)) < 0 || s.write_error) {
04682          break;
04683       }
04684    }
04685    /* session is over, explain why and terminate */
04686    if (session->authenticated) {
04687       if (manager_displayconnects(session)) {
04688          ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
04689       }
04690    } else {
04691       if (displayconnects) {
04692          ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
04693       }
04694    }
04695 
04696    session_destroy(session);
04697 
04698    ast_mutex_destroy(&s.lock);
04699 done:
04700    ao2_ref(ser, -1);
04701    ser = NULL;
04702    return NULL;
04703 }

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

01984 {
01985    int maskint = strings_to_mask(eventmask);
01986 
01987    ao2_lock(s->session);
01988    if (maskint >= 0) {
01989       s->session->send_events = maskint;
01990    }
01991    ao2_unlock(s->session);
01992 
01993    return maskint;
01994 }

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

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

Referenced by set_eventmask().

01193 {
01194    const char *p;
01195 
01196    if (ast_strlen_zero(string)) {
01197       return -1;
01198    }
01199 
01200    for (p = string; *p; p++) {
01201       if (*p < '0' || *p > '9') {
01202          break;
01203       }
01204    }
01205    if (!*p) { /* all digits */
01206       return atoi(string);
01207    }
01208    if (ast_false(string)) {
01209       return 0;
01210    }
01211    if (ast_true(string)) { /* all permissions */
01212       int x, ret = 0;
01213       for (x = 0; x < ARRAY_LEN(perms); x++) {
01214          ret |= perms[x].num;
01215       }
01216       return ret;
01217    }
01218    return get_perm(string);
01219 }

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

References ao2_ref, ast_log(), LOG_DEBUG, and manager_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().

01224 {
01225    int refcount = ao2_ref(s, -1);
01226         if (manager_debug) {
01227       ast_log(LOG_DEBUG, "Mansession: %p refcount now %d\n", s, refcount - 1);
01228    }
01229    return s;
01230 }

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

Definition at line 4049 of file manager.c.

References CMP_MATCH, and CMP_STOP.

Referenced by match_filter().

04050 {
04051    regex_t *regex_filter = obj;
04052    const char *eventdata = arg;
04053    int *result = data;
04054 
04055    if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
04056       *result = 1;
04057       return (CMP_MATCH | CMP_STOP);
04058    }
04059 
04060    return 0;
04061 }


Variable Documentation

int allowmultiplelogin = 1 [static]

Definition at line 865 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 1876 of file manager.c.

Referenced by astman_append().

int block_sockets [static]

Definition at line 876 of file manager.c.

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

int broken_events_action [static]

Definition at line 868 of file manager.c.

Referenced by __init_manager(), and action_events().

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

Referenced by check_blacklist().

const int DEFAULT_BLOCKSOCKETS = 0 [static]

Default setting for block-sockets

Definition at line 858 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_BROKENEVENTSACTION = 0 [static]

Default setting for brokeneventsaction

Definition at line 862 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_DISPLAYCONNECTS = 1 [static]

Default setting for displaying manager connections

Definition at line 859 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_ENABLED = 0 [static]

Default setting for manager to be enabled

Definition at line 856 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_HTTPTIMEOUT = 60 [static]

Default manager http timeout

Definition at line 861 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_TIMESTAMPEVENTS = 0 [static]

Default setting for timestampevents

Definition at line 860 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 857 of file manager.c.

Referenced by __init_manager().

int displayconnects [static]

Definition at line 864 of file manager.c.

Referenced by __init_manager(), and handle_manager_show_settings().

char global_realm[MAXHOSTNAMELEN] [static]

Default realm

Definition at line 874 of file manager.c.

Referenced by __init_manager().

int httptimeout [static]

Definition at line 867 of file manager.c.

Referenced by __init_manager(), and handle_manager_show_settings().

char* manager_channelvars [static]

Definition at line 871 of file manager.c.

Referenced by handle_manager_show_settings().

int manager_debug [static]

enable some debugging code in the manager

Definition at line 878 of file manager.c.

Referenced by __ast_manager_event_multichan(), handle_manager_show_settings(), handle_mandebug(), and unref_mansession().

int manager_enabled = 0 [static]

Definition at line 869 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 4782 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 4759 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 979 of file manager.c.

int timestampevents [static]

Definition at line 866 of file manager.c.

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

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

Definition at line 1877 of file manager.c.

Referenced by action_userevent().

int webmanager_enabled = 0 [static]

Definition at line 870 of file manager.c.

Referenced by __init_manager(), and handle_manager_show_settings().

const char* words[AST_MAX_CMD_LEN] [inherited]

Definition at line 892 of file manager.c.


Generated on Wed Apr 6 11:30:12 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7