Thu Apr 3 08:22:54 2014

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
}
enum  mansession_message_parsing { MESSAGE_OKAY, MESSAGE_LINE_TOO_LONG }

Functions

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

Variables

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

Detailed Description

callback to display queues status in manager


Define Documentation

#define ASTMAN_APPEND_BUF_INITSIZE   256

initial allocated size for the astman_append_buf

Definition at line 2052 of file manager.c.

Referenced by astman_append().

#define DEFAULT_REALM   "asterisk"

Definition at line 910 of file manager.c.

Referenced by __init_manager(), and reload_config().

#define GET_HEADER_FIRST_MATCH   0

Definition at line 1805 of file manager.c.

Referenced by astman_get_header().

#define GET_HEADER_LAST_MATCH   1

Definition at line 1806 of file manager.c.

Referenced by __astman_get_header().

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 1807 of file manager.c.

Referenced by __astman_get_header(), and process_message().

#define MANAGER_EVENT_BUF_INITSIZE   256

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

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

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

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

Enumerator:
MESSAGE_OKAY 
MESSAGE_LINE_TOO_LONG 

Definition at line 1002 of file manager.c.

01002                                 {
01003    MESSAGE_OKAY,
01004    MESSAGE_LINE_TOO_LONG
01005 };


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

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

05244 {
05245    struct mansession_session *session;
05246    struct manager_custom_hook *hook;
05247    struct ast_str *auth = ast_str_alloca(80);
05248    const char *cat_str;
05249    va_list ap;
05250    struct timeval now;
05251    struct ast_str *buf;
05252    int i;
05253 
05254    if (!(sessions && ao2_container_count(sessions)) && AST_RWLIST_EMPTY(&manager_hooks)) {
05255       return 0;
05256    }
05257    
05258    if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) {
05259       return -1;
05260    }
05261 
05262    cat_str = authority_to_str(category, &auth);
05263    ast_str_set(&buf, 0,
05264          "Event: %s\r\nPrivilege: %s\r\n",
05265           event, cat_str);
05266 
05267    if (timestampevents) {
05268       now = ast_tvnow();
05269       ast_str_append(&buf, 0,
05270             "Timestamp: %ld.%06lu\r\n",
05271              (long)now.tv_sec, (unsigned long) now.tv_usec);
05272    }
05273    if (manager_debug) {
05274       static int seq;
05275       ast_str_append(&buf, 0,
05276             "SequenceNumber: %d\r\n",
05277              ast_atomic_fetchadd_int(&seq, 1));
05278       ast_str_append(&buf, 0,
05279             "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func);
05280    }
05281 
05282    va_start(ap, fmt);
05283    ast_str_append_va(&buf, 0, fmt, ap);
05284    va_end(ap);
05285    for (i = 0; i < chancount; i++) {
05286       append_channel_vars(&buf, chans[i]);
05287    }
05288 
05289    ast_str_append(&buf, 0, "\r\n");
05290 
05291    append_event(ast_str_buffer(buf), category);
05292 
05293    /* Wake up any sleeping sessions */
05294    if (sessions) {
05295       struct ao2_iterator i;
05296       i = ao2_iterator_init(sessions, 0);
05297       while ((session = ao2_iterator_next(&i))) {
05298          ao2_lock(session);
05299          if (session->waiting_thread != AST_PTHREADT_NULL) {
05300             pthread_kill(session->waiting_thread, SIGURG);
05301          } else {
05302             /* We have an event to process, but the mansession is
05303              * not waiting for it. We still need to indicate that there
05304              * is an event waiting so that get_input processes the pending
05305              * event instead of polling.
05306              */
05307             session->pending_event = 1;
05308          }
05309          ao2_unlock(session);
05310          unref_mansession(session);
05311       }
05312       ao2_iterator_destroy(&i);
05313    }
05314 
05315    if (!AST_RWLIST_EMPTY(&manager_hooks)) {
05316       AST_RWLIST_RDLOCK(&manager_hooks);
05317       AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) {
05318          hook->helper(category, event, ast_str_buffer(buf));
05319       }
05320       AST_RWLIST_UNLOCK(&manager_hooks);
05321    }
05322 
05323    return 0;
05324 }

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

Return a matching header value.

Generic function to return either the first or the last matching header from a list of variables, possibly skipping empty strings.

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

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

01823 {
01824    int x, l = strlen(var);
01825    const char *result = "";
01826 
01827    if (!m) {
01828       return result;
01829    }
01830 
01831    for (x = 0; x < m->hdrcount; x++) {
01832       const char *h = m->headers[x];
01833       if (!strncasecmp(var, h, l) && h[l] == ':') {
01834          const char *value = h + l + 1;
01835          value = ast_skip_blanks(value); /* ignore leading spaces in the value */
01836          /* found a potential candidate */
01837          if ((mode & GET_HEADER_SKIP_EMPTY) && ast_strlen_zero(value)) {
01838             continue;   /* not interesting */
01839          }
01840          if (mode & GET_HEADER_LAST_MATCH) {
01841             result = value;   /* record the last match so far */
01842          } else {
01843             return value;
01844          }
01845       }
01846    }
01847 
01848    return result;
01849 }

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

02058 {

static void __init_manager_event_buf ( void   )  [static]

Definition at line 5239 of file manager.c.

05244 {

static void __init_manager_event_funcbuf ( void   )  [static]

Definition at line 5212 of file manager.c.

05215 {

static void __init_userevent_buf ( void   )  [static]

Definition at line 2049 of file manager.c.

02058 {

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

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

03903 {
03904    const char *channel = astman_get_header(m, "Channel");
03905    const char *pchannel = astman_get_header(m, "ChannelPrefix");
03906    const char *msgtype = astman_get_header(m, "MsgType");
03907    const char *chargetype = astman_get_header(m, "ChargeType");
03908    const char *currencyname = astman_get_header(m, "CurrencyName");
03909    const char *currencyamount = astman_get_header(m, "CurrencyAmount");
03910    const char *mult = astman_get_header(m, "CurrencyMultiplier");
03911    const char *totaltype = astman_get_header(m, "TotalType");
03912    const char *aocbillingid = astman_get_header(m, "AOCBillingId");
03913    const char *association_id= astman_get_header(m, "ChargingAssociationId");
03914    const char *association_num = astman_get_header(m, "ChargingAssociationNumber");
03915    const char *association_plan = astman_get_header(m, "ChargingAssociationPlan");
03916 
03917    enum ast_aoc_type _msgtype;
03918    enum ast_aoc_charge_type _chargetype;
03919    enum ast_aoc_currency_multiplier _mult = AST_AOC_MULT_ONE;
03920    enum ast_aoc_total_type _totaltype = AST_AOC_TOTAL;
03921    enum ast_aoc_billing_id _billingid = AST_AOC_BILLING_NA;
03922    unsigned int _currencyamount = 0;
03923    int _association_id = 0;
03924    unsigned int _association_plan = 0;
03925    struct ast_channel *chan = NULL;
03926 
03927    struct ast_aoc_decoded *decoded = NULL;
03928    struct ast_aoc_encoded *encoded = NULL;
03929    size_t encoded_size = 0;
03930 
03931    if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) {
03932       astman_send_error(s, m, "Channel and PartialChannel are not specified. Specify at least one of these.");
03933       goto aocmessage_cleanup;
03934    }
03935 
03936    if (!(chan = ast_channel_get_by_name(channel)) && !ast_strlen_zero(pchannel)) {
03937       chan = ast_channel_get_by_name_prefix(pchannel, strlen(pchannel));
03938    }
03939 
03940    if (!chan) {
03941       astman_send_error(s, m, "No such channel");
03942       goto aocmessage_cleanup;
03943    }
03944 
03945    if (ast_strlen_zero(msgtype) || (strcasecmp(msgtype, "d") && strcasecmp(msgtype, "e"))) {
03946       astman_send_error(s, m, "Invalid MsgType");
03947       goto aocmessage_cleanup;
03948    }
03949 
03950    if (ast_strlen_zero(chargetype)) {
03951       astman_send_error(s, m, "ChargeType not specified");
03952       goto aocmessage_cleanup;
03953    }
03954 
03955    _msgtype = strcasecmp(msgtype, "d") ? AST_AOC_E : AST_AOC_D;
03956 
03957    if (!strcasecmp(chargetype, "NA")) {
03958       _chargetype = AST_AOC_CHARGE_NA;
03959    } else if (!strcasecmp(chargetype, "Free")) {
03960       _chargetype = AST_AOC_CHARGE_FREE;
03961    } else if (!strcasecmp(chargetype, "Currency")) {
03962       _chargetype = AST_AOC_CHARGE_CURRENCY;
03963    } else if (!strcasecmp(chargetype, "Unit")) {
03964       _chargetype = AST_AOC_CHARGE_UNIT;
03965    } else {
03966       astman_send_error(s, m, "Invalid ChargeType");
03967       goto aocmessage_cleanup;
03968    }
03969 
03970    if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
03971 
03972       if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u", &_currencyamount) != 1)) {
03973          astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency");
03974          goto aocmessage_cleanup;
03975       }
03976 
03977       if (ast_strlen_zero(mult)) {
03978          astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency.");
03979          goto aocmessage_cleanup;
03980       } else if (!strcasecmp(mult, "onethousandth")) {
03981          _mult = AST_AOC_MULT_ONETHOUSANDTH;
03982       } else if (!strcasecmp(mult, "onehundredth")) {
03983          _mult = AST_AOC_MULT_ONEHUNDREDTH;
03984       } else if (!strcasecmp(mult, "onetenth")) {
03985          _mult = AST_AOC_MULT_ONETENTH;
03986       } else if (!strcasecmp(mult, "one")) {
03987          _mult = AST_AOC_MULT_ONE;
03988       } else if (!strcasecmp(mult, "ten")) {
03989          _mult = AST_AOC_MULT_TEN;
03990       } else if (!strcasecmp(mult, "hundred")) {
03991          _mult = AST_AOC_MULT_HUNDRED;
03992       } else if (!strcasecmp(mult, "thousand")) {
03993          _mult = AST_AOC_MULT_THOUSAND;
03994       } else {
03995          astman_send_error(s, m, "Invalid ChargeMultiplier");
03996          goto aocmessage_cleanup;
03997       }
03998    }
03999 
04000    /* create decoded object and start setting values */
04001    if (!(decoded = ast_aoc_create(_msgtype, _chargetype, 0))) {
04002          astman_send_error(s, m, "Message Creation Failed");
04003          goto aocmessage_cleanup;
04004    }
04005 
04006    if (_msgtype == AST_AOC_D) {
04007       if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype, "subtotal")) {
04008          _totaltype = AST_AOC_SUBTOTAL;
04009       }
04010 
04011       if (ast_strlen_zero(aocbillingid)) {
04012          /* ignore this is optional */
04013       } else if (!strcasecmp(aocbillingid, "Normal")) {
04014          _billingid = AST_AOC_BILLING_NORMAL;
04015       } else if (!strcasecmp(aocbillingid, "ReverseCharge")) {
04016          _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
04017       } else if (!strcasecmp(aocbillingid, "CreditCard")) {
04018          _billingid = AST_AOC_BILLING_CREDIT_CARD;
04019       } else {
04020          astman_send_error(s, m, "Invalid AOC-D AOCBillingId");
04021          goto aocmessage_cleanup;
04022       }
04023    } else {
04024       if (ast_strlen_zero(aocbillingid)) {
04025          /* ignore this is optional */
04026       } else if (!strcasecmp(aocbillingid, "Normal")) {
04027          _billingid = AST_AOC_BILLING_NORMAL;
04028       } else if (!strcasecmp(aocbillingid, "ReverseCharge")) {
04029          _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
04030       } else if (!strcasecmp(aocbillingid, "CreditCard")) {
04031          _billingid = AST_AOC_BILLING_CREDIT_CARD;
04032       } else if (!strcasecmp(aocbillingid, "CallFwdUnconditional")) {
04033          _billingid = AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL;
04034       } else if (!strcasecmp(aocbillingid, "CallFwdBusy")) {
04035          _billingid = AST_AOC_BILLING_CALL_FWD_BUSY;
04036       } else if (!strcasecmp(aocbillingid, "CallFwdNoReply")) {
04037          _billingid = AST_AOC_BILLING_CALL_FWD_NO_REPLY;
04038       } else if (!strcasecmp(aocbillingid, "CallDeflection")) {
04039          _billingid = AST_AOC_BILLING_CALL_DEFLECTION;
04040       } else if (!strcasecmp(aocbillingid, "CallTransfer")) {
04041          _billingid = AST_AOC_BILLING_CALL_TRANSFER;
04042       } else {
04043          astman_send_error(s, m, "Invalid AOC-E AOCBillingId");
04044          goto aocmessage_cleanup;
04045       }
04046 
04047       if (!ast_strlen_zero(association_id) && (sscanf(association_id, "%30d", &_association_id) != 1)) {
04048          astman_send_error(s, m, "Invalid ChargingAssociationId");
04049          goto aocmessage_cleanup;
04050       }
04051       if (!ast_strlen_zero(association_plan) && (sscanf(association_plan, "%30u", &_association_plan) != 1)) {
04052          astman_send_error(s, m, "Invalid ChargingAssociationPlan");
04053          goto aocmessage_cleanup;
04054       }
04055 
04056       if (_association_id) {
04057          ast_aoc_set_association_id(decoded, _association_id);
04058       } else if (!ast_strlen_zero(association_num)) {
04059          ast_aoc_set_association_number(decoded, association_num, _association_plan);
04060       }
04061    }
04062 
04063    if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
04064       ast_aoc_set_currency_info(decoded, _currencyamount, _mult, ast_strlen_zero(currencyname) ? NULL : currencyname);
04065    } else if (_chargetype == AST_AOC_CHARGE_UNIT) {
04066       struct ast_aoc_unit_entry entry;
04067       int i;
04068 
04069       /* multiple unit entries are possible, lets get them all */
04070       for (i = 0; i < 32; i++) {
04071          if (aocmessage_get_unit_entry(m, &entry, i)) {
04072             break; /* that's the end then */
04073          }
04074 
04075          ast_aoc_add_unit_entry(decoded, entry.valid_amount, entry.amount, entry.valid_type, entry.type);
04076       }
04077 
04078       /* at least one unit entry is required */
04079       if (!i) {
04080          astman_send_error(s, m, "Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit");
04081          goto aocmessage_cleanup;
04082       }
04083 
04084    }
04085 
04086    ast_aoc_set_billing_id(decoded, _billingid);
04087    ast_aoc_set_total_type(decoded, _totaltype);
04088 
04089 
04090    if ((encoded = ast_aoc_encode(decoded, &encoded_size, NULL)) && !ast_indicate_data(chan, AST_CONTROL_AOC, encoded, encoded_size)) {
04091       astman_send_ack(s, m, "AOC Message successfully queued on channel");
04092    } else {
04093       astman_send_error(s, m, "Error encoding AOC message, could not queue onto channel");
04094    }
04095 
04096 aocmessage_cleanup:
04097 
04098    ast_aoc_destroy_decoded(decoded);
04099    ast_aoc_destroy_encoded(encoded);
04100 
04101    if (chan) {
04102       chan = ast_channel_unref(chan);
04103    }
04104    return 0;
04105 }

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

Definition at line 3630 of file manager.c.

References ast_channel_get_by_name(), ast_channel_unref, ast_find_call_feature(), AST_FRAME_DTMF, ast_queue_frame(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), context, ast_call_feature::exten, exten, and pbx_builtin_setvar_helper().

Referenced by __init_manager().

03631 {
03632    const char *name = astman_get_header(m, "Channel");
03633    const char *exten = astman_get_header(m, "Exten");
03634    const char *context = astman_get_header(m, "Context");
03635    struct ast_channel *chan = NULL;
03636    struct ast_call_feature *atxfer_feature = NULL;
03637    char *feature_code = NULL;
03638 
03639    if (ast_strlen_zero(name)) {
03640       astman_send_error(s, m, "No channel specified");
03641       return 0;
03642    }
03643    if (ast_strlen_zero(exten)) {
03644       astman_send_error(s, m, "No extension specified");
03645       return 0;
03646    }
03647 
03648    if (!(atxfer_feature = ast_find_call_feature("atxfer"))) {
03649       astman_send_error(s, m, "No attended transfer feature found");
03650       return 0;
03651    }
03652 
03653    if (!(chan = ast_channel_get_by_name(name))) {
03654       astman_send_error(s, m, "Channel specified does not exist");
03655       return 0;
03656    }
03657 
03658    if (!ast_strlen_zero(context)) {
03659       pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context);
03660    }
03661 
03662    for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) {
03663       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code };
03664       ast_queue_frame(chan, &f);
03665    }
03666 
03667    for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) {
03668       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code };
03669       ast_queue_frame(chan, &f);
03670    }
03671 
03672    chan = ast_channel_unref(chan);
03673 
03674    astman_send_ack(s, m, "Atxfer successfully queued");
03675 
03676    return 0;
03677 }

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

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

03133 {
03134    const char *authtype = astman_get_header(m, "AuthType");
03135 
03136    if (!strcasecmp(authtype, "MD5")) {
03137       if (ast_strlen_zero(s->session->challenge)) {
03138          snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
03139       }
03140       mansession_lock(s);
03141       astman_start_ack(s, m);
03142       astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
03143       mansession_unlock(s);
03144    } else {
03145       astman_send_error(s, m, "Must specify AuthType");
03146    }
03147    return 0;
03148 }

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

Manager command "command" - execute CLI command.

Definition at line 3715 of file manager.c.

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

Referenced by __init_manager().

03716 {
03717    const char *cmd = astman_get_header(m, "Command");
03718    const char *id = astman_get_header(m, "ActionID");
03719    char *buf = NULL, *final_buf = NULL;
03720    char template[] = "/tmp/ast-ami-XXXXXX";  /* template for temporary file */
03721    int fd;
03722    off_t l;
03723 
03724    if (ast_strlen_zero(cmd)) {
03725       astman_send_error(s, m, "No command provided");
03726       return 0;
03727    }
03728 
03729    if (check_blacklist(cmd)) {
03730       astman_send_error(s, m, "Command blacklisted");
03731       return 0;
03732    }
03733 
03734    if ((fd = mkstemp(template)) < 0) {
03735       ast_log(AST_LOG_WARNING, "Failed to create temporary file for command: %s\n", strerror(errno));
03736       astman_send_error(s, m, "Command response construction error");
03737       return 0;
03738    }
03739 
03740    astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
03741    if (!ast_strlen_zero(id)) {
03742       astman_append(s, "ActionID: %s\r\n", id);
03743    }
03744    /* FIXME: Wedge a ActionID response in here, waiting for later changes */
03745    ast_cli_command(fd, cmd);  /* XXX need to change this to use a FILE * */
03746    /* Determine number of characters available */
03747    if ((l = lseek(fd, 0, SEEK_END)) < 0) {
03748       ast_log(LOG_WARNING, "Failed to determine number of characters for command: %s\n", strerror(errno));
03749       goto action_command_cleanup;
03750    }
03751 
03752    /* This has a potential to overflow the stack.  Hence, use the heap. */
03753    buf = ast_malloc(l + 1);
03754    final_buf = ast_malloc(l + 1);
03755 
03756    if (!buf || !final_buf) {
03757       ast_log(LOG_WARNING, "Failed to allocate memory for temporary buffer\n");
03758       goto action_command_cleanup;
03759    }
03760 
03761    if (lseek(fd, 0, SEEK_SET) < 0) {
03762       ast_log(LOG_WARNING, "Failed to set position on temporary file for command: %s\n", strerror(errno));
03763       goto action_command_cleanup;
03764    }
03765 
03766    if (read(fd, buf, l) < 0) {
03767       ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
03768       goto action_command_cleanup;
03769    }
03770 
03771    buf[l] = '\0';
03772    term_strip(final_buf, buf, l);
03773    final_buf[l] = '\0';
03774    astman_append(s, "%s", final_buf);
03775 
03776 action_command_cleanup:
03777 
03778    close(fd);
03779    unlink(template);
03780    astman_append(s, "--END COMMAND--\r\n\r\n");
03781 
03782    ast_free(buf);
03783    ast_free(final_buf);
03784 
03785    return 0;
03786 }

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

Show PBX core settings information.

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

04452 {
04453    const char *actionid = astman_get_header(m, "ActionID");
04454    char idText[150];
04455 
04456    if (!ast_strlen_zero(actionid)) {
04457       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
04458    } else {
04459       idText[0] = '\0';
04460    }
04461 
04462    astman_append(s, "Response: Success\r\n"
04463          "%s"
04464          "AMIversion: %s\r\n"
04465          "AsteriskVersion: %s\r\n"
04466          "SystemName: %s\r\n"
04467          "CoreMaxCalls: %d\r\n"
04468          "CoreMaxLoadAvg: %f\r\n"
04469          "CoreRunUser: %s\r\n"
04470          "CoreRunGroup: %s\r\n"
04471          "CoreMaxFilehandles: %d\r\n"
04472          "CoreRealTimeEnabled: %s\r\n"
04473          "CoreCDRenabled: %s\r\n"
04474          "CoreHTTPenabled: %s\r\n"
04475          "\r\n",
04476          idText,
04477          AMI_VERSION,
04478          ast_get_version(),
04479          ast_config_AST_SYSTEM_NAME,
04480          option_maxcalls,
04481          option_maxload,
04482          ast_config_AST_RUN_USER,
04483          ast_config_AST_RUN_GROUP,
04484          option_maxfiles,
04485          AST_CLI_YESNO(ast_realtime_enabled()),
04486          AST_CLI_YESNO(check_cdr_enabled()),
04487          AST_CLI_YESNO(check_webmanager_enabled())
04488          );
04489    return 0;
04490 }

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

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

Referenced by __init_manager().

04561 {
04562    const char *actionid = astman_get_header(m, "ActionID");
04563    char idText[256];
04564    struct ast_channel *c = NULL;
04565    int numchans = 0;
04566    int duration, durh, durm, durs;
04567    struct ast_channel_iterator *iter;
04568 
04569    if (!ast_strlen_zero(actionid)) {
04570       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
04571    } else {
04572       idText[0] = '\0';
04573    }
04574 
04575    if (!(iter = ast_channel_iterator_all_new())) {
04576       astman_send_error(s, m, "Memory Allocation Failure");
04577       return 1;
04578    }
04579 
04580    astman_send_listack(s, m, "Channels will follow", "start");
04581 
04582    for (; (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) {
04583       struct ast_channel *bc;
04584       char durbuf[10] = "";
04585 
04586       ast_channel_lock(c);
04587 
04588       bc = ast_bridged_channel(c);
04589       if (c->cdr && !ast_tvzero(c->cdr->start)) {
04590          duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
04591          durh = duration / 3600;
04592          durm = (duration % 3600) / 60;
04593          durs = duration % 60;
04594          snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
04595       }
04596 
04597       astman_append(s,
04598          "Event: CoreShowChannel\r\n"
04599          "%s"
04600          "Channel: %s\r\n"
04601          "UniqueID: %s\r\n"
04602          "Context: %s\r\n"
04603          "Extension: %s\r\n"
04604          "Priority: %d\r\n"
04605          "ChannelState: %d\r\n"
04606          "ChannelStateDesc: %s\r\n"
04607          "Application: %s\r\n"
04608          "ApplicationData: %s\r\n"
04609          "CallerIDnum: %s\r\n"
04610          "CallerIDname: %s\r\n"
04611          "ConnectedLineNum: %s\r\n"
04612          "ConnectedLineName: %s\r\n"
04613          "Duration: %s\r\n"
04614          "AccountCode: %s\r\n"
04615          "BridgedChannel: %s\r\n"
04616          "BridgedUniqueID: %s\r\n"
04617          "\r\n", idText, c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state,
04618          ast_state2str(c->_state), c->appl ? c->appl : "", c->data ? S_OR(c->data, "") : "",
04619          S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""),
04620          S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""),
04621          S_COR(c->connected.id.number.valid, c->connected.id.number.str, ""),
04622          S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""),
04623          durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : "");
04624 
04625       ast_channel_unlock(c);
04626 
04627       numchans++;
04628    }
04629 
04630    astman_append(s,
04631       "Event: CoreShowChannelsComplete\r\n"
04632       "EventList: Complete\r\n"
04633       "ListItems: %d\r\n"
04634       "%s"
04635       "\r\n", numchans, idText);
04636 
04637    ast_channel_iterator_destroy(iter);
04638 
04639    return 0;
04640 }

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

Show PBX core status information.

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

04494 {
04495    const char *actionid = astman_get_header(m, "ActionID");
04496    char idText[150];
04497    char startuptime[150], startupdate[150];
04498    char reloadtime[150], reloaddate[150];
04499    struct ast_tm tm;
04500 
04501    if (!ast_strlen_zero(actionid)) {
04502       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
04503    } else {
04504       idText[0] = '\0';
04505    }
04506 
04507    ast_localtime(&ast_startuptime, &tm, NULL);
04508    ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm);
04509    ast_strftime(startupdate, sizeof(startupdate), "%Y-%m-%d", &tm);
04510    ast_localtime(&ast_lastreloadtime, &tm, NULL);
04511    ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm);
04512    ast_strftime(reloaddate, sizeof(reloaddate), "%Y-%m-%d", &tm);
04513 
04514    astman_append(s, "Response: Success\r\n"
04515          "%s"
04516          "CoreStartupDate: %s\r\n"
04517          "CoreStartupTime: %s\r\n"
04518          "CoreReloadDate: %s\r\n"
04519          "CoreReloadTime: %s\r\n"
04520          "CoreCurrentCalls: %d\r\n"
04521          "\r\n",
04522          idText,
04523          startupdate,
04524          startuptime,
04525          reloaddate,
04526          reloadtime,
04527          ast_active_channels()
04528          );
04529    return 0;
04530 }

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

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

02909 {
02910    int fd;
02911    const char *fn = astman_get_header(m, "Filename");
02912    struct ast_str *filepath = ast_str_alloca(PATH_MAX);
02913    ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR);
02914    ast_str_append(&filepath, 0, "%s", fn);
02915 
02916    if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
02917       close(fd);
02918       astman_send_ack(s, m, "New configuration file created successfully");
02919    } else {
02920       astman_send_error(s, m, strerror(errno));
02921    }
02922 
02923    return 0;
02924 }

static void action_destroy ( void *  obj  )  [static]

Definition at line 5431 of file manager.c.

References ast_string_field_free_memory.

Referenced by ast_manager_register2().

05432 {
05433    struct manager_action *doomed = obj;
05434 
05435    if (doomed->synopsis) {
05436       /* The string fields were initialized. */
05437       ast_string_field_free_memory(doomed);
05438    }
05439 }

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

Definition at line 3051 of file manager.c.

References ARRAY_LEN, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), permalias::num, perms, and set_eventmask().

Referenced by __init_manager().

03052 {
03053    const char *mask = astman_get_header(m, "EventMask");
03054    int res, x;
03055    const char *id = astman_get_header(m, "ActionID");
03056    char id_text[256];
03057 
03058    if (!ast_strlen_zero(id)) {
03059       snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
03060    } else {
03061       id_text[0] = '\0';
03062    }
03063 
03064    res = set_eventmask(s, mask);
03065    if (broken_events_action) {
03066       /* if this option is set we should not return a response on
03067        * error, or when all events are set */
03068 
03069       if (res > 0) {
03070          for (x = 0; x < ARRAY_LEN(perms); x++) {
03071             if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) {
03072                return 0;
03073             }
03074          }
03075          astman_append(s, "Response: Success\r\n%s"
03076                 "Events: On\r\n\r\n", id_text);
03077       } else if (res == 0)
03078          astman_append(s, "Response: Success\r\n%s"
03079                 "Events: Off\r\n\r\n", id_text);
03080       return 0;
03081    }
03082 
03083    if (res > 0)
03084       astman_append(s, "Response: Success\r\n%s"
03085              "Events: On\r\n\r\n", id_text);
03086    else if (res == 0)
03087       astman_append(s, "Response: Success\r\n%s"
03088              "Events: Off\r\n\r\n", id_text);
03089    else
03090       astman_send_error(s, m, "Invalid event mask");
03091 
03092    return 0;
03093 }

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

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

04290 {
04291    const char *exten = astman_get_header(m, "Exten");
04292    const char *context = astman_get_header(m, "Context");
04293    char hint[256] = "";
04294    int status;
04295    if (ast_strlen_zero(exten)) {
04296       astman_send_error(s, m, "Extension not specified");
04297       return 0;
04298    }
04299    if (ast_strlen_zero(context)) {
04300       context = "default";
04301    }
04302    status = ast_extension_state(NULL, context, exten);
04303    ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
04304    astman_start_ack(s, m);
04305    astman_append(s,   "Message: Extension Status\r\n"
04306             "Exten: %s\r\n"
04307             "Context: %s\r\n"
04308             "Hint: %s\r\n"
04309             "Status: %d\r\n\r\n",
04310             exten, context, hint, status);
04311    return 0;
04312 }

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

Definition at line 1073 of file manager.c.

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

Referenced by ast_hook_send_action(), and process_message().

01074 {
01075    struct manager_action *act;
01076 
01077    AST_RWLIST_RDLOCK(&actions);
01078    AST_RWLIST_TRAVERSE(&actions, act, list) {
01079       if (!strcasecmp(name, act->action)) {
01080          ao2_t_ref(act, +1, "found action object");
01081          break;
01082       }
01083    }
01084    AST_RWLIST_UNLOCK(&actions);
01085 
01086    return act;
01087 }

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

Definition at line 2526 of file manager.c.

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

Referenced by __init_manager().

02527 {
02528    struct ast_config *cfg;
02529    const char *fn = astman_get_header(m, "Filename");
02530    const char *category = astman_get_header(m, "Category");
02531    int catcount = 0;
02532    int lineno = 0;
02533    char *cur_category = NULL;
02534    struct ast_variable *v;
02535    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02536 
02537    if (ast_strlen_zero(fn)) {
02538       astman_send_error(s, m, "Filename not specified");
02539       return 0;
02540    }
02541    cfg = ast_config_load2(fn, "manager", config_flags);
02542    if (cfg == CONFIG_STATUS_FILEMISSING) {
02543       astman_send_error(s, m, "Config file not found");
02544       return 0;
02545    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02546       astman_send_error(s, m, "Config file has invalid format");
02547       return 0;
02548    }
02549 
02550    astman_start_ack(s, m);
02551    while ((cur_category = ast_category_browse(cfg, cur_category))) {
02552       if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) {
02553          lineno = 0;
02554          astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category);
02555          for (v = ast_variable_browse(cfg, cur_category); v; v = v->next) {
02556             astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value);
02557          }
02558          catcount++;
02559       }
02560    }
02561    if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
02562       astman_append(s, "No categories found\r\n");
02563    }
02564    ast_config_destroy(cfg);
02565    astman_append(s, "\r\n");
02566 
02567    return 0;
02568 }

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

Definition at line 2636 of file manager.c.

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

Referenced by __init_manager().

02637 {
02638    struct ast_config *cfg;
02639    const char *fn = astman_get_header(m, "Filename");
02640    char *category = NULL;
02641    struct ast_variable *v;
02642    int comma1 = 0;
02643    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02644 
02645    if (ast_strlen_zero(fn)) {
02646       astman_send_error(s, m, "Filename not specified");
02647       return 0;
02648    }
02649 
02650    if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
02651       astman_send_error(s, m, "Config file not found");
02652       return 0;
02653    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02654       astman_send_error(s, m, "Config file has invalid format");
02655       return 0;
02656    }
02657 
02658    astman_start_ack(s, m);
02659    astman_append(s, "JSON: {");
02660    while ((category = ast_category_browse(cfg, category))) {
02661       int comma2 = 0;
02662 
02663       astman_append(s, "%s\"", comma1 ? "," : "");
02664       astman_append_json(s, category);
02665       astman_append(s, "\":[");
02666       comma1 = 1;
02667       for (v = ast_variable_browse(cfg, category); v; v = v->next) {
02668          astman_append(s, "%s\"", comma2 ? "," : "");
02669          astman_append_json(s, v->name);
02670          astman_append(s, "\":\"");
02671          astman_append_json(s, v->value);
02672          astman_append(s, "\"");
02673          comma2 = 1;
02674       }
02675       astman_append(s, "]");
02676    }
02677    astman_append(s, "}\r\n\r\n");
02678 
02679    ast_config_destroy(cfg);
02680 
02681    return 0;
02682 }

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

Definition at line 3226 of file manager.c.

References ast_channel_get_by_name(), ast_channel_unref, ast_dummy_channel_alloc, ast_func_read(), ast_log(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), function_capable_string_allowed_with_auths(), LOG_ERROR, pbx_retrieve_variable(), S_OR, mansession::session, and mansession_session::writeperm.

Referenced by __init_manager().

03227 {
03228    struct ast_channel *c = NULL;
03229    const char *name = astman_get_header(m, "Channel");
03230    const char *varname = astman_get_header(m, "Variable");
03231    char *varval;
03232    char workspace[1024];
03233 
03234    if (ast_strlen_zero(varname)) {
03235       astman_send_error(s, m, "No variable specified");
03236       return 0;
03237    }
03238 
03239    /* We don't want users with insufficient permissions using certain functions. */
03240    if (!(function_capable_string_allowed_with_auths(varname, s->session->writeperm))) {
03241       astman_send_error(s, m, "GetVar Access Forbidden: Variable");
03242       return 0;
03243    }
03244 
03245    if (!ast_strlen_zero(name)) {
03246       if (!(c = ast_channel_get_by_name(name))) {
03247          astman_send_error(s, m, "No such channel");
03248          return 0;
03249       }
03250    }
03251 
03252    workspace[0] = '\0';
03253    if (varname[strlen(varname) - 1] == ')') {
03254       if (!c) {
03255          c = ast_dummy_channel_alloc();
03256          if (c) {
03257             ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
03258          } else
03259             ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03260       } else {
03261          ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
03262       }
03263       varval = workspace;
03264    } else {
03265       pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
03266    }
03267 
03268    if (c) {
03269       c = ast_channel_unref(c);
03270    }
03271 
03272    astman_start_ack(s, m);
03273    astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, S_OR(varval, ""));
03274 
03275    return 0;
03276 }

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

Definition at line 3150 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(), ast_channel::hangupcause, and LOG_NOTICE.

Referenced by __init_manager().

03151 {
03152    struct ast_channel *c = NULL;
03153    int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */
03154    const char *name = astman_get_header(m, "Channel");
03155    const char *cause = astman_get_header(m, "Cause");
03156 
03157    if (ast_strlen_zero(name)) {
03158       astman_send_error(s, m, "No channel specified");
03159       return 0;
03160    }
03161 
03162    if (!ast_strlen_zero(cause)) {
03163       char *endptr;
03164       causecode = strtol(cause, &endptr, 10);
03165       if (causecode < 0 || causecode > 127 || *endptr != '\0') {
03166          ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause);
03167          /* keep going, better to hangup without cause than to not hang up at all */
03168          causecode = 0; /* do not set channel's hangupcause */
03169       }
03170    }
03171 
03172    if (!(c = ast_channel_get_by_name(name))) {
03173       astman_send_error(s, m, "No such channel");
03174       return 0;
03175    }
03176 
03177    ast_channel_lock(c);
03178    if (causecode > 0) {
03179       ast_debug(1, "Setting hangupcause of channel %s to %d (is %d now)\n",
03180             c->name, causecode, c->hangupcause);
03181       c->hangupcause = causecode;
03182    }
03183    ast_softhangup_nolock(c, AST_SOFTHANGUP_EXPLICIT);
03184    ast_channel_unlock(c);
03185 
03186    c = ast_channel_unref(c);
03187 
03188    astman_send_ack(s, m, "Channel Hungup");
03189 
03190    return 0;
03191 }

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

Definition at line 2570 of file manager.c.

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

Referenced by __init_manager().

02571 {
02572    struct ast_config *cfg;
02573    const char *fn = astman_get_header(m, "Filename");
02574    char *category = NULL;
02575    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02576    int catcount = 0;
02577 
02578    if (ast_strlen_zero(fn)) {
02579       astman_send_error(s, m, "Filename not specified");
02580       return 0;
02581    }
02582    if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
02583       astman_send_error(s, m, "Config file not found");
02584       return 0;
02585    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02586       astman_send_error(s, m, "Config file has invalid format");
02587       return 0;
02588    }
02589    astman_start_ack(s, m);
02590    while ((category = ast_category_browse(cfg, category))) {
02591       astman_append(s, "Category-%06d: %s\r\n", catcount, category);
02592       catcount++;
02593    }
02594    if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
02595       astman_append(s, "Error: no categories found\r\n");
02596    }
02597    ast_config_destroy(cfg);
02598    astman_append(s, "\r\n");
02599 
02600    return 0;
02601 }

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

Definition at line 3032 of file manager.c.

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

Referenced by __init_manager().

03033 {
03034    struct manager_action *cur;
03035    struct ast_str *temp = ast_str_alloca(256);
03036 
03037    astman_start_ack(s, m);
03038    AST_RWLIST_RDLOCK(&actions);
03039    AST_RWLIST_TRAVERSE(&actions, cur, list) {
03040       if ((s->session->writeperm & cur->authority) || cur->authority == 0) {
03041          astman_append(s, "%s: %s (Priv: %s)\r\n",
03042             cur->action, cur->synopsis, authority_to_str(cur->authority, &temp));
03043       }
03044    }
03045    AST_RWLIST_UNLOCK(&actions);
03046    astman_append(s, "\r\n");
03047 
03048    return 0;
03049 }

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

Definition at line 3101 of file manager.c.

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

Referenced by __init_manager().

03102 {
03103 
03104    /* still authenticated - don't process again */
03105    if (s->session->authenticated) {
03106       astman_send_ack(s, m, "Already authenticated");
03107       return 0;
03108    }
03109 
03110    if (authenticate(s, m)) {
03111       sleep(1);
03112       astman_send_error(s, m, "Authentication failed");
03113       return -1;
03114    }
03115    s->session->authenticated = 1;
03116    ast_atomic_fetchadd_int(&unauth_sessions, -1);
03117    if (manager_displayconnects(s->session)) {
03118       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));
03119    }
03120    astman_send_ack(s, m, "Authentication accepted");
03121    if ((s->session->send_events & EVENT_FLAG_SYSTEM)
03122       && ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
03123       struct ast_str *auth = ast_str_alloca(80);
03124       const char *cat_str = authority_to_str(EVENT_FLAG_SYSTEM, &auth);
03125       astman_append(s, "Event: FullyBooted\r\n"
03126          "Privilege: %s\r\n"
03127          "Status: Fully Booted\r\n\r\n", cat_str);
03128    }
03129    return 0;
03130 }

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

Definition at line 3095 of file manager.c.

References astman_send_response().

Referenced by __init_manager().

03096 {
03097    astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
03098    return -1;
03099 }

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

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

04269 {
04270    const char *mailbox = astman_get_header(m, "Mailbox");
04271    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;;
04272 
04273    if (ast_strlen_zero(mailbox)) {
04274       astman_send_error(s, m, "Mailbox not specified");
04275       return 0;
04276    }
04277    ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs);
04278    astman_start_ack(s, m);
04279    astman_append(s,   "Message: Mailbox Message Count\r\n"
04280             "Mailbox: %s\r\n"
04281             "UrgMessages: %d\r\n"
04282             "NewMessages: %d\r\n"
04283             "OldMessages: %d\r\n"
04284             "\r\n",
04285             mailbox, urgentmsgs, newmsgs, oldmsgs);
04286    return 0;
04287 }

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

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

04252 {
04253    const char *mailbox = astman_get_header(m, "Mailbox");
04254    int ret;
04255 
04256    if (ast_strlen_zero(mailbox)) {
04257       astman_send_error(s, m, "Mailbox not specified");
04258       return 0;
04259    }
04260    ret = ast_app_has_voicemail(mailbox, NULL);
04261    astman_start_ack(s, m);
04262    astman_append(s, "Message: Mailbox Status\r\n"
04263           "Mailbox: %s\r\n"
04264           "Waiting: %d\r\n\r\n", mailbox, ret);
04265    return 0;
04266 }

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

Definition at line 4107 of file manager.c.

References app, ast_callerid_parse(), ast_calloc, ast_copy_string(), ast_findlabel_extension(), AST_FORMAT_SLINEAR, ast_free, ast_parse_allow_disallow(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_pthread_create_detached, ast_shrink_phone_number(), ast_string_field_build, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_true(), ast_variables_destroy(), astman_get_header(), astman_get_variables(), astman_send_ack(), astman_send_error(), cid_name, cid_num, context, ast_frame::data, destroy_fast_originate_helper(), EVENT_FLAG_SYSTEM, exten, fast_originate(), fast_originate_helper::format, fast_originate_helper::priority, mansession::session, fast_originate_helper::timeout, fast_originate_helper::vars, and mansession_session::writeperm.

Referenced by __init_manager().

04108 {
04109    const char *name = astman_get_header(m, "Channel");
04110    const char *exten = astman_get_header(m, "Exten");
04111    const char *context = astman_get_header(m, "Context");
04112    const char *priority = astman_get_header(m, "Priority");
04113    const char *timeout = astman_get_header(m, "Timeout");
04114    const char *callerid = astman_get_header(m, "CallerID");
04115    const char *account = astman_get_header(m, "Account");
04116    const char *app = astman_get_header(m, "Application");
04117    const char *appdata = astman_get_header(m, "Data");
04118    const char *async = astman_get_header(m, "Async");
04119    const char *id = astman_get_header(m, "ActionID");
04120    const char *codecs = astman_get_header(m, "Codecs");
04121    struct ast_variable *vars;
04122    char *tech, *data;
04123    char *l = NULL, *n = NULL;
04124    int pi = 0;
04125    int res;
04126    int to = 30000;
04127    int reason = 0;
04128    char tmp[256];
04129    char tmp2[256];
04130    format_t format = AST_FORMAT_SLINEAR;
04131 
04132    pthread_t th;
04133    if (ast_strlen_zero(name)) {
04134       astman_send_error(s, m, "Channel not specified");
04135       return 0;
04136    }
04137    if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) {
04138       if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
04139          astman_send_error(s, m, "Invalid priority");
04140          return 0;
04141       }
04142    }
04143    if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) {
04144       astman_send_error(s, m, "Invalid timeout");
04145       return 0;
04146    }
04147    ast_copy_string(tmp, name, sizeof(tmp));
04148    tech = tmp;
04149    data = strchr(tmp, '/');
04150    if (!data) {
04151       astman_send_error(s, m, "Invalid channel");
04152       return 0;
04153    }
04154    *data++ = '\0';
04155    ast_copy_string(tmp2, callerid, sizeof(tmp2));
04156    ast_callerid_parse(tmp2, &n, &l);
04157    if (n) {
04158       if (ast_strlen_zero(n)) {
04159          n = NULL;
04160       }
04161    }
04162    if (l) {
04163       ast_shrink_phone_number(l);
04164       if (ast_strlen_zero(l)) {
04165          l = NULL;
04166       }
04167    }
04168    if (!ast_strlen_zero(codecs)) {
04169       format = 0;
04170       ast_parse_allow_disallow(NULL, &format, codecs, 1);
04171    }
04172    if (!ast_strlen_zero(app) && s->session) {
04173       int bad_appdata = 0;
04174       /* To run the System application (or anything else that goes to
04175        * shell), you must have the additional System privilege */
04176       if (!(s->session->writeperm & EVENT_FLAG_SYSTEM)
04177          && (
04178             strcasestr(app, "system") ||      /* System(rm -rf /)
04179                                                  TrySystem(rm -rf /)       */
04180             strcasestr(app, "exec") ||        /* Exec(System(rm -rf /))
04181                                                  TryExec(System(rm -rf /)) */
04182             strcasestr(app, "agi") ||         /* AGI(/bin/rm,-rf /)
04183                                                  EAGI(/bin/rm,-rf /)       */
04184             strcasestr(app, "mixmonitor") ||  /* MixMonitor(blah,,rm -rf)  */
04185             strcasestr(app, "externalivr") || /* ExternalIVR(rm -rf)       */
04186             (strstr(appdata, "SHELL") && (bad_appdata = 1)) ||       /* NoOp(${SHELL(rm -rf /)})  */
04187             (strstr(appdata, "EVAL") && (bad_appdata = 1))           /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
04188             )) {
04189          char error_buf[64];
04190          snprintf(error_buf, sizeof(error_buf), "Originate Access Forbidden: %s", bad_appdata ? "Data" : "Application");
04191          astman_send_error(s, m, error_buf);
04192          return 0;
04193       }
04194    }
04195    /* Allocate requested channel variables */
04196    vars = astman_get_variables(m);
04197 
04198    if (ast_true(async)) {
04199       struct fast_originate_helper *fast;
04200 
04201       fast = ast_calloc(1, sizeof(*fast));
04202       if (!fast || ast_string_field_init(fast, 252)) {
04203          ast_free(fast);
04204          ast_variables_destroy(vars);
04205          res = -1;
04206       } else {
04207          if (!ast_strlen_zero(id)) {
04208             ast_string_field_build(fast, idtext, "ActionID: %s\r\n", id);
04209          }
04210          ast_string_field_set(fast, tech, tech);
04211          ast_string_field_set(fast, data, data);
04212          ast_string_field_set(fast, app, app);
04213          ast_string_field_set(fast, appdata, appdata);
04214          ast_string_field_set(fast, cid_num, l);
04215          ast_string_field_set(fast, cid_name, n);
04216          ast_string_field_set(fast, context, context);
04217          ast_string_field_set(fast, exten, exten);
04218          ast_string_field_set(fast, account, account);
04219          fast->vars = vars;
04220          fast->format = format;
04221          fast->timeout = to;
04222          fast->priority = pi;
04223          if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) {
04224             destroy_fast_originate_helper(fast);
04225             res = -1;
04226          } else {
04227             res = 0;
04228          }
04229       }
04230    } else if (!ast_strlen_zero(app)) {
04231       res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
04232       /* Any vars memory was passed to ast_pbx_outgoing_app(). */
04233    } else {
04234       if (exten && context && pi) {
04235          res = ast_pbx_outgoing_exten(tech, format, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
04236          /* Any vars memory was passed to ast_pbx_outgoing_exten(). */
04237       } else {
04238          astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
04239          ast_variables_destroy(vars);
04240          return 0;
04241       }
04242    }
04243    if (!res) {
04244       astman_send_ack(s, m, "Originate successfully queued");
04245    } else {
04246       astman_send_error(s, m, "Originate failed");
04247    }
04248    return 0;
04249 }

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

Definition at line 2508 of file manager.c.

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

Referenced by __init_manager().

02509 {
02510    const char *actionid = astman_get_header(m, "ActionID");
02511    struct timeval now = ast_tvnow();
02512 
02513    astman_append(s, "Response: Success\r\n");
02514    if (!ast_strlen_zero(actionid)){
02515       astman_append(s, "ActionID: %s\r\n", actionid);
02516    }
02517    astman_append(
02518       s,
02519       "Ping: Pong\r\n"
02520       "Timestamp: %ld.%06lu\r\n"
02521       "\r\n",
02522       (long) now.tv_sec, (unsigned long) now.tv_usec);
02523    return 0;
02524 }

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

action_redirect: The redirect manager command

Definition at line 3477 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_clear_flag, ast_findlabel_extension(), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT, AST_FLAG_BRIDGE_HANGUP_DONT, ast_set_flag, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), context, exten, ast_channel::pbx, and ast_channel::priority.

Referenced by __init_manager().

03478 {
03479    char buf[256];
03480    const char *name = astman_get_header(m, "Channel");
03481    const char *name2 = astman_get_header(m, "ExtraChannel");
03482    const char *exten = astman_get_header(m, "Exten");
03483    const char *exten2 = astman_get_header(m, "ExtraExten");
03484    const char *context = astman_get_header(m, "Context");
03485    const char *context2 = astman_get_header(m, "ExtraContext");
03486    const char *priority = astman_get_header(m, "Priority");
03487    const char *priority2 = astman_get_header(m, "ExtraPriority");
03488    struct ast_channel *chan;
03489    struct ast_channel *chan2;
03490    int pi = 0;
03491    int pi2 = 0;
03492    int res;
03493 
03494    if (ast_strlen_zero(name)) {
03495       astman_send_error(s, m, "Channel not specified");
03496       return 0;
03497    }
03498 
03499    if (ast_strlen_zero(context)) {
03500       astman_send_error(s, m, "Context not specified");
03501       return 0;
03502    }
03503    if (ast_strlen_zero(exten)) {
03504       astman_send_error(s, m, "Exten not specified");
03505       return 0;
03506    }
03507    if (ast_strlen_zero(priority)) {
03508       astman_send_error(s, m, "Priority not specified");
03509       return 0;
03510    }
03511    if (sscanf(priority, "%30d", &pi) != 1) {
03512       pi = ast_findlabel_extension(NULL, context, exten, priority, NULL);
03513    }
03514    if (pi < 1) {
03515       astman_send_error(s, m, "Priority is invalid");
03516       return 0;
03517    }
03518 
03519    if (!ast_strlen_zero(name2) && !ast_strlen_zero(context2)) {
03520       /* We have an ExtraChannel and an ExtraContext */
03521       if (ast_strlen_zero(exten2)) {
03522          astman_send_error(s, m, "ExtraExten not specified");
03523          return 0;
03524       }
03525       if (ast_strlen_zero(priority2)) {
03526          astman_send_error(s, m, "ExtraPriority not specified");
03527          return 0;
03528       }
03529       if (sscanf(priority2, "%30d", &pi2) != 1) {
03530          pi2 = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL);
03531       }
03532       if (pi2 < 1) {
03533          astman_send_error(s, m, "ExtraPriority is invalid");
03534          return 0;
03535       }
03536    }
03537 
03538    chan = ast_channel_get_by_name(name);
03539    if (!chan) {
03540       snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
03541       astman_send_error(s, m, buf);
03542       return 0;
03543    }
03544    if (ast_check_hangup_locked(chan)) {
03545       astman_send_error(s, m, "Redirect failed, channel not up.");
03546       chan = ast_channel_unref(chan);
03547       return 0;
03548    }
03549 
03550    if (ast_strlen_zero(name2)) {
03551       /* Single channel redirect in progress. */
03552       if (chan->pbx) {
03553          ast_channel_lock(chan);
03554          /* don't let the after-bridge code run the h-exten */
03555          ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT);
03556          ast_channel_unlock(chan);
03557       }
03558       res = ast_async_goto(chan, context, exten, pi);
03559       if (!res) {
03560          astman_send_ack(s, m, "Redirect successful");
03561       } else {
03562          astman_send_error(s, m, "Redirect failed");
03563       }
03564       chan = ast_channel_unref(chan);
03565       return 0;
03566    }
03567 
03568    chan2 = ast_channel_get_by_name(name2);
03569    if (!chan2) {
03570       snprintf(buf, sizeof(buf), "ExtraChannel does not exist: %s", name2);
03571       astman_send_error(s, m, buf);
03572       chan = ast_channel_unref(chan);
03573       return 0;
03574    }
03575    if (ast_check_hangup_locked(chan2)) {
03576       astman_send_error(s, m, "Redirect failed, extra channel not up.");
03577       chan2 = ast_channel_unref(chan2);
03578       chan = ast_channel_unref(chan);
03579       return 0;
03580    }
03581 
03582    /* Dual channel redirect in progress. */
03583    if (chan->pbx) {
03584       ast_channel_lock(chan);
03585       /* don't let the after-bridge code run the h-exten */
03586       ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT
03587          | AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT);
03588       ast_channel_unlock(chan);
03589    }
03590    if (chan2->pbx) {
03591       ast_channel_lock(chan2);
03592       /* don't let the after-bridge code run the h-exten */
03593       ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT
03594          | AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT);
03595       ast_channel_unlock(chan2);
03596    }
03597    res = ast_async_goto(chan, context, exten, pi);
03598    if (!res) {
03599       if (!ast_strlen_zero(context2)) {
03600          res = ast_async_goto(chan2, context2, exten2, pi2);
03601       } else {
03602          res = ast_async_goto(chan2, context, exten, pi);
03603       }
03604       if (!res) {
03605          astman_send_ack(s, m, "Dual Redirect successful");
03606       } else {
03607          astman_send_error(s, m, "Secondary redirect failed");
03608       }
03609    } else {
03610       astman_send_error(s, m, "Redirect failed");
03611    }
03612 
03613    /* Release the bridge wait. */
03614    if (chan->pbx) {
03615       ast_channel_lock(chan);
03616       ast_clear_flag(chan, AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT);
03617       ast_channel_unlock(chan);
03618    }
03619    if (chan2->pbx) {
03620       ast_channel_lock(chan2);
03621       ast_clear_flag(chan2, AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT);
03622       ast_channel_unlock(chan2);
03623    }
03624 
03625    chan2 = ast_channel_unref(chan2);
03626    chan = ast_channel_unref(chan);
03627    return 0;
03628 }

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

Send a reload event.

Definition at line 4533 of file manager.c.

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

Referenced by __init_manager().

04534 {
04535    const char *module = astman_get_header(m, "Module");
04536    int res = ast_module_reload(S_OR(module, NULL));
04537 
04538    switch (res) {
04539    case -1:
04540       astman_send_error(s, m, "A reload is in progress");
04541       break;
04542    case 0:
04543       astman_send_error(s, m, "No such module");
04544       break;
04545    case 1:
04546       astman_send_error(s, m, "Module does not support reload");
04547       break;
04548    case 2:
04549       astman_send_ack(s, m, "Module Reloaded");
04550       break;
04551    default:
04552       astman_send_error(s, m, "An unknown error occurred");
04553       break;
04554    }
04555    return 0;
04556 }

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

Definition at line 3442 of file manager.c.

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

Referenced by __init_manager().

03443 {
03444    struct ast_channel *c = NULL;
03445    const char *name = astman_get_header(m, "Channel");
03446    const char *textmsg = astman_get_header(m, "Message");
03447    int res = 0;
03448 
03449    if (ast_strlen_zero(name)) {
03450       astman_send_error(s, m, "No channel specified");
03451       return 0;
03452    }
03453 
03454    if (ast_strlen_zero(textmsg)) {
03455       astman_send_error(s, m, "No Message specified");
03456       return 0;
03457    }
03458 
03459    if (!(c = ast_channel_get_by_name(name))) {
03460       astman_send_error(s, m, "No such channel");
03461       return 0;
03462    }
03463 
03464    res = ast_sendtext(c, textmsg);
03465    c = ast_channel_unref(c);
03466 
03467    if (res >= 0) {
03468       astman_send_ack(s, m, "Success");
03469    } else {
03470       astman_send_error(s, m, "Failure");
03471    }
03472 
03473    return 0;
03474 }

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

Definition at line 3193 of file manager.c.

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

Referenced by __init_manager().

03194 {
03195    struct ast_channel *c = NULL;
03196    const char *name = astman_get_header(m, "Channel");
03197    const char *varname = astman_get_header(m, "Variable");
03198    const char *varval = astman_get_header(m, "Value");
03199    int res = 0;
03200    
03201    if (ast_strlen_zero(varname)) {
03202       astman_send_error(s, m, "No variable specified");
03203       return 0;
03204    }
03205 
03206    if (!ast_strlen_zero(name)) {
03207       if (!(c = ast_channel_get_by_name(name))) {
03208          astman_send_error(s, m, "No such channel");
03209          return 0;
03210       }
03211    }
03212 
03213    res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
03214 
03215    if (c) {
03216       c = ast_channel_unref(c);
03217    }
03218    if (res == 0) {
03219       astman_send_ack(s, m, "Variable Set"); 
03220    } else {
03221       astman_send_error(s, m, "Variable not set");
03222    }
03223    return 0;
03224 }

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

Manager "status" command to show channels.

Definition at line 3280 of file manager.c.

References ast_channel::_bridge, ast_channel::_state, AST_APP_ARG, ast_channel_get_by_name(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, AST_DECLARE_APP_ARGS, ast_free, ast_func_read(), AST_STANDARD_APP_ARGS, ast_state2str(), ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_reset(), ast_strdupa, ast_strlen_zero(), ast_tvnow(), astman_append(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_channel::bridge, ast_channel::caller, ast_channel::cdr, channels, ast_channel::connected, ast_channel::context, ast_channel::exten, function_capable_string_allowed_with_auths(), ast_party_connected_line::id, ast_party_caller::id, ast_party_id::name, ast_party_id::number, ast_channel::pbx, pbx_retrieve_variable(), ast_channel::priority, S_COR, S_OR, mansession::session, ast_cdr::start, ast_party_name::str, ast_party_number::str, str, ast_party_name::valid, ast_party_number::valid, and mansession_session::writeperm.

Referenced by __init_manager().

03281 {
03282    const char *name = astman_get_header(m, "Channel");
03283    const char *cvariables = astman_get_header(m, "Variables");
03284    char *variables = ast_strdupa(S_OR(cvariables, ""));
03285    struct ast_channel *c;
03286    char bridge[256];
03287    struct timeval now = ast_tvnow();
03288    long elapsed_seconds = 0;
03289    int channels = 0;
03290    int all = ast_strlen_zero(name); /* set if we want all channels */
03291    const char *id = astman_get_header(m, "ActionID");
03292    char idText[256];
03293    AST_DECLARE_APP_ARGS(vars,
03294       AST_APP_ARG(name)[100];
03295    );
03296    struct ast_str *str = ast_str_create(1000);
03297    struct ast_channel_iterator *iter = NULL;
03298 
03299    if (!ast_strlen_zero(id)) {
03300       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
03301    } else {
03302       idText[0] = '\0';
03303    }
03304 
03305    if (!(function_capable_string_allowed_with_auths(variables, s->session->writeperm))) {
03306       astman_send_error(s, m, "Status Access Forbidden: Variables");
03307       return 0;
03308    }
03309 
03310    if (all) {
03311       if (!(iter = ast_channel_iterator_all_new())) {
03312          ast_free(str);
03313          astman_send_error(s, m, "Memory Allocation Failure");
03314          return 1;
03315       }
03316       c = ast_channel_iterator_next(iter);
03317    } else {
03318       if (!(c = ast_channel_get_by_name(name))) {
03319          astman_send_error(s, m, "No such channel");
03320          ast_free(str);
03321          return 0;
03322       }
03323    }
03324 
03325    astman_send_ack(s, m, "Channel status will follow");
03326 
03327    if (!ast_strlen_zero(cvariables)) {
03328       AST_STANDARD_APP_ARGS(vars, variables);
03329    }
03330 
03331    /* if we look by name, we break after the first iteration */
03332    for (; c; c = ast_channel_iterator_next(iter)) {
03333       ast_channel_lock(c);
03334 
03335       if (!ast_strlen_zero(cvariables)) {
03336          int i;
03337          ast_str_reset(str);
03338          for (i = 0; i < vars.argc; i++) {
03339             char valbuf[512], *ret = NULL;
03340 
03341             if (vars.name[i][strlen(vars.name[i]) - 1] == ')') {
03342                if (ast_func_read(c, vars.name[i], valbuf, sizeof(valbuf)) < 0) {
03343                   valbuf[0] = '\0';
03344                }
03345                ret = valbuf;
03346             } else {
03347                pbx_retrieve_variable(c, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL);
03348             }
03349 
03350             ast_str_append(&str, 0, "Variable: %s=%s\r\n", vars.name[i], ret);
03351          }
03352       }
03353 
03354       channels++;
03355       if (c->_bridge) {
03356          snprintf(bridge, sizeof(bridge), "BridgedChannel: %s\r\nBridgedUniqueid: %s\r\n", c->_bridge->name, c->_bridge->uniqueid);
03357       } else {
03358          bridge[0] = '\0';
03359       }
03360       if (c->pbx) {
03361          if (c->cdr) {
03362             elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
03363          }
03364          astman_append(s,
03365          "Event: Status\r\n"
03366          "Privilege: Call\r\n"
03367          "Channel: %s\r\n"
03368          "CallerIDNum: %s\r\n"
03369          "CallerIDName: %s\r\n"
03370          "ConnectedLineNum: %s\r\n"
03371          "ConnectedLineName: %s\r\n"
03372          "Accountcode: %s\r\n"
03373          "ChannelState: %d\r\n"
03374          "ChannelStateDesc: %s\r\n"
03375          "Context: %s\r\n"
03376          "Extension: %s\r\n"
03377          "Priority: %d\r\n"
03378          "Seconds: %ld\r\n"
03379          "%s"
03380          "Uniqueid: %s\r\n"
03381          "%s"
03382          "%s"
03383          "\r\n",
03384          c->name,
03385          S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"),
03386          S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"),
03387          S_COR(c->connected.id.number.valid, c->connected.id.number.str, "<unknown>"),
03388          S_COR(c->connected.id.name.valid, c->connected.id.name.str, "<unknown>"),
03389          c->accountcode,
03390          c->_state,
03391          ast_state2str(c->_state), c->context,
03392          c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, ast_str_buffer(str), idText);
03393       } else {
03394          astman_append(s,
03395             "Event: Status\r\n"
03396             "Privilege: Call\r\n"
03397             "Channel: %s\r\n"
03398             "CallerIDNum: %s\r\n"
03399             "CallerIDName: %s\r\n"
03400             "ConnectedLineNum: %s\r\n"
03401             "ConnectedLineName: %s\r\n"
03402             "Account: %s\r\n"
03403             "State: %s\r\n"
03404             "%s"
03405             "Uniqueid: %s\r\n"
03406             "%s"
03407             "%s"
03408             "\r\n",
03409             c->name,
03410             S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"),
03411             S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"),
03412             S_COR(c->connected.id.number.valid, c->connected.id.number.str, "<unknown>"),
03413             S_COR(c->connected.id.name.valid, c->connected.id.name.str, "<unknown>"),
03414             c->accountcode,
03415             ast_state2str(c->_state), bridge, c->uniqueid,
03416             ast_str_buffer(str), idText);
03417       }
03418 
03419       ast_channel_unlock(c);
03420       c = ast_channel_unref(c);
03421 
03422       if (!all) {
03423          break;
03424       }
03425    }
03426 
03427    if (iter) {
03428       ast_channel_iterator_destroy(iter);
03429    }
03430 
03431    astman_append(s,
03432       "Event: StatusComplete\r\n"
03433       "%s"
03434       "Items: %d\r\n"
03435       "\r\n", idText, channels);
03436 
03437    ast_free(str);
03438 
03439    return 0;
03440 }

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

Definition at line 4314 of file manager.c.

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

Referenced by __init_manager().

04315 {
04316    struct ast_channel *c;
04317    const char *name = astman_get_header(m, "Channel");
04318    double timeout = atof(astman_get_header(m, "Timeout"));
04319    struct timeval when = { timeout, 0 };
04320 
04321    if (ast_strlen_zero(name)) {
04322       astman_send_error(s, m, "No channel specified");
04323       return 0;
04324    }
04325 
04326    if (!timeout || timeout < 0) {
04327       astman_send_error(s, m, "No timeout specified");
04328       return 0;
04329    }
04330 
04331    if (!(c = ast_channel_get_by_name(name))) {
04332       astman_send_error(s, m, "No such channel");
04333       return 0;
04334    }
04335 
04336    when.tv_usec = (timeout - when.tv_sec) * 1000000.0;
04337 
04338    ast_channel_lock(c);
04339    ast_channel_setwhentohangup_tv(c, when);
04340    ast_channel_unlock(c);
04341    c = ast_channel_unref(c);
04342 
04343    astman_send_ack(s, m, "Timeout Set");
04344 
04345    return 0;
04346 }

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

Definition at line 2830 of file manager.c.

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

Referenced by __init_manager().

02831 {
02832    struct ast_config *cfg;
02833    const char *sfn = astman_get_header(m, "SrcFilename");
02834    const char *dfn = astman_get_header(m, "DstFilename");
02835    int res;
02836    const char *rld = astman_get_header(m, "Reload");
02837    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02838    enum error_type result;
02839 
02840    if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) {
02841       astman_send_error(s, m, "Filename not specified");
02842       return 0;
02843    }
02844    if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) {
02845       astman_send_error(s, m, "Config file not found");
02846       return 0;
02847    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02848       astman_send_error(s, m, "Config file has invalid format");
02849       return 0;
02850    }
02851    result = handle_updates(s, m, cfg, dfn);
02852    if (!result) {
02853       ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */
02854       res = ast_config_text_file_save(dfn, cfg, "Manager");
02855       ast_config_destroy(cfg);
02856       if (res) {
02857          astman_send_error(s, m, "Save of config failed");
02858          return 0;
02859       }
02860       astman_send_ack(s, m, NULL);
02861       if (!ast_strlen_zero(rld)) {
02862          if (ast_true(rld)) {
02863             rld = NULL;
02864          }
02865          ast_module_reload(rld);
02866       }
02867    } else {
02868       ast_config_destroy(cfg);
02869       switch(result) {
02870       case UNKNOWN_ACTION:
02871          astman_send_error(s, m, "Unknown action command");
02872          break;
02873       case UNKNOWN_CATEGORY:
02874          astman_send_error(s, m, "Given category does not exist");
02875          break;
02876       case UNSPECIFIED_CATEGORY:
02877          astman_send_error(s, m, "Category not specified");
02878          break;
02879       case UNSPECIFIED_ARGUMENT:
02880          astman_send_error(s, m, "Problem with category, value, or line (if required)");
02881          break;
02882       case FAILURE_ALLOCATION:
02883          astman_send_error(s, m, "Memory allocation failure, this should not happen");
02884          break;
02885       case FAILURE_NEWCAT:
02886          astman_send_error(s, m, "Create category did not complete successfully");
02887          break;
02888       case FAILURE_DELCAT:
02889          astman_send_error(s, m, "Delete category did not complete successfully");
02890          break;
02891       case FAILURE_EMPTYCAT:
02892          astman_send_error(s, m, "Empty category did not complete successfully");
02893          break;
02894       case FAILURE_UPDATE:
02895          astman_send_error(s, m, "Update did not complete successfully");
02896          break;
02897       case FAILURE_DELETE:
02898          astman_send_error(s, m, "Delete did not complete successfully");
02899          break;
02900       case FAILURE_APPEND:
02901          astman_send_error(s, m, "Append did not complete successfully");
02902          break;
02903       }
02904    }
02905    return 0;
02906 }

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

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

04432 {
04433    const char *event = astman_get_header(m, "UserEvent");
04434    struct ast_str *body = ast_str_thread_get(&userevent_buf, 16);
04435    int x;
04436 
04437    ast_str_reset(body);
04438 
04439    for (x = 0; x < m->hdrcount; x++) {
04440       if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) {
04441          ast_str_append(&body, 0, "%s\r\n", m->headers[x]);
04442       }
04443    }
04444 
04445    astman_send_ack(s, m, "Event Sent");   
04446    manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, ast_str_buffer(body));
04447    return 0;
04448 }

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

Definition at line 2926 of file manager.c.

References advance_event(), ao2_lock, ao2_unlock, ast_debug, AST_PTHREADT_NULL, AST_RWLIST_NEXT, ast_strlen_zero(), ast_wait_for_input(), astman_append(), astman_get_header(), astman_send_response(), eventqent::category, eventqent::eventdata, mansession_session::fd, mansession_session::last_ev, mansession_session::managerid, mansession_session::needdestroy, mansession_session::readperm, mansession_session::send_events, mansession::session, mansession_session::sessiontimeout, and mansession_session::waiting_thread.

Referenced by __init_manager().

02927 {
02928    const char *timeouts = astman_get_header(m, "Timeout");
02929    int timeout = -1;
02930    int x;
02931    int needexit = 0;
02932    const char *id = astman_get_header(m, "ActionID");
02933    char idText[256];
02934 
02935    if (!ast_strlen_zero(id)) {
02936       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
02937    } else {
02938       idText[0] = '\0';
02939    }
02940 
02941    if (!ast_strlen_zero(timeouts)) {
02942       sscanf(timeouts, "%30i", &timeout);
02943       if (timeout < -1) {
02944          timeout = -1;
02945       }
02946       /* XXX maybe put an upper bound, or prevent the use of 0 ? */
02947    }
02948 
02949    ao2_lock(s->session);
02950    if (s->session->waiting_thread != AST_PTHREADT_NULL) {
02951       pthread_kill(s->session->waiting_thread, SIGURG);
02952    }
02953 
02954    if (s->session->managerid) { /* AMI-over-HTTP session */
02955       /*
02956        * Make sure the timeout is within the expire time of the session,
02957        * as the client will likely abort the request if it does not see
02958        * data coming after some amount of time.
02959        */
02960       time_t now = time(NULL);
02961       int max = s->session->sessiontimeout - now - 10;
02962 
02963       if (max < 0) { /* We are already late. Strange but possible. */
02964          max = 0;
02965       }
02966       if (timeout < 0 || timeout > max) {
02967          timeout = max;
02968       }
02969       if (!s->session->send_events) {  /* make sure we record events */
02970          s->session->send_events = -1;
02971       }
02972    }
02973    ao2_unlock(s->session);
02974 
02975    /* XXX should this go inside the lock ? */
02976    s->session->waiting_thread = pthread_self(); /* let new events wake up this thread */
02977    ast_debug(1, "Starting waiting for an event!\n");
02978 
02979    for (x = 0; x < timeout || timeout < 0; x++) {
02980       ao2_lock(s->session);
02981       if (AST_RWLIST_NEXT(s->session->last_ev, eq_next)) {
02982          needexit = 1;
02983       }
02984       /* We can have multiple HTTP session point to the same mansession entry.
02985        * The way we deal with it is not very nice: newcomers kick out the previous
02986        * HTTP session. XXX this needs to be improved.
02987        */
02988       if (s->session->waiting_thread != pthread_self()) {
02989          needexit = 1;
02990       }
02991       if (s->session->needdestroy) {
02992          needexit = 1;
02993       }
02994       ao2_unlock(s->session);
02995       if (needexit) {
02996          break;
02997       }
02998       if (s->session->managerid == 0) {   /* AMI session */
02999          if (ast_wait_for_input(s->session->fd, 1000)) {
03000             break;
03001          }
03002       } else { /* HTTP session */
03003          sleep(1);
03004       }
03005    }
03006    ast_debug(1, "Finished waiting for an event!\n");
03007 
03008    ao2_lock(s->session);
03009    if (s->session->waiting_thread == pthread_self()) {
03010       struct eventqent *eqe = s->session->last_ev;
03011       astman_send_response(s, m, "Success", "Waiting for Event completed.");
03012       while ((eqe = advance_event(eqe))) {
03013          if (((s->session->readperm & eqe->category) == eqe->category) &&
03014              ((s->session->send_events & eqe->category) == eqe->category)) {
03015             astman_append(s, "%s", eqe->eventdata);
03016          }
03017          s->session->last_ev = eqe;
03018       }
03019       astman_append(s,
03020          "Event: WaitEventComplete\r\n"
03021          "%s"
03022          "\r\n", idText);
03023       s->session->waiting_thread = AST_PTHREADT_NULL;
03024    } else {
03025       ast_debug(1, "Abandoning event request!\n");
03026    }
03027    ao2_unlock(s->session);
03028 
03029    return 0;
03030 }

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

Definition at line 1792 of file manager.c.

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

Referenced by action_waitevent(), and process_events().

01793 {
01794    struct eventqent *next;
01795 
01796    AST_RWLIST_RDLOCK(&all_events);
01797    if ((next = AST_RWLIST_NEXT(e, eq_next))) {
01798       ast_atomic_fetchadd_int(&next->usecount, 1);
01799       ast_atomic_fetchadd_int(&e->usecount, -1);
01800    }
01801    AST_RWLIST_UNLOCK(&all_events);
01802    return next;
01803 }

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

Definition at line 3877 of file manager.c.

References ast_aoc_unit_entry::amount, ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_strlen_zero(), astman_get_header(), str, ast_aoc_unit_entry::type, ast_aoc_unit_entry::valid_amount, and ast_aoc_unit_entry::valid_type.

Referenced by action_aocmessage().

03878 {
03879    const char *unitamount;
03880    const char *unittype;
03881    struct ast_str *str = ast_str_alloca(32);
03882 
03883    memset(entry, 0, sizeof(*entry));
03884 
03885    ast_str_set(&str, 0, "UnitAmount(%u)", entry_num);
03886    unitamount = astman_get_header(m, ast_str_buffer(str));
03887 
03888    ast_str_set(&str, 0, "UnitType(%u)", entry_num);
03889    unittype = astman_get_header(m, ast_str_buffer(str));
03890 
03891    if (!ast_strlen_zero(unitamount) && (sscanf(unitamount, "%30u", &entry->amount) == 1)) {
03892       entry->valid_amount = 1;
03893    }
03894 
03895    if (!ast_strlen_zero(unittype) && sscanf(unittype, "%30u", &entry->type) == 1) {
03896       entry->valid_type = 1;
03897    }
03898 
03899    return 0;
03900 }

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

Definition at line 5214 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_channel_variable::isfunc, manager_event_funcbuf, manager_channel_variable::name, pbx_builtin_getvar_helper(), and var.

Referenced by __ast_manager_event_multichan().

05215 {
05216    struct manager_channel_variable *var;
05217 
05218    AST_RWLIST_RDLOCK(&channelvars);
05219    AST_LIST_TRAVERSE(&channelvars, var, entry) {
05220       const char *val;
05221       struct ast_str *res;
05222 
05223       if (var->isfunc) {
05224          res = ast_str_thread_get(&manager_event_funcbuf, 16);
05225          if (res && ast_func_read2(chan, var->name, &res, 0) == 0) {
05226             val = ast_str_buffer(res);
05227          } else {
05228             val = NULL;
05229          }
05230       } else {
05231          val = pbx_builtin_getvar_helper(chan, var->name);
05232       }
05233       ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", chan->name, var->name, val ? val : "");
05234    }
05235    AST_RWLIST_UNLOCK(&channelvars);
05236 }

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

Definition at line 5188 of file manager.c.

References ast_atomic_fetchadd_int(), ast_malloc, AST_RWLIST_INSERT_TAIL, AST_RWLIST_NEXT, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_tvnow(), eventqent::category, eventqent::eventdata, eventqent::seq, eventqent::tv, and eventqent::usecount.

Referenced by __ast_manager_event_multichan(), and __init_manager().

05189 {
05190    struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str));
05191    static int seq;   /* sequence number */
05192 
05193    if (!tmp) {
05194       return -1;
05195    }
05196 
05197    /* need to init all fields, because ast_malloc() does not */
05198    tmp->usecount = 0;
05199    tmp->category = category;
05200    tmp->seq = ast_atomic_fetchadd_int(&seq, 1);
05201    tmp->tv = ast_tvnow();
05202    AST_RWLIST_NEXT(tmp, eq_next) = NULL;
05203    strcpy(tmp->eventdata, str);
05204 
05205    AST_RWLIST_WRLOCK(&all_events);
05206    AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next);
05207    AST_RWLIST_UNLOCK(&all_events);
05208 
05209    return 0;
05210 }

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

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

01940 {
01941    const char *action;
01942    int ret = 0;
01943    struct manager_action *act_found;
01944    struct mansession s = {.session = NULL, };
01945    struct message m = { 0 };
01946    char *dup_str;
01947    char *src;
01948    int x = 0;
01949    int curlen;
01950 
01951    if (hook == NULL) {
01952       return -1;
01953    }
01954 
01955    /* Create our own copy of the AMI action msg string. */
01956    src = dup_str = ast_strdup(msg);
01957    if (!dup_str) {
01958       return -1;
01959    }
01960 
01961    /* convert msg string to message struct */
01962    curlen = strlen(src);
01963    for (x = 0; x < curlen; x++) {
01964       int cr;  /* set if we have \r */
01965       if (src[x] == '\r' && x+1 < curlen && src[x+1] == '\n')
01966          cr = 2;  /* Found. Update length to include \r\n */
01967       else if (src[x] == '\n')
01968          cr = 1;  /* also accept \n only */
01969       else
01970          continue;
01971       /* don't keep empty lines */
01972       if (x && m.hdrcount < ARRAY_LEN(m.headers)) {
01973          /* ... but trim \r\n and terminate the header string */
01974          src[x] = '\0';
01975          m.headers[m.hdrcount++] = src;
01976       }
01977       x += cr;
01978       curlen -= x;      /* remaining size */
01979       src += x;      /* update pointer */
01980       x = -1;        /* reset loop */
01981    }
01982 
01983    action = astman_get_header(&m, "Action");
01984    if (strcasecmp(action, "login")) {
01985       act_found = action_find(action);
01986       if (act_found) {
01987          /*
01988           * we have to simulate a session for this action request
01989           * to be able to pass it down for processing
01990           * This is necessary to meet the previous design of manager.c
01991           */
01992          s.hook = hook;
01993          s.f = (void*)1; /* set this to something so our request will make it through all functions that test it*/
01994 
01995          ao2_lock(act_found);
01996          if (act_found->registered && act_found->func) {
01997             ++act_found->active_count;
01998             ao2_unlock(act_found);
01999             ret = act_found->func(&s, &m);
02000             ao2_lock(act_found);
02001             --act_found->active_count;
02002          } else {
02003             ret = -1;
02004          }
02005          ao2_unlock(act_found);
02006          ao2_t_ref(act_found, -1, "done with found action object");
02007       }
02008    }
02009    ast_free(dup_str);
02010    return ret;
02011 }

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

References eventqent::next.

Referenced by get_perm().

01258 {
01259    const char *val = bigstr, *next;
01260 
01261    do {
01262       if ((next = strchr(val, delim))) {
01263          if (!strncmp(val, smallstr, (next - val))) {
01264             return 1;
01265          } else {
01266             continue;
01267          }
01268       } else {
01269          return !strcmp(smallstr, val);
01270       }
01271    } while (*(val = (next + 1)));
01272 
01273    return 0;
01274 }

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

register a new command with manager, including online help. This is the preferred way to register a manager command

Register a manager command with the manager interface.

Definition at line 5443 of file manager.c.

References manager_action::action, action_destroy(), ao2_alloc, ao2_t_ref, ast_free, ast_manager_register_struct(), AST_STATIC_DOC, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, 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().

05444 {
05445    struct manager_action *cur;
05446 
05447    cur = ao2_alloc(sizeof(*cur), action_destroy);
05448    if (!cur) {
05449       return -1;
05450    }
05451    if (ast_string_field_init(cur, 128)) {
05452       ao2_t_ref(cur, -1, "action object creation failed");
05453       return -1;
05454    }
05455 
05456    cur->action = action;
05457    cur->authority = auth;
05458    cur->func = func;
05459 #ifdef AST_XML_DOCS
05460    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
05461       char *tmpxml;
05462 
05463       tmpxml = ast_xmldoc_build_synopsis("manager", action, NULL);
05464       ast_string_field_set(cur, synopsis, tmpxml);
05465       ast_free(tmpxml);
05466 
05467       tmpxml = ast_xmldoc_build_syntax("manager", action, NULL);
05468       ast_string_field_set(cur, syntax, tmpxml);
05469       ast_free(tmpxml);
05470 
05471       tmpxml = ast_xmldoc_build_description("manager", action, NULL);
05472       ast_string_field_set(cur, description, tmpxml);
05473       ast_free(tmpxml);
05474 
05475       tmpxml = ast_xmldoc_build_seealso("manager", action, NULL);
05476       ast_string_field_set(cur, seealso, tmpxml);
05477       ast_free(tmpxml);
05478 
05479       tmpxml = ast_xmldoc_build_arguments("manager", action, NULL);
05480       ast_string_field_set(cur, arguments, tmpxml);
05481       ast_free(tmpxml);
05482 
05483       cur->docsrc = AST_XML_DOC;
05484    } else
05485 #endif
05486    {
05487       ast_string_field_set(cur, synopsis, synopsis);
05488       ast_string_field_set(cur, description, description);
05489 #ifdef AST_XML_DOCS
05490       cur->docsrc = AST_STATIC_DOC;
05491 #endif
05492    }
05493    if (ast_manager_register_struct(cur)) {
05494       ao2_t_ref(cur, -1, "action object registration failed");
05495       return -1;
05496    }
05497 
05498    ao2_t_ref(cur, -1, "action object registration successful");
05499    return 0;
05500 }

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

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

static int ast_manager_register_struct ( struct manager_action act  )  [static]

Definition at line 5388 of file manager.c.

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

Referenced by ast_manager_register2().

05389 {
05390    struct manager_action *cur, *prev = NULL;
05391 
05392    AST_RWLIST_WRLOCK(&actions);
05393    AST_RWLIST_TRAVERSE(&actions, cur, list) {
05394       int ret;
05395 
05396       ret = strcasecmp(cur->action, act->action);
05397       if (ret == 0) {
05398          ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action);
05399          AST_RWLIST_UNLOCK(&actions);
05400          return -1;
05401       }
05402       if (ret > 0) { /* Insert these alphabetically */
05403          prev = cur;
05404          break;
05405       }
05406    }
05407 
05408    ao2_t_ref(act, +1, "action object added to list");
05409    act->registered = 1;
05410    if (prev) {
05411       AST_RWLIST_INSERT_AFTER(&actions, prev, act, list);
05412    } else {
05413       AST_RWLIST_INSERT_HEAD(&actions, act, list);
05414    }
05415 
05416    ast_verb(2, "Manager registered action %s\n", act->action);
05417 
05418    AST_RWLIST_UNLOCK(&actions);
05419 
05420    return 0;
05421 }

int ast_manager_unregister ( char *  action  ) 

Unregister a registered manager command.

Parameters:
action Name of registered Action:

Definition at line 5329 of file manager.c.

References manager_action::action, manager_action::active_count, ao2_lock, ao2_t_ref, ao2_unlock, ast_debug, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, and manager_action::registered.

Referenced by __unload_module(), astdb_shutdown(), data_shutdown(), features_shutdown(), manager_shutdown(), unload_module(), and unload_pbx().

05330 {
05331    struct manager_action *cur;
05332 
05333    AST_RWLIST_WRLOCK(&actions);
05334    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) {
05335       if (!strcasecmp(action, cur->action)) {
05336          AST_RWLIST_REMOVE_CURRENT(list);
05337          break;
05338       }
05339    }
05340    AST_RWLIST_TRAVERSE_SAFE_END;
05341    AST_RWLIST_UNLOCK(&actions);
05342 
05343    if (cur) {
05344       time_t now;
05345 
05346       /*
05347        * We have removed the action object from the container so we
05348        * are no longer in a hurry.
05349        */
05350       ao2_lock(cur);
05351       cur->registered = 0;
05352       ao2_unlock(cur);
05353 
05354       /*
05355        * Wait up to 5 seconds for any active invocations to complete
05356        * before returning.  We have to wait instead of blocking
05357        * because we may be waiting for ourself to complete.
05358        */
05359       now = time(NULL);
05360       while (cur->active_count) {
05361          if (5 <= time(NULL) - now) {
05362             ast_debug(1,
05363                "Unregister manager action %s timed out waiting for %d active instances to complete\n",
05364                action, cur->active_count);
05365             break;
05366          }
05367 
05368          sched_yield();
05369       }
05370 
05371       ao2_t_ref(cur, -1, "action object removed from list");
05372       ast_verb(2, "Manager unregistered action %s\n", action);
05373    }
05374 
05375    return 0;
05376 }

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

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

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

utility functions for creating AMI replies

Definition at line 2057 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_one(), _skinny_show_device(), _skinny_show_devices(), _skinny_show_line(), _skinny_show_lines(), action_agents(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_dahdishowchannels(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_listcategories(), action_listcommands(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_ping(), action_status(), action_waitevent(), ast_cli_netstats(), astman_append_json(), astman_send_response_full(), data_result_manager_output(), do_print(), manager_data_get(), manager_dbget(), manager_iax2_show_netstats(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_jabber_send(), manager_list_voicemail_users(), manager_modulecheck(), manager_mute_mixmonitor(), manager_mutestream(), manager_parking_status(), manager_queue_rule_show(), manager_queues_show(), manager_queues_status(), manager_queues_summary(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_show_registry(), manager_sip_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(), and session_do().

02058 {
02059    va_list ap;
02060    struct ast_str *buf;
02061 
02062    if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
02063       return;
02064    }
02065 
02066    va_start(ap, fmt);
02067    ast_str_set_va(&buf, 0, fmt, ap);
02068    va_end(ap);
02069 
02070    if (s->f != NULL || s->session->f != NULL) {
02071       send_string(s, ast_str_buffer(buf));
02072    } else {
02073       ast_verbose("fd == -1 in astman_append, should not happen\n");
02074    }
02075 }

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

Definition at line 2627 of file manager.c.

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

Referenced by action_getconfigjson().

02628 {
02629    char *buf;
02630 
02631    buf = ast_alloca(2 * strlen(str) + 1);
02632    json_escape(buf, str);
02633    astman_append(s, "%s", buf);
02634 }

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

Return the first matching variable from an array.

Get header from mananger transaction.

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

Definition at line 1859 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_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(), start_monitor_action(), and stop_monitor_action().

01860 {
01861    return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH);
01862 }

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

Get a linked list of the Variable: headers.

Definition at line 1917 of file manager.c.

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

Referenced by action_originate(), and manager_sipnotify().

01918 {
01919    int varlen;
01920    int x;
01921    struct ast_variable *head = NULL;
01922 
01923    static const char var_hdr[] = "Variable:";
01924 
01925    /* Process all "Variable:" headers. */
01926    varlen = strlen(var_hdr);
01927    for (x = 0; x < m->hdrcount; x++) {
01928       if (strncasecmp(var_hdr, m->headers[x], varlen)) {
01929          continue;
01930       }
01931       head = man_do_variable_value(head, m->headers[x] + varlen);
01932    }
01933 
01934    return head;
01935 }

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

Send error in manager transaction.

Definition at line 2119 of file manager.c.

References astman_send_response_full().

Referenced by _sip_qualify_peer(), _sip_show_peer(), action_add_agi_cmd(), action_agent_logoff(), action_aocmessage(), action_atxfer(), action_bridge(), action_challenge(), action_command(), action_coreshowchannels(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_originate(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), change_monitor_action(), do_message(), do_pause_or_unpause(), handle_parse_error(), 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_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().

02120 {
02121    astman_send_response_full(s, m, "Error", error, NULL);
02122 }

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

Send response in manager transaction.

Definition at line 2114 of file manager.c.

References astman_send_response_full().

Referenced by action_logoff(), and action_waitevent().

02115 {
02116    astman_send_response_full(s, m, resp, msg, NULL);
02117 }

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

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

02095 {
02096    const char *id = astman_get_header(m, "ActionID");
02097 
02098    astman_append(s, "Response: %s\r\n", resp);
02099    if (!ast_strlen_zero(id)) {
02100       astman_append(s, "ActionID: %s\r\n", id);
02101    }
02102    if (listflag) {
02103       astman_append(s, "EventList: %s\r\n", listflag);   /* Start, complete, cancelled */
02104    }
02105    if (msg == MSG_MOREDATA) {
02106       return;
02107    } else if (msg) {
02108       astman_append(s, "Message: %s\r\n\r\n", msg);
02109    } else {
02110       astman_append(s, "\r\n");
02111    }
02112 }

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

Definition at line 2411 of file manager.c.

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

Referenced by action_login().

02412 {
02413    const char *username = astman_get_header(m, "Username");
02414    const char *password = astman_get_header(m, "Secret");
02415    int error = -1;
02416    struct ast_manager_user *user = NULL;
02417    regex_t *regex_filter;
02418    struct ao2_iterator filter_iter;
02419    struct ast_sockaddr addr;
02420 
02421    if (ast_strlen_zero(username)) { /* missing username */
02422       return -1;
02423    }
02424 
02425    /* locate user in locked state */
02426    AST_RWLIST_WRLOCK(&users);
02427 
02428    ast_sockaddr_from_sin(&addr, &s->session->sin);
02429 
02430    if (!(user = get_manager_by_name_locked(username))) {
02431       report_invalid_user(s, username);
02432       ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
02433    } else if (user->ha && !ast_apply_ha(user->ha, &addr)) {
02434       report_failed_acl(s, username);
02435       ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
02436    } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) {
02437       const char *key = astman_get_header(m, "Key");
02438       if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) {
02439          int x;
02440          int len = 0;
02441          char md5key[256] = "";
02442          struct MD5Context md5;
02443          unsigned char digest[16];
02444 
02445          MD5Init(&md5);
02446          MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge));
02447          MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret));
02448          MD5Final(digest, &md5);
02449          for (x = 0; x < 16; x++)
02450             len += sprintf(md5key + len, "%2.2x", digest[x]);
02451          if (!strcmp(md5key, key)) {
02452             error = 0;
02453          } else {
02454             report_failed_challenge_response(s, key, md5key);
02455          }
02456       } else {
02457          ast_debug(1, "MD5 authentication is not possible.  challenge: '%s'\n",
02458             S_OR(s->session->challenge, ""));
02459       }
02460    } else if (user->secret) {
02461       if (!strcmp(password, user->secret)) {
02462          error = 0;
02463       } else {
02464          report_inval_password(s, username);
02465       }
02466    }
02467 
02468    if (error) {
02469       ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
02470       AST_RWLIST_UNLOCK(&users);
02471       return -1;
02472    }
02473 
02474    /* auth complete */
02475 
02476    /* All of the user parameters are copied to the session so that in the event
02477      * of a reload and a configuration change, the session parameters are not
02478      * changed. */
02479    ast_copy_string(s->session->username, username, sizeof(s->session->username));
02480    s->session->readperm = user->readperm;
02481    s->session->writeperm = user->writeperm;
02482    s->session->writetimeout = user->writetimeout;
02483 
02484    filter_iter = ao2_iterator_init(user->whitefilters, 0);
02485    while ((regex_filter = ao2_iterator_next(&filter_iter))) {
02486       ao2_t_link(s->session->whitefilters, regex_filter, "add white user filter to session");
02487       ao2_t_ref(regex_filter, -1, "remove iterator ref");
02488    }
02489    ao2_iterator_destroy(&filter_iter);
02490 
02491    filter_iter = ao2_iterator_init(user->blackfilters, 0);
02492    while ((regex_filter = ao2_iterator_next(&filter_iter))) {
02493       ao2_t_link(s->session->blackfilters, regex_filter, "add black user filter to session");
02494       ao2_t_ref(regex_filter, -1, "remove iterator ref");
02495    }
02496    ao2_iterator_destroy(&filter_iter);
02497 
02498    s->session->sessionstart = time(NULL);
02499    s->session->sessionstart_tv = ast_tvnow();
02500    set_eventmask(s, astman_get_header(m, "Events"));
02501 
02502    report_auth_success(s);
02503 
02504    AST_RWLIST_UNLOCK(&users);
02505    return 0;
02506 }

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

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

Definition at line 1233 of file manager.c.

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

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

01234 {
01235    int i;
01236    char *sep = "";
01237 
01238    ast_str_reset(*res);
01239    for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
01240       if (authority & perms[i].num) {
01241          ast_str_append(res, 0, "%s%s", sep, perms[i].label);
01242          sep = ",";
01243       }
01244    }
01245 
01246    if (ast_str_strlen(*res) == 0)   /* replace empty string with something sensible */
01247       ast_str_append(res, 0, "<none>");
01248 
01249    return ast_str_buffer(*res);
01250 }

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

Definition at line 4362 of file manager.c.

References CMP_MATCH, and CMP_STOP.

Referenced by match_filter().

04363 {
04364    regex_t *regex_filter = obj;
04365    const char *eventdata = arg;
04366    int *result = data;
04367 
04368    if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
04369       *result = 0;
04370       return (CMP_MATCH | CMP_STOP);
04371    }
04372 
04373    *result = 1;
04374    return 0;
04375 }

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

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

Definition at line 1374 of file manager.c.

References ao2_alloc, ao2_container_alloc, ao2_link, ao2_ref, AST_PTHREADT_NULL, mansession_session::blackfilters, mansession_session::fd, mansession_session::send_events, session_destructor(), sessions, mansession_session::sin, mansession_session::waiting_thread, mansession_session::whitefilters, and mansession_session::writetimeout.

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

01375 {
01376    struct mansession_session *newsession;
01377 
01378    if (!(newsession = ao2_alloc(sizeof(*newsession), session_destructor))) {
01379       return NULL;
01380    }
01381 
01382    if (!(newsession->whitefilters = ao2_container_alloc(1, NULL, NULL))) {
01383       ao2_ref(newsession, -1);
01384       return NULL;
01385    }
01386 
01387    if (!(newsession->blackfilters = ao2_container_alloc(1, NULL, NULL))) {
01388       ao2_ref(newsession, -1); /* session_destructor will cleanup the other filter */
01389       return NULL;
01390    }
01391 
01392    newsession->fd = -1;
01393    newsession->waiting_thread = AST_PTHREADT_NULL;
01394    newsession->writetimeout = 100;
01395    newsession->send_events = -1;
01396    newsession->sin = sin;
01397 
01398    ao2_link(sessions, newsession);
01399 
01400    return newsession;
01401 }

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

Definition at line 3679 of file manager.c.

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

Referenced by action_command().

03680 {
03681    char *cmd_copy, *cur_cmd;
03682    char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, };
03683    int i;
03684 
03685    cmd_copy = ast_strdupa(cmd);
03686    for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) {
03687       cur_cmd = ast_strip(cur_cmd);
03688       if (ast_strlen_zero(cur_cmd)) {
03689          i--;
03690          continue;
03691       }
03692 
03693       cmd_words[i] = cur_cmd;
03694    }
03695 
03696    for (i = 0; i < ARRAY_LEN(command_blacklist); i++) {
03697       int j, match = 1;
03698 
03699       for (j = 0; command_blacklist[i].words[j]; j++) {
03700          if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) {
03701             match = 0;
03702             break;
03703          }
03704       }
03705 
03706       if (match) {
03707          return 1;
03708       }
03709    }
03710 
03711    return 0;
03712 }

int check_manager_enabled ( void   ) 

Check if AMI is enabled.

Definition at line 1105 of file manager.c.

Referenced by handle_show_settings().

01106 {
01107    return manager_enabled;
01108 }

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

Definition at line 1417 of file manager.c.

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

Referenced by process_message().

01418 {
01419    struct mansession_session *session = ao2_find(sessions, (char *) name, 0);
01420    int inuse = 0;
01421 
01422    if (session) {
01423       inuse = 1;
01424       unref_mansession(session);
01425    }
01426    return inuse;
01427 }

int check_webmanager_enabled ( void   ) 

Check if AMI/HTTP is enabled.

Definition at line 1110 of file manager.c.

Referenced by action_coresettings(), and handle_show_settings().

01111 {
01112    return (webmanager_enabled && manager_enabled);
01113 }

static void destroy_fast_originate_helper ( struct fast_originate_helper doomed  )  [static]

Definition at line 3816 of file manager.c.

References ast_free, ast_string_field_free_memory, ast_variables_destroy(), and fast_originate_helper::vars.

Referenced by action_originate(), and fast_originate().

03817 {
03818    ast_variables_destroy(doomed->vars);
03819    ast_string_field_free_memory(doomed);
03820    ast_free(doomed);
03821 }

static int do_message ( struct mansession s  )  [static]

Definition at line 4968 of file manager.c.

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

Referenced by session_do().

04969 {
04970    struct message m = { 0 };
04971    char header_buf[sizeof(s->session->inbuf)] = { '\0' };
04972    int res;
04973    int idx;
04974    int hdr_loss;
04975    time_t now;
04976 
04977    hdr_loss = 0;
04978    for (;;) {
04979       /* Check if any events are pending and do them if needed */
04980       if (process_events(s)) {
04981          res = -1;
04982          break;
04983       }
04984       res = get_input(s, header_buf);
04985       if (res == 0) {
04986          /* No input line received. */
04987          if (!s->session->authenticated) {
04988             if (time(&now) == -1) {
04989                ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
04990                res = -1;
04991                break;
04992             }
04993 
04994             if (now - s->session->authstart > authtimeout) {
04995                if (displayconnects) {
04996                   ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout);
04997                }
04998                res = -1;
04999                break;
05000             }
05001          }
05002          continue;
05003       } else if (res > 0) {
05004          /* Input line received. */
05005          if (ast_strlen_zero(header_buf)) {
05006             if (hdr_loss) {
05007                mansession_lock(s);
05008                astman_send_error(s, &m, "Too many lines in message or allocation failure");
05009                mansession_unlock(s);
05010                res = 0;
05011             } else {
05012                switch (s->parsing) {
05013                case MESSAGE_OKAY:
05014                   res = process_message(s, &m) ? -1 : 0;
05015                   break;
05016                case MESSAGE_LINE_TOO_LONG:
05017                   handle_parse_error(s, &m, "Failed to parse message: line too long");
05018                   res = 0;
05019                   break;
05020                }
05021             }
05022             break;
05023          } else if (m.hdrcount < ARRAY_LEN(m.headers)) {
05024             m.headers[m.hdrcount] = ast_strdup(header_buf);
05025             if (!m.headers[m.hdrcount]) {
05026                /* Allocation failure. */
05027                hdr_loss = 1;
05028             } else {
05029                ++m.hdrcount;
05030             }
05031          } else {
05032             /* Too many lines in message. */
05033             hdr_loss = 1;
05034          }
05035       } else {
05036          /* Input error. */
05037          break;
05038       }
05039    }
05040 
05041    /* Free AMI request headers. */
05042    for (idx = 0; idx < m.hdrcount; ++idx) {
05043       ast_free((void *) m.headers[idx]);
05044    }
05045    return res;
05046 }

static void event_filter_destructor ( void *  obj  )  [static]

Definition at line 1337 of file manager.c.

Referenced by __init_manager().

01338 {
01339    regex_t *regex_filter = obj;
01340    regfree(regex_filter);
01341 }

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

Definition at line 3823 of file manager.c.

References fast_originate_helper::account, fast_originate_helper::app, fast_originate_helper::appdata, AST_CHANNEL_NAME, ast_channel_unlock, 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, destroy_fast_originate_helper(), EVENT_FLAG_CALL, fast_originate_helper::exten, fast_originate_helper::format, fast_originate_helper::idtext, fast_originate_helper::priority, S_OR, fast_originate_helper::tech, fast_originate_helper::timeout, and fast_originate_helper::vars.

Referenced by action_originate().

03824 {
03825    struct fast_originate_helper *in = data;
03826    int res;
03827    int reason = 0;
03828    struct ast_channel *chan = NULL, *chans[1];
03829    char requested_channel[AST_CHANNEL_NAME];
03830 
03831    if (!ast_strlen_zero(in->app)) {
03832       res = ast_pbx_outgoing_app(in->tech, in->format, (char *) in->data,
03833          in->timeout, in->app, in->appdata, &reason, 1,
03834          S_OR(in->cid_num, NULL),
03835          S_OR(in->cid_name, NULL),
03836          in->vars, in->account, &chan);
03837    } else {
03838       res = ast_pbx_outgoing_exten(in->tech, in->format, (char *) in->data,
03839          in->timeout, in->context, in->exten, in->priority, &reason, 1,
03840          S_OR(in->cid_num, NULL),
03841          S_OR(in->cid_name, NULL),
03842          in->vars, in->account, &chan);
03843    }
03844    /* Any vars memory was passed to the ast_pbx_outgoing_xxx() calls. */
03845    in->vars = NULL;
03846 
03847    if (!chan) {
03848       snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);
03849    }
03850    /* Tell the manager what happened with the channel */
03851    chans[0] = chan;
03852    ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans,
03853       "%s"
03854       "Response: %s\r\n"
03855       "Channel: %s\r\n"
03856       "Context: %s\r\n"
03857       "Exten: %s\r\n"
03858       "Reason: %d\r\n"
03859       "Uniqueid: %s\r\n"
03860       "CallerIDNum: %s\r\n"
03861       "CallerIDName: %s\r\n",
03862       in->idtext, res ? "Failure" : "Success",
03863       chan ? chan->name : requested_channel, in->context, in->exten, reason,
03864       chan ? chan->uniqueid : "<null>",
03865       S_OR(in->cid_num, "<unknown>"),
03866       S_OR(in->cid_name, "<unknown>")
03867       );
03868 
03869    /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
03870    if (chan) {
03871       ast_channel_unlock(chan);
03872    }
03873    destroy_fast_originate_helper(in);
03874    return NULL;
03875 }

static void free_channelvars ( void   )  [static]

Definition at line 7227 of file manager.c.

References ast_free, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and var.

Referenced by __init_manager(), and load_channelvars().

07228 {
07229    struct manager_channel_variable *var;
07230    AST_RWLIST_WRLOCK(&channelvars);
07231    while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) {
07232       ast_free(var);
07233    }
07234    AST_RWLIST_UNLOCK(&channelvars);
07235 }

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

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

Definition at line 1197 of file manager.c.

References EVENT_FLAG_SYSTEM.

Referenced by action_getvar(), and action_status().

01198 {
01199    if (!(writepermlist & EVENT_FLAG_SYSTEM)
01200       && (
01201          strstr(evaluating, "SHELL") ||       /* NoOp(${SHELL(rm -rf /)})  */
01202          strstr(evaluating, "EVAL")           /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
01203       )) {
01204       return 0;
01205    }
01206    return 1;
01207 }

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

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

Referenced by do_message().

04854 {
04855    int res, x;
04856    int maxlen = sizeof(s->session->inbuf) - 1;
04857    char *src = s->session->inbuf;
04858    int timeout = -1;
04859    time_t now;
04860 
04861    /*
04862     * Look for \r\n within the buffer. If found, copy to the output
04863     * buffer and return, trimming the \r\n (not used afterwards).
04864     */
04865    for (x = 0; x < s->session->inlen; x++) {
04866       int cr;  /* set if we have \r */
04867       if (src[x] == '\r' && x+1 < s->session->inlen && src[x + 1] == '\n') {
04868          cr = 2;  /* Found. Update length to include \r\n */
04869       } else if (src[x] == '\n') {
04870          cr = 1;  /* also accept \n only */
04871       } else {
04872          continue;
04873       }
04874       memmove(output, src, x);   /*... but trim \r\n */
04875       output[x] = '\0';    /* terminate the string */
04876       x += cr;       /* number of bytes used */
04877       s->session->inlen -= x;       /* remaining size */
04878       memmove(src, src + x, s->session->inlen); /* remove used bytes */
04879       return 1;
04880    }
04881    if (s->session->inlen >= maxlen) {
04882       /* no crlf found, and buffer full - sorry, too long for us */
04883       ast_log(LOG_WARNING, "Discarding message from %s. Line too long: %.25s...\n", ast_inet_ntoa(s->session->sin.sin_addr), src);
04884       s->session->inlen = 0;
04885       s->parsing = MESSAGE_LINE_TOO_LONG;
04886    }
04887    res = 0;
04888    while (res == 0) {
04889       /* calculate a timeout if we are not authenticated */
04890       if (!s->session->authenticated) {
04891          if(time(&now) == -1) {
04892             ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
04893             return -1;
04894          }
04895 
04896          timeout = (authtimeout - (now - s->session->authstart)) * 1000;
04897          if (timeout < 0) {
04898             /* we have timed out */
04899             return 0;
04900          }
04901       }
04902 
04903       ao2_lock(s->session);
04904       if (s->session->pending_event) {
04905          s->session->pending_event = 0;
04906          ao2_unlock(s->session);
04907          return 0;
04908       }
04909       s->session->waiting_thread = pthread_self();
04910       ao2_unlock(s->session);
04911 
04912       res = ast_wait_for_input(s->session->fd, timeout);
04913 
04914       ao2_lock(s->session);
04915       s->session->waiting_thread = AST_PTHREADT_NULL;
04916       ao2_unlock(s->session);
04917    }
04918    if (res < 0) {
04919       /* If we get a signal from some other thread (typically because
04920        * there are new events queued), return 0 to notify the caller.
04921        */
04922       if (errno == EINTR || errno == EAGAIN) {
04923          return 0;
04924       }
04925       ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno));
04926       return -1;
04927    }
04928 
04929    ao2_lock(s->session);
04930    res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f);
04931    if (res < 1) {
04932       res = -1;   /* error return */
04933    } else {
04934       s->session->inlen += res;
04935       src[s->session->inlen] = '\0';
04936       res = 0;
04937    }
04938    ao2_unlock(s->session);
04939    return res;
04940 }

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

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

Definition at line 1434 of file manager.c.

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

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

01435 {
01436    struct ast_manager_user *user = NULL;
01437 
01438    AST_RWLIST_TRAVERSE(&users, user, list) {
01439       if (!strcasecmp(user->username, name)) {
01440          break;
01441       }
01442    }
01443 
01444    return user;
01445 }

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

Definition at line 1276 of file manager.c.

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

Referenced by __init_manager(), and strings_to_mask().

01277 {
01278    int x = 0, ret = 0;
01279 
01280    if (!instr) {
01281       return 0;
01282    }
01283 
01284    for (x = 0; x < ARRAY_LEN(perms); x++) {
01285       if (ast_instring(instr, perms[x].label, ',')) {
01286          ret |= perms[x].num;
01287       }
01288    }
01289 
01290    return ret;
01291 }

static struct eventqent* grab_last ( void   )  [static, read]

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

Definition at line 1119 of file manager.c.

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

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

01120 {
01121    struct eventqent *ret;
01122 
01123    AST_RWLIST_WRLOCK(&all_events);
01124    ret = AST_RWLIST_LAST(&all_events);
01125    /* the list is never empty now, but may become so when
01126     * we optimize it in the future, so be prepared.
01127     */
01128    if (ret) {
01129       ast_atomic_fetchadd_int(&ret->usecount, 1);
01130    }
01131    AST_RWLIST_UNLOCK(&all_events);
01132    return ret;
01133 }

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

01774 {
01775    switch (cmd) {
01776    case CLI_INIT:
01777       e->command = "manager reload";
01778       e->usage =
01779          "Usage: manager reload\n"
01780          "       Reloads the manager configuration.\n";
01781       return NULL;
01782    case CLI_GENERATE:
01783       return NULL;
01784    }
01785    if (a->argc > 2) {
01786       return CLI_SHOWUSAGE;
01787    }
01788    reload_manager();
01789    return CLI_SUCCESS;
01790 }

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

Definition at line 1547 of file manager.c.

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

01548 {
01549    switch (cmd) {
01550    case CLI_INIT:
01551       e->command = "manager set debug [on|off]";
01552       e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n";
01553       return NULL;
01554    case CLI_GENERATE:
01555       return NULL;
01556    }
01557 
01558    if (a->argc == 3) {
01559       ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off");
01560    } else if (a->argc == 4) {
01561       if (!strcasecmp(a->argv[3], "on")) {
01562          manager_debug = 1;
01563       } else if (!strcasecmp(a->argv[3], "off")) {
01564          manager_debug = 0;
01565       } else {
01566          return CLI_SHOWUSAGE;
01567       }
01568    }
01569    return CLI_SUCCESS;
01570 }

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

Definition at line 4951 of file manager.c.

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

Referenced by do_message().

04952 {
04953    mansession_lock(s);
04954    astman_send_error(s, m, error);
04955    s->parsing = MESSAGE_OKAY;
04956    mansession_unlock(s);
04957 }

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

Definition at line 1572 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, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_manager_user::displayconnects, ast_cli_args::fd, get_manager_by_name_locked(), ast_manager_user::ha, ast_cli_args::n, ast_cli_args::pos, ast_manager_user::readperm, ast_manager_user::secret, ast_cli_entry::usage, user_authority_to_str(), ast_manager_user::username, ast_cli_args::word, and ast_manager_user::writeperm.

01573 {
01574    struct ast_manager_user *user = NULL;
01575    int l, which;
01576    char *ret = NULL;
01577    struct ast_str *rauthority = ast_str_alloca(128);
01578    struct ast_str *wauthority = ast_str_alloca(128);
01579 
01580    switch (cmd) {
01581    case CLI_INIT:
01582       e->command = "manager show user";
01583       e->usage =
01584          " Usage: manager show user <user>\n"
01585          "        Display all information related to the manager user specified.\n";
01586       return NULL;
01587    case CLI_GENERATE:
01588       l = strlen(a->word);
01589       which = 0;
01590       if (a->pos != 3) {
01591          return NULL;
01592       }
01593       AST_RWLIST_RDLOCK(&users);
01594       AST_RWLIST_TRAVERSE(&users, user, list) {
01595          if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) {
01596             ret = ast_strdup(user->username);
01597             break;
01598          }
01599       }
01600       AST_RWLIST_UNLOCK(&users);
01601       return ret;
01602    }
01603 
01604    if (a->argc != 4) {
01605       return CLI_SHOWUSAGE;
01606    }
01607 
01608    AST_RWLIST_RDLOCK(&users);
01609 
01610    if (!(user = get_manager_by_name_locked(a->argv[3]))) {
01611       ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]);
01612       AST_RWLIST_UNLOCK(&users);
01613       return CLI_SUCCESS;
01614    }
01615 
01616    ast_cli(a->fd, "\n");
01617    ast_cli(a->fd,
01618       "       username: %s\n"
01619       "         secret: %s\n"
01620       "            acl: %s\n"
01621       "      read perm: %s\n"
01622       "     write perm: %s\n"
01623       "displayconnects: %s\n",
01624       (user->username ? user->username : "(N/A)"),
01625       (user->secret ? "<Set>" : "(N/A)"),
01626       (user->ha ? "yes" : "no"),
01627       user_authority_to_str(user->readperm, &rauthority),
01628       user_authority_to_str(user->writeperm, &wauthority),
01629       (user->displayconnects ? "yes" : "no"));
01630 
01631    AST_RWLIST_UNLOCK(&users);
01632 
01633    return CLI_SUCCESS;
01634 }

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

Definition at line 1636 of file manager.c.

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

01637 {
01638    struct ast_manager_user *user = NULL;
01639    int count_amu = 0;
01640    switch (cmd) {
01641    case CLI_INIT:
01642       e->command = "manager show users";
01643       e->usage =
01644          "Usage: manager show users\n"
01645          "       Prints a listing of all managers that are currently configured on that\n"
01646          " system.\n";
01647       return NULL;
01648    case CLI_GENERATE:
01649       return NULL;
01650    }
01651    if (a->argc != 3) {
01652       return CLI_SHOWUSAGE;
01653    }
01654 
01655    AST_RWLIST_RDLOCK(&users);
01656 
01657    /* If there are no users, print out something along those lines */
01658    if (AST_RWLIST_EMPTY(&users)) {
01659       ast_cli(a->fd, "There are no manager users.\n");
01660       AST_RWLIST_UNLOCK(&users);
01661       return CLI_SUCCESS;
01662    }
01663 
01664    ast_cli(a->fd, "\nusername\n--------\n");
01665 
01666    AST_RWLIST_TRAVERSE(&users, user, list) {
01667       ast_cli(a->fd, "%s\n", user->username);
01668       count_amu++;
01669    }
01670 
01671    AST_RWLIST_UNLOCK(&users);
01672 
01673    ast_cli(a->fd,"-------------------\n"
01674             "%d manager users configured.\n", count_amu);
01675    return CLI_SUCCESS;
01676 }

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

Definition at line 1465 of file manager.c.

References manager_action::action, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_free, 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, CLI_SUCCESS, COLOR_MAGENTA, ast_cli_entry::command, manager_action::docsrc, ast_cli_args::fd, ast_cli_args::n, S_OR, synopsis, term_color(), ast_cli_entry::usage, and ast_cli_args::word.

01466 {
01467    struct manager_action *cur;
01468    struct ast_str *authority;
01469    int num, l, which;
01470    char *ret = NULL;
01471 #ifdef AST_XML_DOCS
01472    char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64];
01473 #endif
01474 
01475    switch (cmd) {
01476    case CLI_INIT:
01477       e->command = "manager show command";
01478       e->usage =
01479          "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n"
01480          "  Shows the detailed description for a specific Asterisk manager interface command.\n";
01481       return NULL;
01482    case CLI_GENERATE:
01483       l = strlen(a->word);
01484       which = 0;
01485       AST_RWLIST_RDLOCK(&actions);
01486       AST_RWLIST_TRAVERSE(&actions, cur, list) {
01487          if (!strncasecmp(a->word, cur->action, l) && ++which > a->n) {
01488             ret = ast_strdup(cur->action);
01489             break;   /* make sure we exit even if ast_strdup() returns NULL */
01490          }
01491       }
01492       AST_RWLIST_UNLOCK(&actions);
01493       return ret;
01494    }
01495    authority = ast_str_alloca(80);
01496    if (a->argc < 4) {
01497       return CLI_SHOWUSAGE;
01498    }
01499 
01500 #ifdef AST_XML_DOCS
01501    /* setup the titles */
01502    term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
01503    term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40);
01504    term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
01505    term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40);
01506    term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
01507 #endif
01508 
01509    AST_RWLIST_RDLOCK(&actions);
01510    AST_RWLIST_TRAVERSE(&actions, cur, list) {
01511       for (num = 3; num < a->argc; num++) {
01512          if (!strcasecmp(cur->action, a->argv[num])) {
01513 #ifdef AST_XML_DOCS
01514             if (cur->docsrc == AST_XML_DOC) {
01515                char *syntax = ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1);
01516                char *synopsis = ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1);
01517                char *description = ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1);
01518                char *arguments = ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1);
01519                char *seealso = ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1);
01520                ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n",
01521                   syntax_title, syntax,
01522                   synopsis_title, synopsis,
01523                   description_title, description,
01524                   arguments_title, arguments,
01525                   seealso_title, seealso);
01526                ast_free(syntax);
01527                ast_free(synopsis);
01528                ast_free(description);
01529                ast_free(arguments);
01530                ast_free(seealso);
01531             } else
01532 #endif
01533             {
01534                ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
01535                   cur->action, cur->synopsis,
01536                   authority_to_str(cur->authority, &authority),
01537                   S_OR(cur->description, ""));
01538             }
01539          }
01540       }
01541    }
01542    AST_RWLIST_UNLOCK(&actions);
01543 
01544    return CLI_SUCCESS;
01545 }

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

01680 {
01681    struct manager_action *cur;
01682    struct ast_str *authority;
01683 #define HSMC_FORMAT "  %-15.15s  %-15.15s  %-55.55s\n"
01684    switch (cmd) {
01685    case CLI_INIT:
01686       e->command = "manager show commands";
01687       e->usage =
01688          "Usage: manager show commands\n"
01689          "  Prints a listing of all the available Asterisk manager interface commands.\n";
01690       return NULL;
01691    case CLI_GENERATE:
01692       return NULL;
01693    }
01694    authority = ast_str_alloca(80);
01695    ast_cli(a->fd, HSMC_FORMAT, "Action", "Privilege", "Synopsis");
01696    ast_cli(a->fd, HSMC_FORMAT, "------", "---------", "--------");
01697 
01698    AST_RWLIST_RDLOCK(&actions);
01699    AST_RWLIST_TRAVERSE(&actions, cur, list) {
01700       ast_cli(a->fd, HSMC_FORMAT, cur->action, authority_to_str(cur->authority, &authority), cur->synopsis);
01701    }
01702    AST_RWLIST_UNLOCK(&actions);
01703 
01704    return CLI_SUCCESS;
01705 }

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

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_cli(), ast_inet_ntoa(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, mansession_session::fd, ast_cli_args::fd, HSMCONN_FORMAT1, HSMCONN_FORMAT2, mansession_session::inuse, mansession_session::readperm, sessions, mansession_session::sessionstart, mansession_session::sin, unref_mansession(), ast_cli_entry::usage, mansession_session::username, and mansession_session::writeperm.

01709 {
01710    struct mansession_session *session;
01711    time_t now = time(NULL);
01712 #define HSMCONN_FORMAT1 "  %-15.15s  %-15.15s  %-10.10s  %-10.10s  %-8.8s  %-8.8s  %-5.5s  %-5.5s\n"
01713 #define HSMCONN_FORMAT2 "  %-15.15s  %-15.15s  %-10d  %-10d  %-8d  %-8d  %-5.5d  %-5.5d\n"
01714    int count = 0;
01715    struct ao2_iterator i;
01716 
01717    switch (cmd) {
01718    case CLI_INIT:
01719       e->command = "manager show connected";
01720       e->usage =
01721          "Usage: manager show connected\n"
01722          "  Prints a listing of the users that are currently connected to the\n"
01723          "Asterisk manager interface.\n";
01724       return NULL;
01725    case CLI_GENERATE:
01726       return NULL;
01727    }
01728 
01729    ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write");
01730 
01731    i = ao2_iterator_init(sessions, 0);
01732    while ((session = ao2_iterator_next(&i))) {
01733       ao2_lock(session);
01734       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);
01735       count++;
01736       ao2_unlock(session);
01737       unref_mansession(session);
01738    }
01739    ao2_iterator_destroy(&i);
01740    ast_cli(a->fd, "%d users connected.\n", count);
01741 
01742    return CLI_SUCCESS;
01743 }

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

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

01748 {
01749    struct eventqent *s;
01750    switch (cmd) {
01751    case CLI_INIT:
01752       e->command = "manager show eventq";
01753       e->usage =
01754          "Usage: manager show eventq\n"
01755          "  Prints a listing of all events pending in the Asterisk manger\n"
01756          "event queue.\n";
01757       return NULL;
01758    case CLI_GENERATE:
01759       return NULL;
01760    }
01761    AST_RWLIST_RDLOCK(&all_events);
01762    AST_RWLIST_TRAVERSE(&all_events, s, eq_next) {
01763       ast_cli(a->fd, "Usecount: %d\n", s->usecount);
01764       ast_cli(a->fd, "Category: %d\n", s->category);
01765       ast_cli(a->fd, "Event:\n%s", s->eventdata);
01766    }
01767    AST_RWLIST_UNLOCK(&all_events);
01768 
01769    return CLI_SUCCESS;
01770 }

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

Definition at line 2685 of file manager.c.

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

Referenced by action_updateconfig().

02686 {
02687    int x;
02688    char hdr[40];
02689    const char *action, *cat, *var, *value, *match, *line;
02690    struct ast_category *category;
02691    struct ast_variable *v;
02692    struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
02693    enum error_type result = 0;
02694 
02695    for (x = 0; x < 100000; x++) {   /* 100000 = the max number of allowed updates + 1 */
02696       unsigned int object = 0;
02697 
02698       snprintf(hdr, sizeof(hdr), "Action-%06d", x);
02699       action = astman_get_header(m, hdr);
02700       if (ast_strlen_zero(action))     /* breaks the for loop if no action header */
02701          break;                        /* this could cause problems if actions come in misnumbered */
02702 
02703       snprintf(hdr, sizeof(hdr), "Cat-%06d", x);
02704       cat = astman_get_header(m, hdr);
02705       if (ast_strlen_zero(cat)) {      /* every action needs a category */
02706          result =  UNSPECIFIED_CATEGORY;
02707          break;
02708       }
02709 
02710       snprintf(hdr, sizeof(hdr), "Var-%06d", x);
02711       var = astman_get_header(m, hdr);
02712 
02713       snprintf(hdr, sizeof(hdr), "Value-%06d", x);
02714       value = astman_get_header(m, hdr);
02715 
02716       if (!ast_strlen_zero(value) && *value == '>') {
02717          object = 1;
02718          value++;
02719       }
02720 
02721       snprintf(hdr, sizeof(hdr), "Match-%06d", x);
02722       match = astman_get_header(m, hdr);
02723 
02724       snprintf(hdr, sizeof(hdr), "Line-%06d", x);
02725       line = astman_get_header(m, hdr);
02726 
02727       if (!strcasecmp(action, "newcat")) {
02728          if (ast_category_get(cfg,cat)) { /* check to make sure the cat doesn't */
02729             result = FAILURE_NEWCAT;   /* already exist */
02730             break;
02731          }
02732          if (!(category = ast_category_new(cat, dfn, -1))) {
02733             result = FAILURE_ALLOCATION;
02734             break;
02735          }
02736          if (ast_strlen_zero(match)) {
02737             ast_category_append(cfg, category);
02738          } else {
02739             ast_category_insert(cfg, category, match);
02740          }
02741       } else if (!strcasecmp(action, "renamecat")) {
02742          if (ast_strlen_zero(value)) {
02743             result = UNSPECIFIED_ARGUMENT;
02744             break;
02745          }
02746          if (!(category = ast_category_get(cfg, cat))) {
02747             result = UNKNOWN_CATEGORY;
02748             break;
02749          }
02750          ast_category_rename(category, value);
02751       } else if (!strcasecmp(action, "delcat")) {
02752          if (ast_category_delete(cfg, cat)) {
02753             result = FAILURE_DELCAT;
02754             break;
02755          }
02756       } else if (!strcasecmp(action, "emptycat")) {
02757          if (ast_category_empty(cfg, cat)) {
02758             result = FAILURE_EMPTYCAT;
02759             break;
02760          }
02761       } else if (!strcasecmp(action, "update")) {
02762          if (ast_strlen_zero(var)) {
02763             result = UNSPECIFIED_ARGUMENT;
02764             break;
02765          }
02766          if (!(category = ast_category_get(cfg,cat))) {
02767             result = UNKNOWN_CATEGORY;
02768             break;
02769          }
02770          if (ast_variable_update(category, var, value, match, object)) {
02771             result = FAILURE_UPDATE;
02772             break;
02773          }
02774       } else if (!strcasecmp(action, "delete")) {
02775          if ((ast_strlen_zero(var) && ast_strlen_zero(line))) {
02776             result = UNSPECIFIED_ARGUMENT;
02777             break;
02778          }
02779          if (!(category = ast_category_get(cfg, cat))) {
02780             result = UNKNOWN_CATEGORY;
02781             break;
02782          }
02783          if (ast_variable_delete(category, var, match, line)) {
02784             result = FAILURE_DELETE;
02785             break;
02786          }
02787       } else if (!strcasecmp(action, "append")) {
02788          if (ast_strlen_zero(var)) {
02789             result = UNSPECIFIED_ARGUMENT;
02790             break;
02791          }
02792          if (!(category = ast_category_get(cfg, cat))) {
02793             result = UNKNOWN_CATEGORY;
02794             break;
02795          }
02796          if (!(v = ast_variable_new(var, value, dfn))) {
02797             result = FAILURE_ALLOCATION;
02798             break;
02799          }
02800          if (object || (match && !strcasecmp(match, "object"))) {
02801             v->object = 1;
02802          }
02803          ast_variable_append(category, v);
02804       } else if (!strcasecmp(action, "insert")) {
02805          if (ast_strlen_zero(var) || ast_strlen_zero(line)) {
02806             result = UNSPECIFIED_ARGUMENT;
02807             break;
02808          }
02809          if (!(category = ast_category_get(cfg, cat))) {
02810             result = UNKNOWN_CATEGORY;
02811             break;
02812          }
02813          if (!(v = ast_variable_new(var, value, dfn))) {
02814             result = FAILURE_ALLOCATION;
02815             break;
02816          }
02817          ast_variable_insert(category, v, line);
02818       }
02819       else {
02820          ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action);
02821          result = UNKNOWN_ACTION;
02822          break;
02823       }
02824    }
02825    ast_free(str1);
02826    ast_free(str2);
02827    return result;
02828 }

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

Referenced by astman_append_json().

02608 {
02609    for (; *in; in++) {
02610       if (*in == '\\' || *in == '\"') {
02611          *out++ = '\\';
02612       }
02613       *out++ = *in;
02614    }
02615    *out = '\0';
02616 }

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

Definition at line 1873 of file manager.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_skip_blanks(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_variable_new(), ast_variable::next, parse(), and var.

Referenced by astman_get_variables().

01874 {
01875    char *parse;
01876    AST_DECLARE_APP_ARGS(args,
01877       AST_APP_ARG(vars)[64];
01878    );
01879 
01880    hdr_val = ast_skip_blanks(hdr_val); /* ignore leading spaces in the value */
01881    parse = ast_strdupa(hdr_val);
01882 
01883    /* Break the header value string into name=val pair items. */
01884    AST_STANDARD_APP_ARGS(args, parse);
01885    if (args.argc) {
01886       int y;
01887 
01888       /* Process each name=val pair item. */
01889       for (y = 0; y < args.argc; y++) {
01890          struct ast_variable *cur;
01891          char *var;
01892          char *val;
01893 
01894          if (!args.vars[y]) {
01895             continue;
01896          }
01897          var = val = args.vars[y];
01898          strsep(&val, "=");
01899 
01900          /* XXX We may wish to trim whitespace from the strings. */
01901          if (!val || ast_strlen_zero(var)) {
01902             continue;
01903          }
01904 
01905          /* Create new variable list node and prepend it to the list. */
01906          cur = ast_variable_new(var, val, "");
01907          if (cur) {
01908             cur->next = head;
01909             head = cur;
01910          }
01911       }
01912    }
01913 
01914    return head;
01915 }

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

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

Referenced by action_login(), generic_http_callback(), purge_sessions(), and session_do().

01452 {
01453    struct ast_manager_user *user = NULL;
01454    int ret = 0;
01455 
01456    AST_RWLIST_RDLOCK(&users);
01457    if ((user = get_manager_by_name_locked (session->username))) {
01458       ret = user->displayconnects;
01459    }
01460    AST_RWLIST_UNLOCK(&users);
01461 
01462    return ret;
01463 }

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

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

04644 {
04645    int res;
04646    const char *module = astman_get_header(m, "Module");
04647    const char *id = astman_get_header(m, "ActionID");
04648    char idText[256];
04649 #if !defined(LOW_MEMORY)
04650    const char *version;
04651 #endif
04652    char filename[PATH_MAX];
04653    char *cut;
04654 
04655    ast_copy_string(filename, module, sizeof(filename));
04656    if ((cut = strchr(filename, '.'))) {
04657       *cut = '\0';
04658    } else {
04659       cut = filename + strlen(filename);
04660    }
04661    snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".so");
04662    ast_log(LOG_DEBUG, "**** ModuleCheck .so file %s\n", filename);
04663    res = ast_module_check(filename);
04664    if (!res) {
04665       astman_send_error(s, m, "Module not loaded");
04666       return 0;
04667    }
04668    snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".c");
04669    ast_log(LOG_DEBUG, "**** ModuleCheck .c file %s\n", filename);
04670 #if !defined(LOW_MEMORY)
04671    version = ast_file_version_find(filename);
04672 #endif
04673 
04674    if (!ast_strlen_zero(id)) {
04675       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
04676    } else {
04677       idText[0] = '\0';
04678    }
04679    astman_append(s, "Response: Success\r\n%s", idText);
04680 #if !defined(LOW_MEMORY)
04681    astman_append(s, "Version: %s\r\n\r\n", version ? version : "");
04682 #endif
04683    return 0;
04684 }

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

Definition at line 4686 of file manager.c.

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

Referenced by __init_manager().

04687 {
04688    int res;
04689    const char *module = astman_get_header(m, "Module");
04690    const char *loadtype = astman_get_header(m, "LoadType");
04691 
04692    if (!loadtype || strlen(loadtype) == 0) {
04693       astman_send_error(s, m, "Incomplete ModuleLoad action.");
04694    }
04695    if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0) {
04696       astman_send_error(s, m, "Need module name");
04697    }
04698 
04699    if (!strcasecmp(loadtype, "load")) {
04700       res = ast_load_resource(module);
04701       if (res) {
04702          astman_send_error(s, m, "Could not load module.");
04703       } else {
04704          astman_send_ack(s, m, "Module loaded.");
04705       }
04706    } else if (!strcasecmp(loadtype, "unload")) {
04707       res = ast_unload_resource(module, AST_FORCE_SOFT);
04708       if (res) {
04709          astman_send_error(s, m, "Could not unload module.");
04710       } else {
04711          astman_send_ack(s, m, "Module unloaded.");
04712       }
04713    } else if (!strcasecmp(loadtype, "reload")) {
04714       if (!ast_strlen_zero(module)) {
04715          res = ast_module_reload(module);
04716          if (res == 0) {
04717             astman_send_error(s, m, "No such module.");
04718          } else if (res == 1) {
04719             astman_send_error(s, m, "Module does not support reload action.");
04720          } else {
04721             astman_send_ack(s, m, "Module reloaded.");
04722          }
04723       } else {
04724          ast_module_reload(NULL);   /* Reload all modules */
04725          astman_send_ack(s, m, "All modules reloaded");
04726       }
04727    } else
04728       astman_send_error(s, m, "Incomplete ModuleLoad action.");
04729    return 0;
04730 }

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

Definition at line 5378 of file manager.c.

References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.

Referenced by __init_manager().

05379 {
05380    /* Notify managers of change */
05381    char hint[512];
05382    ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten);
05383 
05384    manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state);
05385    return 0;
05386 }

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

Definition at line 1403 of file manager.c.

References CMP_MATCH, str, and mansession_session::username.

Referenced by __init_manager().

01404 {
01405    struct mansession_session *s = obj;
01406    char *str = arg;
01407    return !strcasecmp(s->username, str) ? CMP_MATCH : 0;
01408 }

static struct sockaddr_in* mansession_encode_sin_local ( const struct mansession s,
struct sockaddr_in *  sin_local 
) [static, read]
static enum ast_security_event_transport_type mansession_get_transport ( const struct mansession s  )  [static]
static void mansession_lock ( struct mansession s  )  [static]

Lock the 'mansession' structure.

Definition at line 2140 of file manager.c.

References ast_mutex_lock, and mansession::lock.

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

02141 {
02142    ast_mutex_lock(&s->lock);
02143 }

static void mansession_unlock ( struct mansession s  )  [static]

Unlock the 'mansession' structure.

Definition at line 2146 of file manager.c.

References ast_mutex_unlock, and mansession::lock.

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

02147 {
02148    ast_mutex_unlock(&s->lock);
02149 }

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

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

04378 {
04379    int result = 0;
04380 
04381    ast_debug(3, "Examining event:\n%s\n", eventdata);
04382    if (!ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) {
04383       return 1; /* no filtering means match all */
04384    } else if (ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) {
04385       /* white filters only: implied black all filter processed first, then white filters */
04386       ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04387    } else if (!ao2_container_count(s->session->whitefilters) && ao2_container_count(s->session->blackfilters)) {
04388       /* black filters only: implied white all filter processed first, then black filters */
04389       ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04390    } else {
04391       /* white and black filters: implied black all filter processed first, then white filters, and lastly black filters */
04392       ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04393       if (result) {
04394          result = 0;
04395          ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04396       }
04397    }
04398 
04399    return result;
04400 }

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

04408 {
04409    int ret = 0;
04410 
04411    ao2_lock(s->session);
04412    if (s->session->f != NULL) {
04413       struct eventqent *eqe = s->session->last_ev;
04414 
04415       while ((eqe = advance_event(eqe))) {
04416          if (!ret && s->session->authenticated &&
04417              (s->session->readperm & eqe->category) == eqe->category &&
04418              (s->session->send_events & eqe->category) == eqe->category) {
04419                if (match_filter(s, eqe->eventdata)) {
04420                   if (send_string(s, eqe->eventdata) < 0)
04421                      ret = -1;   /* don't send more */
04422                }
04423          }
04424          s->session->last_ev = eqe;
04425       }
04426    }
04427    ao2_unlock(s->session);
04428    return ret;
04429 }

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

Definition at line 4745 of file manager.c.

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

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

04746 {
04747    int ret = 0;
04748    struct manager_action *act_found;
04749    const char *user;
04750    const char *action;
04751 
04752    action = __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY);
04753    if (ast_strlen_zero(action)) {
04754       report_req_bad_format(s, "NONE");
04755       mansession_lock(s);
04756       astman_send_error(s, m, "Missing action in request");
04757       mansession_unlock(s);
04758       return 0;
04759    }
04760 
04761    if (!s->session->authenticated
04762       && strcasecmp(action, "Login")
04763       && strcasecmp(action, "Logoff")
04764       && strcasecmp(action, "Challenge")) {
04765       if (!s->session->authenticated) {
04766          report_req_not_allowed(s, action);
04767       }
04768       mansession_lock(s);
04769       astman_send_error(s, m, "Permission denied");
04770       mansession_unlock(s);
04771       return 0;
04772    }
04773 
04774    if (!allowmultiplelogin
04775       && !s->session->authenticated
04776       && (!strcasecmp(action, "Login")
04777          || !strcasecmp(action, "Challenge"))) {
04778       user = astman_get_header(m, "Username");
04779 
04780       if (!ast_strlen_zero(user) && check_manager_session_inuse(user)) {
04781          report_session_limit(s);
04782          sleep(1);
04783          mansession_lock(s);
04784          astman_send_error(s, m, "Login Already In Use");
04785          mansession_unlock(s);
04786          return -1;
04787       }
04788    }
04789 
04790    act_found = action_find(action);
04791    if (act_found) {
04792       /* Found the requested AMI action. */
04793       int acted = 0;
04794 
04795       if ((s->session->writeperm & act_found->authority)
04796          || act_found->authority == 0) {
04797          /* We have the authority to execute the action. */
04798          ao2_lock(act_found);
04799          if (act_found->registered && act_found->func) {
04800             ast_debug(1, "Running action '%s'\n", act_found->action);
04801             ++act_found->active_count;
04802             ao2_unlock(act_found);
04803             ret = act_found->func(s, m);
04804             acted = 1;
04805             ao2_lock(act_found);
04806             --act_found->active_count;
04807          }
04808          ao2_unlock(act_found);
04809       }
04810       if (!acted) {
04811          /*
04812           * We did not execute the action because access was denied, it
04813           * was no longer registered, or no action was really registered.
04814           * Complain about it and leave.
04815           */
04816          report_req_not_allowed(s, action);
04817          mansession_lock(s);
04818          astman_send_error(s, m, "Permission denied");
04819          mansession_unlock(s);
04820       }
04821       ao2_t_ref(act_found, -1, "done with found action object");
04822    } else {
04823       char buf[512];
04824 
04825       report_req_bad_format(s, action);
04826       snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action);
04827       mansession_lock(s);
04828       astman_send_error(s, m, buf);
04829       mansession_unlock(s);
04830    }
04831    if (ret) {
04832       return ret;
04833    }
04834    /* Once done with our message, deliver any pending events unless the
04835       requester doesn't want them as part of this response.
04836    */
04837    if (ast_strlen_zero(astman_get_header(m, "SuppressEvents"))) {
04838       return process_events(s);
04839    } else {
04840       return ret;
04841    }
04842 }

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

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

Referenced by purge_old_stuff().

01140 {
01141    struct eventqent *ev;
01142    struct timeval now = ast_tvnow();
01143 
01144    AST_RWLIST_WRLOCK(&all_events);
01145    while ( (ev = AST_RWLIST_FIRST(&all_events)) &&
01146        ev->usecount == 0 && AST_RWLIST_NEXT(ev, eq_next)) {
01147       AST_RWLIST_REMOVE_HEAD(&all_events, eq_next);
01148       ast_free(ev);
01149    }
01150 
01151    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&all_events, ev, eq_next) {
01152       /* Never release the last event */
01153       if (!AST_RWLIST_NEXT(ev, eq_next)) {
01154          break;
01155       }
01156 
01157       /* 2.5 times whatever the HTTP timeout is (maximum 2.5 hours) is the maximum time that we will definitely cache an event */
01158       if (ev->usecount == 0 && ast_tvdiff_sec(now, ev->tv) > (httptimeout > 3600 ? 3600 : httptimeout) * 2.5) {
01159          AST_RWLIST_REMOVE_CURRENT(eq_next);
01160          ast_free(ev);
01161       }
01162    }
01163    AST_RWLIST_TRAVERSE_SAFE_END;
01164    AST_RWLIST_UNLOCK(&all_events);
01165 }

static void purge_sessions ( int  n_max  )  [static]

remove at most n_max stale session from the list.

Definition at line 5155 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(), sessions, mansession_session::sessiontimeout, mansession_session::sin, unref_mansession(), mansession_session::username, and VERBOSITY_ATLEAST.

Referenced by purge_old_stuff().

05156 {
05157    struct mansession_session *session;
05158    time_t now = time(NULL);
05159    struct ao2_iterator i;
05160 
05161    if (!sessions) {
05162       return;
05163    }
05164 
05165    i = ao2_iterator_init(sessions, 0);
05166    while ((session = ao2_iterator_next(&i)) && n_max > 0) {
05167       ao2_lock(session);
05168       if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) {
05169          if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) {
05170             ast_verb(2, "HTTP Manager '%s' timed out from %s\n",
05171                session->username, ast_inet_ntoa(session->sin.sin_addr));
05172          }
05173          ao2_unlock(session);
05174          session_destroy(session);
05175          n_max--;
05176       } else {
05177          ao2_unlock(session);
05178          unref_mansession(session);
05179       }
05180    }
05181    ao2_iterator_destroy(&i);
05182 }

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

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

02262 {
02263    struct sockaddr_in sin_local;
02264    char session_id[32];
02265    struct ast_security_event_successful_auth successful_auth = {
02266       .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH,
02267       .common.version    = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
02268       .common.service    = "AMI",
02269       .common.account_id = s->session->username,
02270       .common.session_tv = &s->session->sessionstart_tv,
02271       .common.local_addr = {
02272          .sin       = mansession_encode_sin_local(s, &sin_local),
02273          .transport = mansession_get_transport(s),
02274       },
02275       .common.remote_addr = {
02276          .sin       = &s->session->sin,
02277          .transport = mansession_get_transport(s),
02278       },
02279       .common.session_id = session_id,
02280    };
02281 
02282    snprintf(session_id, sizeof(session_id), "%p", s->session);
02283 
02284    ast_security_event_report(AST_SEC_EVT(&successful_auth));
02285 }

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

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

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

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

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

02349 {
02350    struct sockaddr_in sin_local;
02351    char session_id[32];
02352    struct ast_security_event_chal_resp_failed chal_resp_failed = {
02353       .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED,
02354       .common.version    = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
02355       .common.service    = "AMI",
02356       .common.account_id = s->session->username,
02357       .common.session_tv = &s->session->sessionstart_tv,
02358       .common.local_addr = {
02359          .sin       = mansession_encode_sin_local(s, &sin_local),
02360          .transport = mansession_get_transport(s),
02361       },
02362       .common.remote_addr = {
02363          .sin       = &s->session->sin,
02364          .transport = mansession_get_transport(s),
02365       },
02366       .common.session_id = session_id,
02367 
02368       .challenge         = s->session->challenge,
02369       .response          = response,
02370       .expected_response = expected_response,
02371    };
02372 
02373    snprintf(session_id, sizeof(session_id), "%p", s->session);
02374 
02375    ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
02376 }

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

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

02236 {
02237    struct sockaddr_in sin_local;
02238    char session_id[32];
02239    struct ast_security_event_inval_password inval_password = {
02240       .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD,
02241       .common.version    = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
02242       .common.service    = "AMI",
02243       .common.account_id = username,
02244       .common.session_tv = &s->session->sessionstart_tv,
02245       .common.local_addr = {
02246          .sin       = mansession_encode_sin_local(s, &sin_local),
02247          .transport = mansession_get_transport(s),
02248       },
02249       .common.remote_addr = {
02250          .sin       = &s->session->sin,
02251          .transport = mansession_get_transport(s),
02252       },
02253       .common.session_id = session_id,
02254    };
02255 
02256    snprintf(session_id, sizeof(session_id), "%p", s->session);
02257 
02258    ast_security_event_report(AST_SEC_EVT(&inval_password));
02259 }

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

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

02184 {
02185    struct sockaddr_in sin_local;
02186    char session_id[32];
02187    struct ast_security_event_inval_acct_id inval_acct_id = {
02188       .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID,
02189       .common.version    = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
02190       .common.service    = "AMI",
02191       .common.account_id = username,
02192       .common.session_tv = &s->session->sessionstart_tv,
02193       .common.local_addr = {
02194          .sin       = mansession_encode_sin_local(s, &sin_local),
02195          .transport = mansession_get_transport(s),
02196       },
02197       .common.remote_addr = {
02198          .sin       = &s->session->sin,
02199          .transport = mansession_get_transport(s),
02200       },
02201       .common.session_id = session_id,
02202    };
02203 
02204    snprintf(session_id, sizeof(session_id), "%p", s);
02205 
02206    ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
02207 }

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

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

02318 {
02319    struct sockaddr_in sin_local;
02320    char session_id[32];
02321    char request_type[64];
02322    struct ast_security_event_req_bad_format req_bad_format = {
02323       .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT,
02324       .common.version    = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
02325       .common.service    = "AMI",
02326       .common.account_id = s->session->username,
02327       .common.session_tv = &s->session->sessionstart_tv,
02328       .common.local_addr = {
02329          .sin       = mansession_encode_sin_local(s, &sin_local),
02330          .transport = mansession_get_transport(s),
02331       },
02332       .common.remote_addr = {
02333          .sin       = &s->session->sin,
02334          .transport = mansession_get_transport(s),
02335       },
02336       .common.session_id = session_id,
02337 
02338       .request_type      = request_type,
02339    };
02340 
02341    snprintf(session_id, sizeof(session_id), "%p", s->session);
02342    snprintf(request_type, sizeof(request_type), "Action: %s", action);
02343 
02344    ast_security_event_report(AST_SEC_EVT(&req_bad_format));
02345 }

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

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

02288 {
02289    struct sockaddr_in sin_local;
02290    char session_id[32];
02291    char request_type[64];
02292    struct ast_security_event_req_not_allowed req_not_allowed = {
02293       .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED,
02294       .common.version    = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
02295       .common.service    = "AMI",
02296       .common.account_id = s->session->username,
02297       .common.session_tv = &s->session->sessionstart_tv,
02298       .common.local_addr = {
02299          .sin       = mansession_encode_sin_local(s, &sin_local),
02300          .transport = mansession_get_transport(s),
02301       },
02302       .common.remote_addr = {
02303          .sin       = &s->session->sin,
02304          .transport = mansession_get_transport(s),
02305       },
02306       .common.session_id = session_id,
02307 
02308       .request_type      = request_type,
02309    };
02310 
02311    snprintf(session_id, sizeof(session_id), "%p", s->session);
02312    snprintf(request_type, sizeof(request_type), "Action: %s", action);
02313 
02314    ast_security_event_report(AST_SEC_EVT(&req_not_allowed));
02315 }

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

Definition at line 2378 of file manager.c.

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

Referenced by process_message().

02379 {
02380    struct sockaddr_in sin_local;
02381    char session_id[32];
02382    struct ast_security_event_session_limit session_limit = {
02383       .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT,
02384       .common.version    = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
02385       .common.service    = "AMI",
02386       .common.account_id = s->session->username,
02387       .common.session_tv = &s->session->sessionstart_tv,
02388       .common.local_addr = {
02389          .sin       = mansession_encode_sin_local(s, &sin_local),
02390          .transport = mansession_get_transport(s),
02391       },
02392       .common.remote_addr = {
02393          .sin       = &s->session->sin,
02394          .transport = mansession_get_transport(s),
02395       },
02396       .common.session_id = session_id,
02397    };
02398 
02399    snprintf(session_id, sizeof(session_id), "%p", s->session);
02400 
02401    ast_security_event_report(AST_SEC_EVT(&session_limit));
02402 }

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

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

Referenced by astman_append(), and process_events().

02019 {
02020    int res;
02021    FILE *f = s->f ? s->f : s->session->f;
02022    int fd = s->f ? s->fd : s->session->fd;
02023 
02024    /* It's a result from one of the hook's action invocation */
02025    if (s->hook) {
02026       /*
02027        * to send responses, we're using the same function
02028        * as for receiving events. We call the event "HookResponse"
02029        */
02030       s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string);
02031       return 0;
02032    }
02033        
02034    if ((res = ast_careful_fwrite(f, fd, string, strlen(string), s->session->writetimeout))) {
02035       s->write_error = 1;
02036    }
02037 
02038    return res;
02039 }

static void session_destroy ( struct mansession_session s  )  [static]

Definition at line 1410 of file manager.c.

References ao2_unlink, sessions, and unref_mansession().

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

01411 {
01412    unref_mansession(s);
01413    ao2_unlink(sessions, s);
01414 }

static void session_destructor ( void *  obj  )  [static]

Definition at line 1343 of file manager.c.

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

Referenced by build_mansession().

01344 {
01345    struct mansession_session *session = obj;
01346    struct eventqent *eqe = session->last_ev;
01347    struct ast_datastore *datastore;
01348 
01349    /* Get rid of each of the data stores on the session */
01350    while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) {
01351       /* Free the data store */
01352       ast_datastore_free(datastore);
01353    }
01354 
01355    if (session->f != NULL) {
01356       fclose(session->f);
01357    }
01358    if (eqe) {
01359       ast_atomic_fetchadd_int(&eqe->usecount, -1);
01360    }
01361 
01362    if (session->whitefilters) {
01363       ao2_t_callback(session->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters");
01364       ao2_t_ref(session->whitefilters, -1 , "decrement ref for white container, should be last one");
01365    }
01366 
01367    if (session->blackfilters) {
01368       ao2_t_callback(session->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters");
01369       ao2_t_ref(session->blackfilters, -1 , "decrement ref for black container, should be last one");
01370    }
01371 }

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

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

05057 {
05058    struct ast_tcptls_session_instance *ser = data;
05059    struct mansession_session *session;
05060    struct mansession s = {
05061       .tcptls_session = data,
05062    };
05063    int flags;
05064    int res;
05065    struct sockaddr_in ser_remote_address_tmp;
05066    struct protoent *p;
05067 
05068    if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
05069       fclose(ser->f);
05070       ast_atomic_fetchadd_int(&unauth_sessions, -1);
05071       goto done;
05072    }
05073 
05074    ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
05075    session = build_mansession(ser_remote_address_tmp);
05076 
05077    if (session == NULL) {
05078       fclose(ser->f);
05079       ast_atomic_fetchadd_int(&unauth_sessions, -1);
05080       goto done;
05081    }
05082 
05083    /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
05084     * This is necessary to prevent delays (caused by buffering) as we
05085     * write to the socket in bits and peices. */
05086    p = getprotobyname("tcp");
05087    if (p) {
05088       int arg = 1;
05089       if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
05090          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));
05091       }
05092    } else {
05093       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");
05094    }
05095 
05096    flags = fcntl(ser->fd, F_GETFL);
05097    if (!block_sockets) { /* make sure socket is non-blocking */
05098       flags |= O_NONBLOCK;
05099    } else {
05100       flags &= ~O_NONBLOCK;
05101    }
05102    fcntl(ser->fd, F_SETFL, flags);
05103 
05104    ao2_lock(session);
05105    /* Hook to the tail of the event queue */
05106    session->last_ev = grab_last();
05107 
05108    ast_mutex_init(&s.lock);
05109 
05110    /* these fields duplicate those in the 'ser' structure */
05111    session->fd = s.fd = ser->fd;
05112    session->f = s.f = ser->f;
05113    session->sin = ser_remote_address_tmp;
05114    s.session = session;
05115 
05116    AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
05117 
05118    if(time(&session->authstart) == -1) {
05119       ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
05120       ast_atomic_fetchadd_int(&unauth_sessions, -1);
05121       ao2_unlock(session);
05122       session_destroy(session);
05123       goto done;
05124    }
05125    ao2_unlock(session);
05126 
05127    astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION);   /* welcome prompt */
05128    for (;;) {
05129       if ((res = do_message(&s)) < 0 || s.write_error) {
05130          break;
05131       }
05132    }
05133    /* session is over, explain why and terminate */
05134    if (session->authenticated) {
05135       if (manager_displayconnects(session)) {
05136          ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
05137       }
05138    } else {
05139       ast_atomic_fetchadd_int(&unauth_sessions, -1);
05140       if (displayconnects) {
05141          ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
05142       }
05143    }
05144 
05145    session_destroy(session);
05146 
05147    ast_mutex_destroy(&s.lock);
05148 done:
05149    ao2_ref(ser, -1);
05150    ser = NULL;
05151    return NULL;
05152 }

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

02156 {
02157    int maskint = strings_to_mask(eventmask);
02158 
02159    ao2_lock(s->session);
02160    if (maskint >= 0) {
02161       s->session->send_events = maskint;
02162    }
02163    ao2_unlock(s->session);
02164 
02165    return maskint;
02166 }

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

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

Referenced by set_eventmask().

01298 {
01299    const char *p;
01300 
01301    if (ast_strlen_zero(string)) {
01302       return -1;
01303    }
01304 
01305    for (p = string; *p; p++) {
01306       if (*p < '0' || *p > '9') {
01307          break;
01308       }
01309    }
01310    if (!*p) { /* all digits */
01311       return atoi(string);
01312    }
01313    if (ast_false(string)) {
01314       return 0;
01315    }
01316    if (ast_true(string)) { /* all permissions */
01317       int x, ret = 0;
01318       for (x = 0; x < ARRAY_LEN(perms); x++) {
01319          ret |= perms[x].num;
01320       }
01321       return ret;
01322    }
01323    return get_perm(string);
01324 }

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

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

Definition at line 1328 of file manager.c.

References ao2_ref, ast_log(), and LOG_DEBUG.

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

01329 {
01330    int refcount = ao2_ref(s, -1);
01331         if (manager_debug) {
01332       ast_log(LOG_DEBUG, "Mansession: %p refcount now %d\n", s, refcount - 1);
01333    }
01334    return s;
01335 }

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

Convert authority code to a list of options for a user. This will only display those authority codes that have an explicit match on authority.

Definition at line 1211 of file manager.c.

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

Referenced by handle_showmanager().

01212 {
01213    int i;
01214    char *sep = "";
01215 
01216    ast_str_reset(*res);
01217    for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
01218       if ((authority & perms[i].num) == perms[i].num) {
01219          ast_str_append(res, 0, "%s%s", sep, perms[i].label);
01220          sep = ",";
01221       }
01222    }
01223 
01224    if (ast_str_strlen(*res) == 0)   /* replace empty string with something sensible */
01225       ast_str_append(res, 0, "<none>");
01226 
01227    return ast_str_buffer(*res);
01228 }

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

Definition at line 4348 of file manager.c.

References CMP_MATCH, and CMP_STOP.

Referenced by match_filter().

04349 {
04350    regex_t *regex_filter = obj;
04351    const char *eventdata = arg;
04352    int *result = data;
04353 
04354    if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
04355       *result = 1;
04356       return (CMP_MATCH | CMP_STOP);
04357    }
04358 
04359    return 0;
04360 }


Variable Documentation

int allowmultiplelogin = 1 [static]

Definition at line 899 of file manager.c.

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

Definition at line 2048 of file manager.c.

Referenced by astman_append().

int authlimit [static]

Definition at line 907 of file manager.c.

int authtimeout [static]

Definition at line 906 of file manager.c.

int block_sockets [static]

Definition at line 913 of file manager.c.

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

int broken_events_action [static]

Definition at line 902 of file manager.c.

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

Referenced by check_blacklist().

const int DEFAULT_AUTHLIMIT = 50 [static]

Default setting for authlimit

Definition at line 895 of file manager.c.

Referenced by reload_config().

const int DEFAULT_AUTHTIMEOUT = 30 [static]

Default setting for authtimeout

Definition at line 894 of file manager.c.

Referenced by reload_config().

const int DEFAULT_BLOCKSOCKETS = 0 [static]

Default setting for block-sockets

Definition at line 889 of file manager.c.

const int DEFAULT_BROKENEVENTSACTION = 0 [static]

Default setting for brokeneventsaction

Definition at line 893 of file manager.c.

const int DEFAULT_DISPLAYCONNECTS = 1 [static]

Default setting for displaying manager connections

Definition at line 890 of file manager.c.

const int DEFAULT_ENABLED = 0 [static]

Default setting for manager to be enabled

Definition at line 887 of file manager.c.

const int DEFAULT_HTTPTIMEOUT = 60 [static]

Default manager http timeout

Definition at line 892 of file manager.c.

const int DEFAULT_MANAGERDEBUG = 0 [static]

Default setting for manager debug

Definition at line 896 of file manager.c.

const int DEFAULT_TIMESTAMPEVENTS = 0 [static]

Default setting for timestampevents

Definition at line 891 of file manager.c.

const int DEFAULT_WEBENABLED = 0 [static]

Default setting for the web interface to be enabled

Definition at line 888 of file manager.c.

int displayconnects [static]

Definition at line 898 of file manager.c.

char global_realm[MAXHOSTNAMELEN] [static]

Default realm

Definition at line 911 of file manager.c.

Referenced by __init_manager(), and auth_http_callback().

int httptimeout [static]

Definition at line 901 of file manager.c.

char* manager_channelvars [static]

Definition at line 908 of file manager.c.

int manager_debug = 0 [static]

enable some debugging code in the manager

Definition at line 905 of file manager.c.

int manager_enabled = 0 [static]

Definition at line 903 of file manager.c.

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

Definition at line 5239 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 5212 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(), strings_to_mask(), and user_authority_to_str().

struct ao2_container* sessions = NULL [static]
int timestampevents [static]

Definition at line 900 of file manager.c.

int unauth_sessions = 0 [static]

Definition at line 914 of file manager.c.

Referenced by action_login(), and session_do().

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

Definition at line 2049 of file manager.c.

Referenced by action_userevent().

int webmanager_enabled = 0 [static]

Definition at line 904 of file manager.c.

const char* words[AST_MAX_CMD_LEN] [inherited]

Definition at line 929 of file manager.c.


Generated on 3 Apr 2014 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1