Tue Aug 20 16:35:18 2013

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

Referenced by astman_get_header().

#define GET_HEADER_LAST_MATCH   1

Definition at line 1801 of file manager.c.

Referenced by __astman_get_header().

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 1802 of file manager.c.

Referenced by __astman_get_header(), and process_message().

#define MANAGER_EVENT_BUF_INITSIZE   256

Definition at line 5235 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 2088 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 5237 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.

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

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

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

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

02053 {

static void __init_manager_event_buf ( void   )  [static]

Definition at line 5234 of file manager.c.

05239 {

static void __init_manager_event_funcbuf ( void   )  [static]

Definition at line 5207 of file manager.c.

05210 {

static void __init_userevent_buf ( void   )  [static]

Definition at line 2044 of file manager.c.

02053 {

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

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

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

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

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

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

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

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

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

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

Manager command "command" - execute CLI command.

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

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

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

Show PBX core settings information.

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

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

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

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

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

Show PBX core status information.

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

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

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

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

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

static void action_destroy ( void *  obj  )  [static]

Definition at line 5426 of file manager.c.

References ast_string_field_free_memory.

Referenced by ast_manager_register2().

05427 {
05428    struct manager_action *doomed = obj;
05429 
05430    if (doomed->synopsis) {
05431       /* The string fields were initialized. */
05432       ast_string_field_free_memory(doomed);
05433    }
05434 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 3090 of file manager.c.

References astman_send_response().

Referenced by __init_manager().

03091 {
03092    astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
03093    return -1;
03094 }

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

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

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

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

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

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

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

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

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

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

Definition at line 2503 of file manager.c.

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

Referenced by __init_manager().

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

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

action_redirect: The redirect manager command

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

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

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

Send a reload event.

Definition at line 4528 of file manager.c.

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

Referenced by __init_manager().

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

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

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

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

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

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

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

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

Manager "status" command to show channels.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

01788 {
01789    struct eventqent *next;
01790 
01791    AST_RWLIST_RDLOCK(&all_events);
01792    if ((next = AST_RWLIST_NEXT(e, eq_next))) {
01793       ast_atomic_fetchadd_int(&next->usecount, 1);
01794       ast_atomic_fetchadd_int(&e->usecount, -1);
01795    }
01796    AST_RWLIST_UNLOCK(&all_events);
01797    return next;
01798 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

int ast_manager_unregister ( char *  action  ) 

Unregister a registered manager command.

Parameters:
action Name of registered Action:

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

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

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

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

Referenced by __iax2_show_peers(), _sip_show_peer(), _sip_show_peers(), _skinny_show_device(), _skinny_show_devices(), _skinny_show_line(), _skinny_show_lines(), action_agents(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_dahdishowchannels(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_listcategories(), action_listcommands(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_ping(), 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().

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

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

Definition at line 2622 of file manager.c.

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

Referenced by action_getconfigjson().

02623 {
02624    char *buf;
02625 
02626    buf = ast_alloca(2 * strlen(str) + 1);
02627    json_escape(buf, str);
02628    astman_append(s, "%s", buf);
02629 }

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

01855 {
01856    return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH);
01857 }

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

Get a linked list of the Variable: headers.

Definition at line 1912 of file manager.c.

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

Referenced by action_originate(), and manager_sipnotify().

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

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

02115 {
02116    astman_send_response_full(s, m, "Error", error, NULL);
02117 }

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

References astman_send_response_full().

Referenced by action_logoff(), and action_waitevent().

02110 {
02111    astman_send_response_full(s, m, resp, msg, NULL);
02112 }

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

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

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

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

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

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

References CMP_MATCH, and CMP_STOP.

Referenced by match_filter().

04358 {
04359    regex_t *regex_filter = obj;
04360    const char *eventdata = arg;
04361    int *result = data;
04362 
04363    if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
04364       *result = 0;
04365       return (CMP_MATCH | CMP_STOP);
04366    }
04367 
04368    *result = 1;
04369    return 0;
04370 }

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

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

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

03812 {
03813    ast_variables_destroy(doomed->vars);
03814    ast_string_field_free_memory(doomed);
03815    ast_free(doomed);
03816 }

static int do_message ( struct mansession s  )  [static]

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

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

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

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

static void free_channelvars ( void   )  [static]

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

07223 {
07224    struct manager_channel_variable *var;
07225    AST_RWLIST_WRLOCK(&channelvars);
07226    while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) {
07227       ast_free(var);
07228    }
07229    AST_RWLIST_UNLOCK(&channelvars);
07230 }

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

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

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

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

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

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

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

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

Definition at line 4946 of file manager.c.

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

Referenced by do_message().

04947 {
04948    mansession_lock(s);
04949    astman_send_error(s, m, error);
04950    s->parsing = MESSAGE_OKAY;
04951    mansession_unlock(s);
04952 }

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

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

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

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

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

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

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_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, 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                ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n",
01516                   syntax_title,
01517                   ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1),
01518                   synopsis_title,
01519                   ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1),
01520                   description_title,
01521                   ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1),
01522                   arguments_title,
01523                   ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1),
01524                   seealso_title,
01525                   ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1));
01526             } else
01527 #endif
01528             {
01529                ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
01530                   cur->action, cur->synopsis,
01531                   authority_to_str(cur->authority, &authority),
01532                   S_OR(cur->description, ""));
01533             }
01534          }
01535       }
01536    }
01537    AST_RWLIST_UNLOCK(&actions);
01538 
01539    return CLI_SUCCESS;
01540 }

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

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

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

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

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

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

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

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

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

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

Referenced by astman_append_json().

02603 {
02604    for (; *in; in++) {
02605       if (*in == '\\' || *in == '\"') {
02606          *out++ = '\\';
02607       }
02608       *out++ = *in;
02609    }
02610    *out = '\0';
02611 }

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

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

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

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

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

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

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

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

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

Definition at line 5373 of file manager.c.

References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.

Referenced by __init_manager().

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

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

References ast_mutex_lock, and mansession::lock.

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

02136 {
02137    ast_mutex_lock(&s->lock);
02138 }

static void mansession_unlock ( struct mansession s  )  [static]

Unlock the 'mansession' structure.

Definition at line 2141 of file manager.c.

References ast_mutex_unlock, and mansession::lock.

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

02142 {
02143    ast_mutex_unlock(&s->lock);
02144 }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

02151 {
02152    int maskint = strings_to_mask(eventmask);
02153 
02154    ao2_lock(s->session);
02155    if (maskint >= 0) {
02156       s->session->send_events = maskint;
02157    }
02158    ao2_unlock(s->session);
02159 
02160    return maskint;
02161 }

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

References CMP_MATCH, and CMP_STOP.

Referenced by match_filter().

04344 {
04345    regex_t *regex_filter = obj;
04346    const char *eventdata = arg;
04347    int *result = data;
04348 
04349    if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
04350       *result = 1;
04351       return (CMP_MATCH | CMP_STOP);
04352    }
04353 
04354    return 0;
04355 }


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 2043 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 5234 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 5207 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 2044 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 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1