Mon Jun 27 16:51:22 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 authlimit
static int authtimeout
static int block_sockets
static int broken_events_action
struct {
   const char *   words [AST_MAX_CMD_LEN]
command_blacklist []
static const int DEFAULT_AUTHLIMIT = 50
static const int DEFAULT_AUTHTIMEOUT = 30
static const int DEFAULT_BLOCKSOCKETS = 0
static const int DEFAULT_BROKENEVENTSACTION = 0
static const int DEFAULT_DISPLAYCONNECTS = 1
static const int DEFAULT_ENABLED = 0
static const int DEFAULT_HTTPTIMEOUT = 60
static const int DEFAULT_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 int unauth_sessions = 0
static struct ast_threadstorage userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , }
static int webmanager_enabled = 0

Detailed Description

callback to display queues status in manager


Define Documentation

#define ASTMAN_APPEND_BUF_INITSIZE   256

initial allocated size for the astman_append_buf

Definition at line 1879 of file manager.c.

Referenced by astman_append().

#define DEFAULT_REALM   "asterisk"

Definition at line 877 of file manager.c.

Referenced by __init_manager().

#define GET_HEADER_FIRST_MATCH   0

Definition at line 1706 of file manager.c.

Referenced by astman_get_header().

#define GET_HEADER_LAST_MATCH   1

Definition at line 1707 of file manager.c.

Referenced by __astman_get_header().

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 1708 of file manager.c.

Referenced by __astman_get_header(), and process_message().

#define MANAGER_EVENT_BUF_INITSIZE   256

Definition at line 4831 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 895 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 1920 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 4833 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().

04835 {
04836    struct mansession_session *session;
04837    struct manager_custom_hook *hook;
04838    struct ast_str *auth = ast_str_alloca(80);
04839    const char *cat_str;
04840    va_list ap;
04841    struct timeval now;
04842    struct ast_str *buf;
04843    int i;
04844 
04845    if (!(sessions && ao2_container_count(sessions)) && AST_RWLIST_EMPTY(&manager_hooks)) {
04846       return 0;
04847    }
04848    
04849    if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) {
04850       return -1;
04851    }
04852 
04853    cat_str = authority_to_str(category, &auth);
04854    ast_str_set(&buf, 0,
04855          "Event: %s\r\nPrivilege: %s\r\n",
04856           event, cat_str);
04857 
04858    if (timestampevents) {
04859       now = ast_tvnow();
04860       ast_str_append(&buf, 0,
04861             "Timestamp: %ld.%06lu\r\n",
04862              (long)now.tv_sec, (unsigned long) now.tv_usec);
04863    }
04864    if (manager_debug) {
04865       static int seq;
04866       ast_str_append(&buf, 0,
04867             "SequenceNumber: %d\r\n",
04868              ast_atomic_fetchadd_int(&seq, 1));
04869       ast_str_append(&buf, 0,
04870             "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func);
04871    }
04872 
04873    va_start(ap, fmt);
04874    ast_str_append_va(&buf, 0, fmt, ap);
04875    va_end(ap);
04876    for (i = 0; i < chancount; i++) {
04877       append_channel_vars(&buf, chans[i]);
04878    }
04879 
04880    ast_str_append(&buf, 0, "\r\n");
04881 
04882    append_event(ast_str_buffer(buf), category);
04883 
04884    /* Wake up any sleeping sessions */
04885    if (sessions) {
04886       struct ao2_iterator i;
04887       i = ao2_iterator_init(sessions, 0);
04888       while ((session = ao2_iterator_next(&i))) {
04889          ao2_lock(session);
04890          if (session->waiting_thread != AST_PTHREADT_NULL) {
04891             pthread_kill(session->waiting_thread, SIGURG);
04892          } else {
04893             /* We have an event to process, but the mansession is
04894              * not waiting for it. We still need to indicate that there
04895              * is an event waiting so that get_input processes the pending
04896              * event instead of polling.
04897              */
04898             session->pending_event = 1;
04899          }
04900          ao2_unlock(session);
04901          unref_mansession(session);
04902       }
04903       ao2_iterator_destroy(&i);
04904    }
04905 
04906    if (!AST_RWLIST_EMPTY(&manager_hooks)) {
04907       AST_RWLIST_RDLOCK(&manager_hooks);
04908       AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) {
04909          hook->helper(category, event, ast_str_buffer(buf));
04910       }
04911       AST_RWLIST_UNLOCK(&manager_hooks);
04912    }
04913 
04914    return 0;
04915 }

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

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

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

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

01885 {

static void __init_manager_event_buf ( void   )  [static]

Definition at line 4830 of file manager.c.

04835 {

static void __init_manager_event_funcbuf ( void   )  [static]

Definition at line 4807 of file manager.c.

04810 {

static void __init_userevent_buf ( void   )  [static]

Definition at line 1876 of file manager.c.

01885 {

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

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

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

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

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

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

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

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

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

Show PBX core settings information.

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

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

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

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

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

Show PBX core status information.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 2922 of file manager.c.

References ast_atomic_fetchadd_int(), 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, unauth_sessions, and mansession_session::username.

Referenced by __init_manager().

02923 {
02924 
02925    /* still authenticated - don't process again */
02926    if (s->session->authenticated) {
02927       astman_send_ack(s, m, "Already authenticated");
02928       return 0;
02929    }
02930 
02931    if (authenticate(s, m)) {
02932       sleep(1);
02933       astman_send_error(s, m, "Authentication failed");
02934       return -1;
02935    }
02936    s->session->authenticated = 1;
02937    ast_atomic_fetchadd_int(&unauth_sessions, -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 2916 of file manager.c.

References astman_send_response().

Referenced by __init_manager().

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

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

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

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

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

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

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

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

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

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

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

Definition at line 2335 of file manager.c.

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

Referenced by __init_manager().

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

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

action_redirect: The redirect manager command

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

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

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

Send a reload event.

Definition at line 4234 of file manager.c.

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

Referenced by __init_manager().

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

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_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    res = ast_sendtext(c, textmsg);
03262    c = ast_channel_unref(c);
03263 
03264    if (res >= 0) {
03265       astman_send_ack(s, m, "Success");
03266    } else {
03267       astman_send_error(s, m, "Failure");
03268    }
03269 
03270    return res;
03271 }

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

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

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

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

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

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

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

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

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

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

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

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

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

01688 {
01689    struct eventqent *next;
01690 
01691    AST_RWLIST_RDLOCK(&all_events);
01692    if ((next = AST_RWLIST_NEXT(e, eq_next))) {
01693       ast_atomic_fetchadd_int(&next->usecount, 1);
01694       ast_atomic_fetchadd_int(&e->usecount, -1);
01695    }
01696    AST_RWLIST_UNLOCK(&all_events);
01697    return next;
01698 }

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

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

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

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

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

04810 {
04811    struct manager_channel_variable *var;
04812    AST_RWLIST_RDLOCK(&channelvars);
04813    AST_LIST_TRAVERSE(&channelvars, var, entry) {
04814       const char *val = "";
04815       if (var->isfunc) {
04816          struct ast_str *res = ast_str_thread_get(&manager_event_funcbuf, 16);
04817          int ret;
04818          if (res && (ret = ast_func_read2(chan, var->name, &res, 0)) == 0) {
04819             val = ast_str_buffer(res);
04820          }
04821       } else {
04822          val = pbx_builtin_getvar_helper(chan, var->name);
04823       }
04824       ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", chan->name, var->name, val ? val : "");
04825    }
04826    AST_RWLIST_UNLOCK(&channelvars);
04827 }

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

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

04784 {
04785    struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str));
04786    static int seq;   /* sequence number */
04787 
04788    if (!tmp) {
04789       return -1;
04790    }
04791 
04792    /* need to init all fields, because ast_malloc() does not */
04793    tmp->usecount = 0;
04794    tmp->category = category;
04795    tmp->seq = ast_atomic_fetchadd_int(&seq, 1);
04796    tmp->tv = ast_tvnow();
04797    AST_RWLIST_NEXT(tmp, eq_next) = NULL;
04798    strcpy(tmp->eventdata, str);
04799 
04800    AST_RWLIST_WRLOCK(&all_events);
04801    AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next);
04802    AST_RWLIST_UNLOCK(&all_events);
04803 
04804    return 0;
04805 }

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

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

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

References eventqent::next.

Referenced by get_perm().

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

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

04992 {
04993    struct manager_action *cur = NULL;
04994 #ifdef AST_XML_DOCS
04995    char *tmpxml;
04996 #endif
04997 
04998    if (!(cur = ast_calloc_with_stringfields(1, struct manager_action, 128))) {
04999       return -1;
05000    }
05001 
05002    cur->action = action;
05003    cur->authority = auth;
05004    cur->func = func;
05005 #ifdef AST_XML_DOCS
05006    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
05007       tmpxml = ast_xmldoc_build_synopsis("manager", action);
05008       ast_string_field_set(cur, synopsis, tmpxml);
05009       ast_free(tmpxml);
05010 
05011       tmpxml = ast_xmldoc_build_syntax("manager", action);
05012       ast_string_field_set(cur, syntax, tmpxml);
05013       ast_free(tmpxml);
05014 
05015       tmpxml = ast_xmldoc_build_description("manager", action);
05016       ast_string_field_set(cur, description, tmpxml);
05017       ast_free(tmpxml);
05018 
05019       tmpxml = ast_xmldoc_build_seealso("manager", action);
05020       ast_string_field_set(cur, seealso, tmpxml);
05021       ast_free(tmpxml);
05022 
05023       tmpxml = ast_xmldoc_build_arguments("manager", action);
05024       ast_string_field_set(cur, arguments, tmpxml);
05025       ast_free(tmpxml);
05026 
05027       cur->docsrc = AST_XML_DOC;
05028    } else {
05029 #endif
05030       ast_string_field_set(cur, synopsis, synopsis);
05031       ast_string_field_set(cur, description, description);
05032 #ifdef AST_XML_DOCS
05033       cur->docsrc = AST_STATIC_DOC;
05034    }
05035 #endif
05036    if (ast_manager_register_struct(cur)) {
05037       ast_free(cur);
05038       return -1;
05039    }
05040 
05041    return 0;
05042 }

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 1027 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 4954 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().

04955 {
04956    struct manager_action *cur, *prev = NULL;
04957    struct timespec tv = { 5, };
04958 
04959    if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) {
04960       ast_log(LOG_ERROR, "Could not obtain lock on manager list\n");
04961       return -1;
04962    }
04963    AST_RWLIST_TRAVERSE(&actions, cur, list) {
04964       int ret = strcasecmp(cur->action, act->action);
04965       if (ret == 0) {
04966          ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action);
04967          AST_RWLIST_UNLOCK(&actions);
04968          return -1;
04969       }
04970       if (ret > 0) { /* Insert these alphabetically */
04971          prev = cur;
04972          break;
04973       }
04974    }
04975 
04976    if (prev) {
04977       AST_RWLIST_INSERT_AFTER(&actions, prev, act, list);
04978    } else {
04979       AST_RWLIST_INSERT_HEAD(&actions, act, list);
04980    }
04981 
04982    ast_verb(2, "Manager registered action %s\n", act->action);
04983 
04984    AST_RWLIST_UNLOCK(&actions);
04985 
04986    return 0;
04987 }

int ast_manager_unregister ( char *  action  ) 

Unregister a registered manager command.

Parameters:
action Name of registered Action:

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

04921 {
04922    struct manager_action *cur;
04923    struct timespec tv = { 5, };
04924 
04925    if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) {
04926       ast_log(LOG_ERROR, "Could not obtain lock on manager list\n");
04927       return -1;
04928    }
04929    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) {
04930       if (!strcasecmp(action, cur->action)) {
04931          AST_RWLIST_REMOVE_CURRENT(list);
04932          ast_string_field_free_memory(cur);
04933          ast_free(cur);
04934          ast_verb(2, "Manager unregistered action %s\n", action);
04935          break;
04936       }
04937    }
04938    AST_RWLIST_TRAVERSE_SAFE_END;
04939    AST_RWLIST_UNLOCK(&actions);
04940 
04941    return 0;
04942 }

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

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

01036 {
01037    AST_RWLIST_WRLOCK(&manager_hooks);
01038    AST_RWLIST_REMOVE(&manager_hooks, hook, list);
01039    AST_RWLIST_UNLOCK(&manager_hooks);
01040 }

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

utility functions for creating AMI replies

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

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

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

Get header from mananger transaction.

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

01738 {
01739    return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH);
01740 }

struct ast_variable* astman_get_variables ( const struct message m  ) 

Get a linked list of the Variable: headers.

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

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

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

Send ack in manager transaction.

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

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

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

Send error in manager transaction.

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

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

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

Send ack in manager list transaction.

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

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

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

Send response in manager transaction.

Definition at line 1941 of file manager.c.

References astman_send_response_full().

Referenced by action_logoff().

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

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

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

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

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

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

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

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

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

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

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

Convert authority code to a list of options.

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

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

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

Definition at line 4064 of file manager.c.

References CMP_MATCH, and CMP_STOP.

Referenced by match_filter().

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

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

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

Referenced by session_do().

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

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

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

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

int check_manager_enabled ( void   ) 

Check if AMI is enabled.

Definition at line 1042 of file manager.c.

Referenced by handle_show_settings().

01043 {
01044    return manager_enabled;
01045 }

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

Definition at line 1317 of file manager.c.

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

Referenced by process_message().

01318 {
01319    struct mansession_session *session = ao2_find(sessions, (char *) name, 0);
01320    int inuse = 0;
01321 
01322    if (session) {
01323       inuse = 1;
01324       unref_mansession(session);
01325    }
01326    return inuse;
01327 }

int check_webmanager_enabled ( void   ) 

Check if AMI/HTTP is enabled.

Definition at line 1047 of file manager.c.

Referenced by action_coresettings(), and handle_show_settings().

01048 {
01049    return (webmanager_enabled && manager_enabled);
01050 }

static int do_message ( struct mansession s  )  [static]

Definition at line 4607 of file manager.c.

References ast_inet_ntoa(), ast_log(), AST_MAX_MANHEADERS, ast_strdupa, ast_strlen_zero(), ast_verb, authtimeout, displayconnects, errno, get_input(), message::hdrcount, message::headers, mansession_session::inbuf, LOG_ERROR, process_events(), process_message(), and mansession::session.

Referenced by session_do().

04608 {
04609    struct message m = { 0 };
04610    char header_buf[sizeof(s->session->inbuf)] = { '\0' };
04611    int res;
04612    time_t now;
04613 
04614    for (;;) {
04615       /* Check if any events are pending and do them if needed */
04616       if (process_events(s)) {
04617          return -1;
04618       }
04619       res = get_input(s, header_buf);
04620       if (res == 0) {
04621          if (!s->session->authenticated) {
04622             if(time(&now) == -1) {
04623                ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
04624                return -1;
04625             }
04626 
04627             if (now - s->session->authstart > authtimeout) {
04628                if (displayconnects) {
04629                   ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout);
04630                }
04631                return -1;
04632             }
04633          }
04634          continue;
04635       } else if (res > 0) {
04636          if (ast_strlen_zero(header_buf)) {
04637             return process_message(s, &m) ? -1 : 0;
04638          } else if (m.hdrcount < (AST_MAX_MANHEADERS - 1)) {
04639             m.headers[m.hdrcount++] = ast_strdupa(header_buf);
04640          }
04641       } else {
04642          return res;
04643       }
04644    }
04645 }

static void event_filter_destructor ( void *  obj  )  [static]

Definition at line 1237 of file manager.c.

01238 {
01239    regex_t *regex_filter = obj;
01240    regfree(regex_filter);
01241 }

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

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

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

static void free_channelvars ( void   )  [static]

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

06625 {
06626    struct manager_channel_variable *var;
06627    AST_RWLIST_WRLOCK(&channelvars);
06628    while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) {
06629       ast_free(var);
06630    }
06631    AST_RWLIST_UNLOCK(&channelvars);
06632 }

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

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

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

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

References AST_RWLIST_TRAVERSE, ast_manager_user::list, and user.

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

01335 {
01336    struct ast_manager_user *user = NULL;
01337 
01338    AST_RWLIST_TRAVERSE(&users, user, list) {
01339       if (!strcasecmp(user->username, name)) {
01340          break;
01341       }
01342    }
01343 
01344    return user;
01345 }

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

Definition at line 1176 of file manager.c.

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

Referenced by strings_to_mask().

01177 {
01178    int x = 0, ret = 0;
01179 
01180    if (!instr) {
01181       return 0;
01182    }
01183 
01184    for (x = 0; x < ARRAY_LEN(perms); x++) {
01185       if (ast_instring(instr, perms[x].label, ',')) {
01186          ret |= perms[x].num;
01187       }
01188    }
01189 
01190    return ret;
01191 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Referenced by action_getconfigjson().

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

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 1351 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(), purge_sessions(), and session_do().

01352 {
01353    struct ast_manager_user *user = NULL;
01354    int ret = 0;
01355 
01356    AST_RWLIST_RDLOCK(&users);
01357    if ((user = get_manager_by_name_locked (session->username))) {
01358       ret = user->displayconnects;
01359    }
01360    AST_RWLIST_UNLOCK(&users);
01361 
01362    return ret;
01363 }

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

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

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

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

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

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

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

Definition at line 4944 of file manager.c.

References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.

Referenced by __init_manager().

04945 {
04946    /* Notify managers of change */
04947    char hint[512];
04948    ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten);
04949 
04950    manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state);
04951    return 0;
04952 }

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

Definition at line 1303 of file manager.c.

References CMP_MATCH, str, and mansession_session::username.

01304 {
01305    struct mansession_session *s = obj;
01306    char *str = arg;
01307    return !strcasecmp(s->username, str) ? CMP_MATCH : 0;
01308 }

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

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

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

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

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

References ast_mutex_lock, and mansession::lock.

Referenced by action_challenge(), and process_message().

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

static void mansession_unlock ( struct mansession s  )  [static]

Unlock the 'mansession' structure.

Definition at line 1973 of file manager.c.

References ast_mutex_unlock, and mansession::lock.

Referenced by action_challenge(), and process_message().

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

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

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

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

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

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

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

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

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

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

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

static void purge_sessions ( int  n_max  )  [static]

remove at most n_max stale session from the list.

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

04755 {
04756    struct mansession_session *session;
04757    time_t now = time(NULL);
04758    struct ao2_iterator i;
04759 
04760    i = ao2_iterator_init(sessions, 0);
04761    while ((session = ao2_iterator_next(&i)) && n_max > 0) {
04762       ao2_lock(session);
04763       if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) {
04764          if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) {
04765             ast_verb(2, "HTTP Manager '%s' timed out from %s\n",
04766                session->username, ast_inet_ntoa(session->sin.sin_addr));
04767          }
04768          ao2_unlock(session);
04769          session_destroy(session);
04770          n_max--;
04771       } else {
04772          ao2_unlock(session);
04773          unref_mansession(session);
04774       }
04775    }
04776    ao2_iterator_destroy(&i);
04777 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

02145 {
02146    struct sockaddr_in sin_local;
02147    char session_id[32];
02148    char request_type[64];
02149    struct ast_security_event_req_bad_format req_bad_format = {
02150       .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT,
02151       .common.version    = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
02152       .common.service    = "AMI",
02153       .common.account_id = s->session->username,
02154       .common.session_tv = &s->session->sessionstart_tv,
02155       .common.local_addr = {
02156          .sin       = mansession_encode_sin_local(s, &sin_local),
02157          .transport = mansession_get_transport(s),
02158       },
02159       .common.remote_addr = {
02160          .sin       = &s->session->sin,
02161          .transport = mansession_get_transport(s),
02162       },
02163       .common.session_id = session_id,
02164 
02165       .request_type      = request_type,
02166    };
02167 
02168    snprintf(session_id, sizeof(session_id), "%p", s->session);
02169    snprintf(request_type, sizeof(request_type), "Action: %s", action);
02170 
02171    ast_security_event_report(AST_SEC_EVT(&req_bad_format));
02172 }

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

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

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

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

Definition at line 2205 of file manager.c.

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

Referenced by process_message().

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

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

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

Referenced by astman_append(), and process_events().

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

static void session_destroy ( struct mansession_session s  )  [static]

Definition at line 1310 of file manager.c.

References ao2_unlink, and unref_mansession().

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

01311 {
01312    unref_mansession(s);
01313    ao2_unlink(sessions, s);
01314 }

static void session_destructor ( void *  obj  )  [static]

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

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

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

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

04656 {
04657    struct ast_tcptls_session_instance *ser = data;
04658    struct mansession_session *session;
04659    struct mansession s = {
04660       .tcptls_session = data,
04661    };
04662    int flags;
04663    int res;
04664    struct sockaddr_in ser_remote_address_tmp;
04665    struct protoent *p;
04666 
04667    if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
04668       fclose(ser->f);
04669       ast_atomic_fetchadd_int(&unauth_sessions, -1);
04670       goto done;
04671    }
04672 
04673    ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
04674    session = build_mansession(ser_remote_address_tmp);
04675 
04676    if (session == NULL) {
04677       fclose(ser->f);
04678       ast_atomic_fetchadd_int(&unauth_sessions, -1);
04679       goto done;
04680    }
04681 
04682    /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
04683     * This is necessary to prevent delays (caused by buffering) as we
04684     * write to the socket in bits and peices. */
04685    p = getprotobyname("tcp");
04686    if (p) {
04687       int arg = 1;
04688       if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
04689          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));
04690       }
04691    } else {
04692       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");
04693    }
04694 
04695    flags = fcntl(ser->fd, F_GETFL);
04696    if (!block_sockets) { /* make sure socket is non-blocking */
04697       flags |= O_NONBLOCK;
04698    } else {
04699       flags &= ~O_NONBLOCK;
04700    }
04701    fcntl(ser->fd, F_SETFL, flags);
04702 
04703    ao2_lock(session);
04704    /* Hook to the tail of the event queue */
04705    session->last_ev = grab_last();
04706 
04707    ast_mutex_init(&s.lock);
04708 
04709    /* these fields duplicate those in the 'ser' structure */
04710    session->fd = s.fd = ser->fd;
04711    session->f = s.f = ser->f;
04712    session->sin = ser_remote_address_tmp;
04713    s.session = session;
04714 
04715    AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
04716 
04717    if(time(&session->authstart) == -1) {
04718       ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
04719       ast_atomic_fetchadd_int(&unauth_sessions, -1);
04720       ao2_unlock(session);
04721       session_destroy(session);
04722       goto done;
04723    }
04724    ao2_unlock(session);
04725 
04726    astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION);   /* welcome prompt */
04727    for (;;) {
04728       if ((res = do_message(&s)) < 0) {
04729          break;
04730       }
04731    }
04732    /* session is over, explain why and terminate */
04733    if (session->authenticated) {
04734       if (manager_displayconnects(session)) {
04735          ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
04736       }
04737    } else {
04738       ast_atomic_fetchadd_int(&unauth_sessions, -1);
04739       if (displayconnects) {
04740          ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
04741       }
04742    }
04743 
04744    session_destroy(session);
04745 
04746    ast_mutex_destroy(&s.lock);
04747 done:
04748    ao2_ref(ser, -1);
04749    ser = NULL;
04750    return NULL;
04751 }

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

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

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

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

Referenced by set_eventmask().

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

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

01229 {
01230    int refcount = ao2_ref(s, -1);
01231         if (manager_debug) {
01232       ast_log(LOG_DEBUG, "Mansession: %p refcount now %d\n", s, refcount - 1);
01233    }
01234    return s;
01235 }

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

Definition at line 4050 of file manager.c.

References CMP_MATCH, and CMP_STOP.

Referenced by match_filter().

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


Variable Documentation

int allowmultiplelogin = 1 [static]

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

Referenced by astman_append().

int authlimit [static]

Definition at line 874 of file manager.c.

int authtimeout [static]

Definition at line 873 of file manager.c.

int block_sockets [static]

Definition at line 880 of file manager.c.

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

int broken_events_action [static]

Definition at line 870 of file manager.c.

Referenced by __init_manager(), and action_events().

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

Referenced by check_blacklist().

const int DEFAULT_AUTHLIMIT = 50 [static]

Default setting for authlimit

Definition at line 864 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_AUTHTIMEOUT = 30 [static]

Default setting for authtimeout

Definition at line 863 of file manager.c.

Referenced by __init_manager().

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

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

char global_realm[MAXHOSTNAMELEN] [static]

Default realm

Definition at line 878 of file manager.c.

Referenced by __init_manager().

int httptimeout [static]

Definition at line 869 of file manager.c.

Referenced by __init_manager(), and handle_manager_show_settings().

char* manager_channelvars [static]

Definition at line 875 of file manager.c.

Referenced by handle_manager_show_settings().

int manager_debug [static]

enable some debugging code in the manager

Definition at line 883 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 871 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 4830 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 4807 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 984 of file manager.c.

int timestampevents [static]

Definition at line 868 of file manager.c.

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

int unauth_sessions = 0 [static]

Definition at line 881 of file manager.c.

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

Definition at line 1876 of file manager.c.

Referenced by action_userevent().

int webmanager_enabled = 0 [static]

Definition at line 872 of file manager.c.

Referenced by __init_manager(), and handle_manager_show_settings().

const char* words[AST_MAX_CMD_LEN] [inherited]

Definition at line 897 of file manager.c.


Generated on Mon Jun 27 16:51:22 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7