Thu Apr 16 06:48:10 2015

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 __fini_actions (void)
static void __fini_all_events (void)
static void __fini_channelvars (void)
static void __fini_manager_hooks (void)
static void __fini_users (void)
static void __init_actions (void)
static void __init_all_events (void)
static void __init_astman_append_buf (void)
 thread local buffer for astman_append
static void __init_channelvars (void)
static void __init_manager_event_buf (void)
static void __init_manager_event_funcbuf (void)
static void __init_manager_hooks (void)
static void __init_userevent_buf (void)
static void __init_users (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.
struct ast_variableastman_get_variables_order (const struct message *m, enum variable_orders order)
 Get a linked list of the Variable: headers with order specified.
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 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_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 2063 of file manager.c.

Referenced by astman_append().

#define DEFAULT_REALM   "asterisk"

Definition at line 911 of file manager.c.

Referenced by manager_set_defaults(), and reload_config().

#define GET_HEADER_FIRST_MATCH   0

Definition at line 1806 of file manager.c.

Referenced by astman_get_header().

#define GET_HEADER_LAST_MATCH   1

Definition at line 1807 of file manager.c.

Referenced by __astman_get_header().

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 1808 of file manager.c.

Referenced by __astman_get_header(), and process_message().

#define MANAGER_EVENT_BUF_INITSIZE   256

Definition at line 5266 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 2104 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 844 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 5268 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, unref_mansession(), and mansession_session::waiting_thread.

05270 {
05271    struct mansession_session *session;
05272    struct manager_custom_hook *hook;
05273    struct ast_str *auth = ast_str_alloca(80);
05274    const char *cat_str;
05275    va_list ap;
05276    struct timeval now;
05277    struct ast_str *buf;
05278    int i;
05279 
05280    if (!(sessions && ao2_container_count(sessions)) && AST_RWLIST_EMPTY(&manager_hooks)) {
05281       return 0;
05282    }
05283    
05284    if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) {
05285       return -1;
05286    }
05287 
05288    cat_str = authority_to_str(category, &auth);
05289    ast_str_set(&buf, 0,
05290          "Event: %s\r\nPrivilege: %s\r\n",
05291           event, cat_str);
05292 
05293    if (timestampevents) {
05294       now = ast_tvnow();
05295       ast_str_append(&buf, 0,
05296             "Timestamp: %ld.%06lu\r\n",
05297              (long)now.tv_sec, (unsigned long) now.tv_usec);
05298    }
05299    if (manager_debug) {
05300       static int seq;
05301       ast_str_append(&buf, 0,
05302             "SequenceNumber: %d\r\n",
05303              ast_atomic_fetchadd_int(&seq, 1));
05304       ast_str_append(&buf, 0,
05305             "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func);
05306    }
05307 
05308    va_start(ap, fmt);
05309    ast_str_append_va(&buf, 0, fmt, ap);
05310    va_end(ap);
05311    for (i = 0; i < chancount; i++) {
05312       append_channel_vars(&buf, chans[i]);
05313    }
05314 
05315    ast_str_append(&buf, 0, "\r\n");
05316 
05317    append_event(ast_str_buffer(buf), category);
05318 
05319    /* Wake up any sleeping sessions */
05320    if (sessions) {
05321       struct ao2_iterator i;
05322       i = ao2_iterator_init(sessions, 0);
05323       while ((session = ao2_iterator_next(&i))) {
05324          ao2_lock(session);
05325          if (session->waiting_thread != AST_PTHREADT_NULL) {
05326             pthread_kill(session->waiting_thread, SIGURG);
05327          } else {
05328             /* We have an event to process, but the mansession is
05329              * not waiting for it. We still need to indicate that there
05330              * is an event waiting so that get_input processes the pending
05331              * event instead of polling.
05332              */
05333             session->pending_event = 1;
05334          }
05335          ao2_unlock(session);
05336          unref_mansession(session);
05337       }
05338       ao2_iterator_destroy(&i);
05339    }
05340 
05341    if (!AST_RWLIST_EMPTY(&manager_hooks)) {
05342       AST_RWLIST_RDLOCK(&manager_hooks);
05343       AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) {
05344          hook->helper(category, event, ast_str_buffer(buf));
05345       }
05346       AST_RWLIST_UNLOCK(&manager_hooks);
05347    }
05348 
05349    return 0;
05350 }

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

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

static void __fini_actions ( void   )  [static]

Definition at line 1058 of file manager.c.

01076 {

static void __fini_all_events ( void   )  [static]

Definition at line 887 of file manager.c.

00928 {

static void __fini_channelvars ( void   )  [static]

Definition at line 1031 of file manager.c.

01039 {

static void __fini_manager_hooks ( void   )  [static]

Definition at line 1061 of file manager.c.

01076 {

static void __fini_users ( void   )  [static]

Definition at line 1055 of file manager.c.

01076 {

static void __init_actions ( void   )  [static]

Definition at line 1058 of file manager.c.

01076 {

static void __init_all_events ( void   )  [static]

Definition at line 887 of file manager.c.

00928 {

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

02069 {

static void __init_channelvars ( void   )  [static]

Definition at line 1031 of file manager.c.

01039 {

static void __init_manager_event_buf ( void   )  [static]

Definition at line 5265 of file manager.c.

05270 {

static void __init_manager_event_funcbuf ( void   )  [static]

Definition at line 5238 of file manager.c.

05241 {

static void __init_manager_hooks ( void   )  [static]

Definition at line 1061 of file manager.c.

01076 {

static void __init_userevent_buf ( void   )  [static]

Definition at line 2060 of file manager.c.

02069 {

static void __init_users ( void   )  [static]

Definition at line 1055 of file manager.c.

01076 {

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

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

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

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

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

03648 {
03649    const char *name = astman_get_header(m, "Channel");
03650    const char *exten = astman_get_header(m, "Exten");
03651    const char *context = astman_get_header(m, "Context");
03652    struct ast_channel *chan = NULL;
03653    struct ast_call_feature *atxfer_feature = NULL;
03654    char *feature_code = NULL;
03655 
03656    if (ast_strlen_zero(name)) {
03657       astman_send_error(s, m, "No channel specified");
03658       return 0;
03659    }
03660    if (ast_strlen_zero(exten)) {
03661       astman_send_error(s, m, "No extension specified");
03662       return 0;
03663    }
03664 
03665    if (!(atxfer_feature = ast_find_call_feature("atxfer"))) {
03666       astman_send_error(s, m, "No attended transfer feature found");
03667       return 0;
03668    }
03669 
03670    if (!(chan = ast_channel_get_by_name(name))) {
03671       astman_send_error(s, m, "Channel specified does not exist");
03672       return 0;
03673    }
03674 
03675    if (!ast_strlen_zero(context)) {
03676       pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context);
03677    }
03678 
03679    for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) {
03680       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code };
03681       ast_queue_frame(chan, &f);
03682    }
03683 
03684    for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) {
03685       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code };
03686       ast_queue_frame(chan, &f);
03687    }
03688 
03689    chan = ast_channel_unref(chan);
03690 
03691    astman_send_ack(s, m, "Atxfer successfully queued");
03692 
03693    return 0;
03694 }

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

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

03150 {
03151    const char *authtype = astman_get_header(m, "AuthType");
03152 
03153    if (!strcasecmp(authtype, "MD5")) {
03154       if (ast_strlen_zero(s->session->challenge)) {
03155          snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
03156       }
03157       mansession_lock(s);
03158       astman_start_ack(s, m);
03159       astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
03160       mansession_unlock(s);
03161    } else {
03162       astman_send_error(s, m, "Must specify AuthType");
03163    }
03164    return 0;
03165 }

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

Manager command "command" - execute CLI command.

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

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

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

Show PBX core settings information.

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

04469 {
04470    const char *actionid = astman_get_header(m, "ActionID");
04471    char idText[150];
04472 
04473    if (!ast_strlen_zero(actionid)) {
04474       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
04475    } else {
04476       idText[0] = '\0';
04477    }
04478 
04479    astman_append(s, "Response: Success\r\n"
04480          "%s"
04481          "AMIversion: %s\r\n"
04482          "AsteriskVersion: %s\r\n"
04483          "SystemName: %s\r\n"
04484          "CoreMaxCalls: %d\r\n"
04485          "CoreMaxLoadAvg: %f\r\n"
04486          "CoreRunUser: %s\r\n"
04487          "CoreRunGroup: %s\r\n"
04488          "CoreMaxFilehandles: %d\r\n"
04489          "CoreRealTimeEnabled: %s\r\n"
04490          "CoreCDRenabled: %s\r\n"
04491          "CoreHTTPenabled: %s\r\n"
04492          "\r\n",
04493          idText,
04494          AMI_VERSION,
04495          ast_get_version(),
04496          ast_config_AST_SYSTEM_NAME,
04497          option_maxcalls,
04498          option_maxload,
04499          ast_config_AST_RUN_USER,
04500          ast_config_AST_RUN_GROUP,
04501          option_maxfiles,
04502          AST_CLI_YESNO(ast_realtime_enabled()),
04503          AST_CLI_YESNO(check_cdr_enabled()),
04504          AST_CLI_YESNO(check_webmanager_enabled())
04505          );
04506    return 0;
04507 }

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

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

Referenced by __init_manager().

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

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

Show PBX core status information.

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

04511 {
04512    const char *actionid = astman_get_header(m, "ActionID");
04513    char idText[150];
04514    char startuptime[150], startupdate[150];
04515    char reloadtime[150], reloaddate[150];
04516    struct ast_tm tm;
04517 
04518    if (!ast_strlen_zero(actionid)) {
04519       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
04520    } else {
04521       idText[0] = '\0';
04522    }
04523 
04524    ast_localtime(&ast_startuptime, &tm, NULL);
04525    ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm);
04526    ast_strftime(startupdate, sizeof(startupdate), "%Y-%m-%d", &tm);
04527    ast_localtime(&ast_lastreloadtime, &tm, NULL);
04528    ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm);
04529    ast_strftime(reloaddate, sizeof(reloaddate), "%Y-%m-%d", &tm);
04530 
04531    astman_append(s, "Response: Success\r\n"
04532          "%s"
04533          "CoreStartupDate: %s\r\n"
04534          "CoreStartupTime: %s\r\n"
04535          "CoreReloadDate: %s\r\n"
04536          "CoreReloadTime: %s\r\n"
04537          "CoreCurrentCalls: %d\r\n"
04538          "\r\n",
04539          idText,
04540          startupdate,
04541          startuptime,
04542          reloaddate,
04543          reloadtime,
04544          ast_active_channels()
04545          );
04546    return 0;
04547 }

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

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

02924 {
02925    int fd;
02926    const char *fn = astman_get_header(m, "Filename");
02927    struct ast_str *filepath = ast_str_alloca(PATH_MAX);
02928    ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR);
02929    ast_str_append(&filepath, 0, "%s", fn);
02930 
02931    if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
02932       close(fd);
02933       astman_send_ack(s, m, "New configuration file created successfully");
02934    } else {
02935       astman_send_error(s, m, strerror(errno));
02936    }
02937 
02938    return 0;
02939 }

static void action_destroy ( void *  obj  )  [static]

Definition at line 5457 of file manager.c.

References ast_string_field_free_memory.

Referenced by ast_manager_register2().

05458 {
05459    struct manager_action *doomed = obj;
05460 
05461    if (doomed->synopsis) {
05462       /* The string fields were initialized. */
05463       ast_string_field_free_memory(doomed);
05464    }
05465 }

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

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

03068 {
03069    const char *mask = astman_get_header(m, "EventMask");
03070    int res, x;
03071    const char *id = astman_get_header(m, "ActionID");
03072    char id_text[256];
03073 
03074    if (!ast_strlen_zero(id)) {
03075       snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
03076    } else {
03077       id_text[0] = '\0';
03078    }
03079 
03080    res = set_eventmask(s, mask);
03081    if (broken_events_action) {
03082       /* if this option is set we should not return a response on
03083        * error, or when all events are set */
03084 
03085       if (res > 0) {
03086          for (x = 0; x < ARRAY_LEN(perms); x++) {
03087             if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) {
03088                return 0;
03089             }
03090          }
03091          astman_append(s, "Response: Success\r\n%s"
03092                 "Events: On\r\n\r\n", id_text);
03093       } else if (res == 0)
03094          astman_append(s, "Response: Success\r\n%s"
03095                 "Events: Off\r\n\r\n", id_text);
03096       return 0;
03097    }
03098 
03099    if (res > 0)
03100       astman_append(s, "Response: Success\r\n%s"
03101              "Events: On\r\n\r\n", id_text);
03102    else if (res == 0)
03103       astman_append(s, "Response: Success\r\n%s"
03104              "Events: Off\r\n\r\n", id_text);
03105    else
03106       astman_send_error(s, m, "Invalid event mask");
03107 
03108    return 0;
03109 }

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

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

04307 {
04308    const char *exten = astman_get_header(m, "Exten");
04309    const char *context = astman_get_header(m, "Context");
04310    char hint[256] = "";
04311    int status;
04312    if (ast_strlen_zero(exten)) {
04313       astman_send_error(s, m, "Extension not specified");
04314       return 0;
04315    }
04316    if (ast_strlen_zero(context)) {
04317       context = "default";
04318    }
04319    status = ast_extension_state(NULL, context, exten);
04320    ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
04321    astman_start_ack(s, m);
04322    astman_append(s,   "Message: Extension Status\r\n"
04323             "Exten: %s\r\n"
04324             "Context: %s\r\n"
04325             "Hint: %s\r\n"
04326             "Status: %d\r\n\r\n",
04327             exten, context, hint, status);
04328    return 0;
04329 }

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

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

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

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

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

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

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

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

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

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

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

03244 {
03245    struct ast_channel *c = NULL;
03246    const char *name = astman_get_header(m, "Channel");
03247    const char *varname = astman_get_header(m, "Variable");
03248    char *varval;
03249    char workspace[1024];
03250 
03251    if (ast_strlen_zero(varname)) {
03252       astman_send_error(s, m, "No variable specified");
03253       return 0;
03254    }
03255 
03256    /* We don't want users with insufficient permissions using certain functions. */
03257    if (!(function_capable_string_allowed_with_auths(varname, s->session->writeperm))) {
03258       astman_send_error(s, m, "GetVar Access Forbidden: Variable");
03259       return 0;
03260    }
03261 
03262    if (!ast_strlen_zero(name)) {
03263       if (!(c = ast_channel_get_by_name(name))) {
03264          astman_send_error(s, m, "No such channel");
03265          return 0;
03266       }
03267    }
03268 
03269    workspace[0] = '\0';
03270    if (varname[strlen(varname) - 1] == ')') {
03271       if (!c) {
03272          c = ast_dummy_channel_alloc();
03273          if (c) {
03274             ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
03275          } else
03276             ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03277       } else {
03278          ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
03279       }
03280       varval = workspace;
03281    } else {
03282       pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
03283    }
03284 
03285    if (c) {
03286       c = ast_channel_unref(c);
03287    }
03288 
03289    astman_start_ack(s, m);
03290    astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, S_OR(varval, ""));
03291 
03292    return 0;
03293 }

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

Definition at line 3167 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, LOG_NOTICE, and ast_channel::name.

Referenced by __init_manager().

03168 {
03169    struct ast_channel *c = NULL;
03170    int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */
03171    const char *name = astman_get_header(m, "Channel");
03172    const char *cause = astman_get_header(m, "Cause");
03173 
03174    if (ast_strlen_zero(name)) {
03175       astman_send_error(s, m, "No channel specified");
03176       return 0;
03177    }
03178 
03179    if (!ast_strlen_zero(cause)) {
03180       char *endptr;
03181       causecode = strtol(cause, &endptr, 10);
03182       if (causecode < 0 || causecode > 127 || *endptr != '\0') {
03183          ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause);
03184          /* keep going, better to hangup without cause than to not hang up at all */
03185          causecode = 0; /* do not set channel's hangupcause */
03186       }
03187    }
03188 
03189    if (!(c = ast_channel_get_by_name(name))) {
03190       astman_send_error(s, m, "No such channel");
03191       return 0;
03192    }
03193 
03194    ast_channel_lock(c);
03195    if (causecode > 0) {
03196       ast_debug(1, "Setting hangupcause of channel %s to %d (is %d now)\n",
03197             c->name, causecode, c->hangupcause);
03198       c->hangupcause = causecode;
03199    }
03200    ast_softhangup_nolock(c, AST_SOFTHANGUP_EXPLICIT);
03201    ast_channel_unlock(c);
03202 
03203    c = ast_channel_unref(c);
03204 
03205    astman_send_ack(s, m, "Channel Hungup");
03206 
03207    return 0;
03208 }

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

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

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

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

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

03049 {
03050    struct manager_action *cur;
03051    struct ast_str *temp = ast_str_alloca(256);
03052 
03053    astman_start_ack(s, m);
03054    AST_RWLIST_RDLOCK(&actions);
03055    AST_RWLIST_TRAVERSE(&actions, cur, list) {
03056       if ((s->session->writeperm & cur->authority) || cur->authority == 0) {
03057          astman_append(s, "%s: %s (Priv: %s)\r\n",
03058             cur->action, cur->synopsis, authority_to_str(cur->authority, &temp));
03059       }
03060    }
03061    AST_RWLIST_UNLOCK(&actions);
03062    astman_append(s, "\r\n");
03063 
03064    return 0;
03065 }

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

Definition at line 3117 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::readperm, mansession_session::send_events, mansession::session, mansession_session::sin, unauth_sessions, and mansession_session::username.

Referenced by __init_manager().

03118 {
03119 
03120    /* still authenticated - don't process again */
03121    if (s->session->authenticated) {
03122       astman_send_ack(s, m, "Already authenticated");
03123       return 0;
03124    }
03125 
03126    if (authenticate(s, m)) {
03127       sleep(1);
03128       astman_send_error(s, m, "Authentication failed");
03129       return -1;
03130    }
03131    s->session->authenticated = 1;
03132    ast_atomic_fetchadd_int(&unauth_sessions, -1);
03133    if (manager_displayconnects(s->session)) {
03134       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));
03135    }
03136    astman_send_ack(s, m, "Authentication accepted");
03137    if ((s->session->send_events & EVENT_FLAG_SYSTEM)
03138       && (s->session->readperm & EVENT_FLAG_SYSTEM)
03139       && ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
03140       struct ast_str *auth = ast_str_alloca(80);
03141       const char *cat_str = authority_to_str(EVENT_FLAG_SYSTEM, &auth);
03142       astman_append(s, "Event: FullyBooted\r\n"
03143          "Privilege: %s\r\n"
03144          "Status: Fully Booted\r\n\r\n", cat_str);
03145    }
03146    return 0;
03147 }

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

Definition at line 3111 of file manager.c.

References astman_send_response().

Referenced by __init_manager().

03112 {
03113    astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
03114    return -1;
03115 }

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

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

04286 {
04287    const char *mailbox = astman_get_header(m, "Mailbox");
04288    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;;
04289 
04290    if (ast_strlen_zero(mailbox)) {
04291       astman_send_error(s, m, "Mailbox not specified");
04292       return 0;
04293    }
04294    ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs);
04295    astman_start_ack(s, m);
04296    astman_append(s,   "Message: Mailbox Message Count\r\n"
04297             "Mailbox: %s\r\n"
04298             "UrgMessages: %d\r\n"
04299             "NewMessages: %d\r\n"
04300             "OldMessages: %d\r\n"
04301             "\r\n",
04302             mailbox, urgentmsgs, newmsgs, oldmsgs);
04303    return 0;
04304 }

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

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

04269 {
04270    const char *mailbox = astman_get_header(m, "Mailbox");
04271    int ret;
04272 
04273    if (ast_strlen_zero(mailbox)) {
04274       astman_send_error(s, m, "Mailbox not specified");
04275       return 0;
04276    }
04277    ret = ast_app_has_voicemail(mailbox, NULL);
04278    astman_start_ack(s, m);
04279    astman_append(s, "Message: Mailbox Status\r\n"
04280           "Mailbox: %s\r\n"
04281           "Waiting: %d\r\n\r\n", mailbox, ret);
04282    return 0;
04283 }

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

Definition at line 4124 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, strcasestr(), fast_originate_helper::timeout, fast_originate_helper::vars, and mansession_session::writeperm.

Referenced by __init_manager().

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

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

Definition at line 2519 of file manager.c.

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

Referenced by __init_manager().

02520 {
02521    const char *actionid = astman_get_header(m, "ActionID");
02522    struct timeval now = ast_tvnow();
02523 
02524    astman_append(s, "Response: Success\r\n");
02525    if (!ast_strlen_zero(actionid)){
02526       astman_append(s, "ActionID: %s\r\n", actionid);
02527    }
02528    astman_append(
02529       s,
02530       "Ping: Pong\r\n"
02531       "Timestamp: %ld.%06lu\r\n"
02532       "\r\n",
02533       (long) now.tv_sec, (unsigned long) now.tv_usec);
02534    return 0;
02535 }

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

action_redirect: The redirect manager command

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

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

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

Send a reload event.

Definition at line 4550 of file manager.c.

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

Referenced by __init_manager().

04551 {
04552    const char *module = astman_get_header(m, "Module");
04553    int res = ast_module_reload(S_OR(module, NULL));
04554 
04555    switch (res) {
04556    case -1:
04557       astman_send_error(s, m, "A reload is in progress");
04558       break;
04559    case 0:
04560       astman_send_error(s, m, "No such module");
04561       break;
04562    case 1:
04563       astman_send_error(s, m, "Module does not support reload");
04564       break;
04565    case 2:
04566       astman_send_ack(s, m, "Module Reloaded");
04567       break;
04568    default:
04569       astman_send_error(s, m, "An unknown error occurred");
04570       break;
04571    }
04572    return 0;
04573 }

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

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

03460 {
03461    struct ast_channel *c = NULL;
03462    const char *name = astman_get_header(m, "Channel");
03463    const char *textmsg = astman_get_header(m, "Message");
03464    int res = 0;
03465 
03466    if (ast_strlen_zero(name)) {
03467       astman_send_error(s, m, "No channel specified");
03468       return 0;
03469    }
03470 
03471    if (ast_strlen_zero(textmsg)) {
03472       astman_send_error(s, m, "No Message specified");
03473       return 0;
03474    }
03475 
03476    if (!(c = ast_channel_get_by_name(name))) {
03477       astman_send_error(s, m, "No such channel");
03478       return 0;
03479    }
03480 
03481    res = ast_sendtext(c, textmsg);
03482    c = ast_channel_unref(c);
03483 
03484    if (res >= 0) {
03485       astman_send_ack(s, m, "Success");
03486    } else {
03487       astman_send_error(s, m, "Failure");
03488    }
03489 
03490    return 0;
03491 }

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

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

03211 {
03212    struct ast_channel *c = NULL;
03213    const char *name = astman_get_header(m, "Channel");
03214    const char *varname = astman_get_header(m, "Variable");
03215    const char *varval = astman_get_header(m, "Value");
03216    int res = 0;
03217    
03218    if (ast_strlen_zero(varname)) {
03219       astman_send_error(s, m, "No variable specified");
03220       return 0;
03221    }
03222 
03223    if (!ast_strlen_zero(name)) {
03224       if (!(c = ast_channel_get_by_name(name))) {
03225          astman_send_error(s, m, "No such channel");
03226          return 0;
03227       }
03228    }
03229 
03230    res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
03231 
03232    if (c) {
03233       c = ast_channel_unref(c);
03234    }
03235    if (res == 0) {
03236       astman_send_ack(s, m, "Variable Set"); 
03237    } else {
03238       astman_send_error(s, m, "Variable not set");
03239    }
03240    return 0;
03241 }

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

Manager "status" command to show channels.

Definition at line 3297 of file manager.c.

References ast_channel::_bridge, ast_channel::_state, ast_channel::accountcode, 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_channel::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_channel::uniqueid, ast_party_name::valid, ast_party_number::valid, and mansession_session::writeperm.

Referenced by __init_manager().

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

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

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

04332 {
04333    struct ast_channel *c;
04334    const char *name = astman_get_header(m, "Channel");
04335    double timeout = atof(astman_get_header(m, "Timeout"));
04336    struct timeval when = { timeout, 0 };
04337 
04338    if (ast_strlen_zero(name)) {
04339       astman_send_error(s, m, "No channel specified");
04340       return 0;
04341    }
04342 
04343    if (!timeout || timeout < 0) {
04344       astman_send_error(s, m, "No timeout specified");
04345       return 0;
04346    }
04347 
04348    if (!(c = ast_channel_get_by_name(name))) {
04349       astman_send_error(s, m, "No such channel");
04350       return 0;
04351    }
04352 
04353    when.tv_usec = (timeout - when.tv_sec) * 1000000.0;
04354 
04355    ast_channel_lock(c);
04356    ast_channel_setwhentohangup_tv(c, when);
04357    ast_channel_unlock(c);
04358    c = ast_channel_unref(c);
04359 
04360    astman_send_ack(s, m, "Timeout Set");
04361 
04362    return 0;
04363 }

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

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

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

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

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

04449 {
04450    const char *event = astman_get_header(m, "UserEvent");
04451    struct ast_str *body = ast_str_thread_get(&userevent_buf, 16);
04452    int x;
04453 
04454    ast_str_reset(body);
04455 
04456    for (x = 0; x < m->hdrcount; x++) {
04457       if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) {
04458          ast_str_append(&body, 0, "%s\r\n", m->headers[x]);
04459       }
04460    }
04461 
04462    astman_send_ack(s, m, "Event Sent");   
04463    manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, ast_str_buffer(body));
04464    return 0;
04465 }

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

Definition at line 2941 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, match_filter(), mansession_session::needdestroy, mansession_session::readperm, mansession_session::send_events, mansession::session, mansession_session::sessiontimeout, and mansession_session::waiting_thread.

Referenced by __init_manager().

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

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

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

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

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

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

03895 {
03896    const char *unitamount;
03897    const char *unittype;
03898    struct ast_str *str = ast_str_alloca(32);
03899 
03900    memset(entry, 0, sizeof(*entry));
03901 
03902    ast_str_set(&str, 0, "UnitAmount(%u)", entry_num);
03903    unitamount = astman_get_header(m, ast_str_buffer(str));
03904 
03905    ast_str_set(&str, 0, "UnitType(%u)", entry_num);
03906    unittype = astman_get_header(m, ast_str_buffer(str));
03907 
03908    if (!ast_strlen_zero(unitamount) && (sscanf(unitamount, "%30u", &entry->amount) == 1)) {
03909       entry->valid_amount = 1;
03910    }
03911 
03912    if (!ast_strlen_zero(unittype) && sscanf(unittype, "%30u", &entry->type) == 1) {
03913       entry->valid_type = 1;
03914    }
03915 
03916    return 0;
03917 }

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

Definition at line 5240 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, ast_channel::name, manager_channel_variable::name, pbx_builtin_getvar_helper(), and var.

Referenced by __ast_manager_event_multichan().

05241 {
05242    struct manager_channel_variable *var;
05243 
05244    AST_RWLIST_RDLOCK(&channelvars);
05245    AST_LIST_TRAVERSE(&channelvars, var, entry) {
05246       const char *val;
05247       struct ast_str *res;
05248 
05249       if (var->isfunc) {
05250          res = ast_str_thread_get(&manager_event_funcbuf, 16);
05251          if (res && ast_func_read2(chan, var->name, &res, 0) == 0) {
05252             val = ast_str_buffer(res);
05253          } else {
05254             val = NULL;
05255          }
05256       } else {
05257          val = pbx_builtin_getvar_helper(chan, var->name);
05258       }
05259       ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", chan->name, var->name, val ? val : "");
05260    }
05261    AST_RWLIST_UNLOCK(&channelvars);
05262 }

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

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

05215 {
05216    struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str));
05217    static int seq;   /* sequence number */
05218 
05219    if (!tmp) {
05220       return -1;
05221    }
05222 
05223    /* need to init all fields, because ast_malloc() does not */
05224    tmp->usecount = 0;
05225    tmp->category = category;
05226    tmp->seq = ast_atomic_fetchadd_int(&seq, 1);
05227    tmp->tv = ast_tvnow();
05228    AST_RWLIST_NEXT(tmp, eq_next) = NULL;
05229    strcpy(tmp->eventdata, str);
05230 
05231    AST_RWLIST_WRLOCK(&all_events);
05232    AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next);
05233    AST_RWLIST_UNLOCK(&all_events);
05234 
05235    return 0;
05236 }

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

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

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

References eventqent::next.

Referenced by get_perm().

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

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 5469 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, manager_action::authority, manager_action::docsrc, and manager_action::func.

Referenced by load_module().

05470 {
05471    struct manager_action *cur;
05472 
05473    cur = ao2_alloc(sizeof(*cur), action_destroy);
05474    if (!cur) {
05475       return -1;
05476    }
05477    if (ast_string_field_init(cur, 128)) {
05478       ao2_t_ref(cur, -1, "action object creation failed");
05479       return -1;
05480    }
05481 
05482    cur->action = action;
05483    cur->authority = auth;
05484    cur->func = func;
05485 #ifdef AST_XML_DOCS
05486    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
05487       char *tmpxml;
05488 
05489       tmpxml = ast_xmldoc_build_synopsis("manager", action, NULL);
05490       ast_string_field_set(cur, synopsis, tmpxml);
05491       ast_free(tmpxml);
05492 
05493       tmpxml = ast_xmldoc_build_syntax("manager", action, NULL);
05494       ast_string_field_set(cur, syntax, tmpxml);
05495       ast_free(tmpxml);
05496 
05497       tmpxml = ast_xmldoc_build_description("manager", action, NULL);
05498       ast_string_field_set(cur, description, tmpxml);
05499       ast_free(tmpxml);
05500 
05501       tmpxml = ast_xmldoc_build_seealso("manager", action, NULL);
05502       ast_string_field_set(cur, seealso, tmpxml);
05503       ast_free(tmpxml);
05504 
05505       tmpxml = ast_xmldoc_build_arguments("manager", action, NULL);
05506       ast_string_field_set(cur, arguments, tmpxml);
05507       ast_free(tmpxml);
05508 
05509       cur->docsrc = AST_XML_DOC;
05510    } else
05511 #endif
05512    {
05513       ast_string_field_set(cur, synopsis, synopsis);
05514       ast_string_field_set(cur, description, description);
05515 #ifdef AST_XML_DOCS
05516       cur->docsrc = AST_STATIC_DOC;
05517 #endif
05518    }
05519    if (ast_manager_register_struct(cur)) {
05520       ao2_t_ref(cur, -1, "action object registration failed");
05521       return -1;
05522    }
05523 
05524    ao2_t_ref(cur, -1, "action object registration successful");
05525    return 0;
05526 }

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 1092 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 5414 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().

05415 {
05416    struct manager_action *cur, *prev = NULL;
05417 
05418    AST_RWLIST_WRLOCK(&actions);
05419    AST_RWLIST_TRAVERSE(&actions, cur, list) {
05420       int ret;
05421 
05422       ret = strcasecmp(cur->action, act->action);
05423       if (ret == 0) {
05424          ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action);
05425          AST_RWLIST_UNLOCK(&actions);
05426          return -1;
05427       }
05428       if (ret > 0) { /* Insert these alphabetically */
05429          prev = cur;
05430          break;
05431       }
05432    }
05433 
05434    ao2_t_ref(act, +1, "action object added to list");
05435    act->registered = 1;
05436    if (prev) {
05437       AST_RWLIST_INSERT_AFTER(&actions, prev, act, list);
05438    } else {
05439       AST_RWLIST_INSERT_HEAD(&actions, act, list);
05440    }
05441 
05442    ast_verb(2, "Manager registered action %s\n", act->action);
05443 
05444    AST_RWLIST_UNLOCK(&actions);
05445 
05446    return 0;
05447 }

int ast_manager_unregister ( char *  action  ) 

Unregister a registered manager command.

Parameters:
action Name of registered Action:

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

05356 {
05357    struct manager_action *cur;
05358 
05359    AST_RWLIST_WRLOCK(&actions);
05360    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) {
05361       if (!strcasecmp(action, cur->action)) {
05362          AST_RWLIST_REMOVE_CURRENT(list);
05363          break;
05364       }
05365    }
05366    AST_RWLIST_TRAVERSE_SAFE_END;
05367    AST_RWLIST_UNLOCK(&actions);
05368 
05369    if (cur) {
05370       time_t now;
05371 
05372       /*
05373        * We have removed the action object from the container so we
05374        * are no longer in a hurry.
05375        */
05376       ao2_lock(cur);
05377       cur->registered = 0;
05378       ao2_unlock(cur);
05379 
05380       /*
05381        * Wait up to 5 seconds for any active invocations to complete
05382        * before returning.  We have to wait instead of blocking
05383        * because we may be waiting for ourself to complete.
05384        */
05385       now = time(NULL);
05386       while (cur->active_count) {
05387          if (5 <= time(NULL) - now) {
05388             ast_debug(1,
05389                "Unregister manager action %s timed out waiting for %u active instances to complete\n",
05390                action, cur->active_count);
05391             break;
05392          }
05393 
05394          sched_yield();
05395       }
05396 
05397       ao2_t_ref(cur, -1, "action object removed from list");
05398       ast_verb(2, "Manager unregistered action %s\n", action);
05399    }
05400 
05401    return 0;
05402 }

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

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

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

02069 {
02070    va_list ap;
02071    struct ast_str *buf;
02072 
02073    if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
02074       return;
02075    }
02076 
02077    va_start(ap, fmt);
02078    ast_str_set_va(&buf, 0, fmt, ap);
02079    va_end(ap);
02080 
02081    if (s->f != NULL || s->session->f != NULL) {
02082       send_string(s, ast_str_buffer(buf));
02083    } else {
02084       ast_verbose("fd == -1 in astman_append, should not happen\n");
02085    }
02086 }

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

Definition at line 2638 of file manager.c.

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

Referenced by action_getconfigjson().

02639 {
02640    char *buf;
02641 
02642    buf = ast_alloca(2 * strlen(str) + 1);
02643    json_escape(buf, str);
02644    astman_append(s, "%s", buf);
02645 }

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

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

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

Get a linked list of the Variable: headers.

Note:
Order of variables is reversed from the order they are specified in the manager message

Definition at line 1918 of file manager.c.

References astman_get_variables_order(), and ORDER_REVERSE.

Referenced by action_originate().

01919 {
01920    return astman_get_variables_order(m, ORDER_REVERSE);
01921 }

struct ast_variable* astman_get_variables_order ( const struct message m,
enum variable_orders  order 
) [read]

Get a linked list of the Variable: headers with order specified.

Definition at line 1923 of file manager.c.

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

Referenced by astman_get_variables(), and manager_sipnotify().

01925 {
01926    int varlen;
01927    int x;
01928    struct ast_variable *head = NULL;
01929 
01930    static const char var_hdr[] = "Variable:";
01931 
01932    /* Process all "Variable:" headers. */
01933    varlen = strlen(var_hdr);
01934    for (x = 0; x < m->hdrcount; x++) {
01935       if (strncasecmp(var_hdr, m->headers[x], varlen)) {
01936          continue;
01937       }
01938       head = man_do_variable_value(head, m->headers[x] + varlen);
01939    }
01940 
01941    if (order == ORDER_NATURAL) {
01942       head = ast_variables_reverse(head);
01943    }
01944 
01945    return head;
01946 }

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

02131 {
02132    astman_send_response_full(s, m, "Error", error, NULL);
02133 }

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

References astman_send_response_full().

Referenced by action_logoff(), and action_waitevent().

02126 {
02127    astman_send_response_full(s, m, resp, msg, NULL);
02128 }

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

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

02106 {
02107    const char *id = astman_get_header(m, "ActionID");
02108 
02109    astman_append(s, "Response: %s\r\n", resp);
02110    if (!ast_strlen_zero(id)) {
02111       astman_append(s, "ActionID: %s\r\n", id);
02112    }
02113    if (listflag) {
02114       astman_append(s, "EventList: %s\r\n", listflag);   /* Start, complete, cancelled */
02115    }
02116    if (msg == MSG_MOREDATA) {
02117       return;
02118    } else if (msg) {
02119       astman_append(s, "Message: %s\r\n\r\n", msg);
02120    } else {
02121       astman_append(s, "\r\n");
02122    }
02123 }

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

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

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

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

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

Definition at line 4379 of file manager.c.

References CMP_MATCH, and CMP_STOP.

Referenced by match_filter().

04380 {
04381    regex_t *regex_filter = obj;
04382    const char *eventdata = arg;
04383    int *result = data;
04384 
04385    if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
04386       *result = 0;
04387       return (CMP_MATCH | CMP_STOP);
04388    }
04389 
04390    *result = 1;
04391    return 0;
04392 }

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 1375 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(), 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().

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

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

Definition at line 3696 of file manager.c.

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

Referenced by action_command().

03697 {
03698    char *cmd_copy, *cur_cmd;
03699    char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, };
03700    int i;
03701 
03702    cmd_copy = ast_strdupa(cmd);
03703    for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) {
03704       cur_cmd = ast_strip(cur_cmd);
03705       if (ast_strlen_zero(cur_cmd)) {
03706          i--;
03707          continue;
03708       }
03709 
03710       cmd_words[i] = cur_cmd;
03711    }
03712 
03713    for (i = 0; i < ARRAY_LEN(command_blacklist); i++) {
03714       int j, match = 1;
03715 
03716       for (j = 0; command_blacklist[i].words[j]; j++) {
03717          if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) {
03718             match = 0;
03719             break;
03720          }
03721       }
03722 
03723       if (match) {
03724          return 1;
03725       }
03726    }
03727 
03728    return 0;
03729 }

int check_manager_enabled ( void   ) 

Check if AMI is enabled.

Definition at line 1107 of file manager.c.

Referenced by handle_show_settings().

01108 {
01109    return manager_enabled;
01110 }

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

Definition at line 1418 of file manager.c.

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

Referenced by process_message().

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

int check_webmanager_enabled ( void   ) 

Check if AMI/HTTP is enabled.

Definition at line 1112 of file manager.c.

Referenced by action_coresettings(), and handle_show_settings().

01113 {
01114    return (webmanager_enabled && manager_enabled);
01115 }

static void destroy_fast_originate_helper ( struct fast_originate_helper doomed  )  [static]

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

03834 {
03835    ast_variables_destroy(doomed->vars);
03836    ast_string_field_free_memory(doomed);
03837    ast_free(doomed);
03838 }

static int do_message ( struct mansession s  )  [static]

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

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

static void event_filter_destructor ( void *  obj  )  [static]

Definition at line 1339 of file manager.c.

Referenced by __init_manager().

01340 {
01341    regex_t *regex_filter = obj;
01342    regfree(regex_filter);
01343 }

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

Definition at line 3840 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, ast_channel::name, fast_originate_helper::priority, S_OR, fast_originate_helper::tech, fast_originate_helper::timeout, ast_channel::uniqueid, and fast_originate_helper::vars.

Referenced by action_originate().

03841 {
03842    struct fast_originate_helper *in = data;
03843    int res;
03844    int reason = 0;
03845    struct ast_channel *chan = NULL, *chans[1];
03846    char requested_channel[AST_CHANNEL_NAME];
03847 
03848    if (!ast_strlen_zero(in->app)) {
03849       res = ast_pbx_outgoing_app(in->tech, in->format, (char *) in->data,
03850          in->timeout, in->app, in->appdata, &reason, 1,
03851          S_OR(in->cid_num, NULL),
03852          S_OR(in->cid_name, NULL),
03853          in->vars, in->account, &chan);
03854    } else {
03855       res = ast_pbx_outgoing_exten(in->tech, in->format, (char *) in->data,
03856          in->timeout, in->context, in->exten, in->priority, &reason, 1,
03857          S_OR(in->cid_num, NULL),
03858          S_OR(in->cid_name, NULL),
03859          in->vars, in->account, &chan);
03860    }
03861    /* Any vars memory was passed to the ast_pbx_outgoing_xxx() calls. */
03862    in->vars = NULL;
03863 
03864    if (!chan) {
03865       snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);
03866    }
03867    /* Tell the manager what happened with the channel */
03868    chans[0] = chan;
03869    ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans,
03870       "%s"
03871       "Response: %s\r\n"
03872       "Channel: %s\r\n"
03873       "Context: %s\r\n"
03874       "Exten: %s\r\n"
03875       "Reason: %d\r\n"
03876       "Uniqueid: %s\r\n"
03877       "CallerIDNum: %s\r\n"
03878       "CallerIDName: %s\r\n",
03879       in->idtext, res ? "Failure" : "Success",
03880       chan ? chan->name : requested_channel, in->context, in->exten, reason,
03881       chan ? chan->uniqueid : "<null>",
03882       S_OR(in->cid_num, "<unknown>"),
03883       S_OR(in->cid_name, "<unknown>")
03884       );
03885 
03886    /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
03887    if (chan) {
03888       ast_channel_unlock(chan);
03889    }
03890    destroy_fast_originate_helper(in);
03891    return NULL;
03892 }

static void free_channelvars ( void   )  [static]

Definition at line 7253 of file manager.c.

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

Referenced by load_channelvars(), and manager_set_defaults().

07254 {
07255    struct manager_channel_variable *var;
07256    AST_RWLIST_WRLOCK(&channelvars);
07257    while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) {
07258       ast_free(var);
07259    }
07260    AST_RWLIST_UNLOCK(&channelvars);
07261 }

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

References EVENT_FLAG_SYSTEM.

Referenced by action_getvar(), and action_status().

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

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

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

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

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

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

Definition at line 1278 of file manager.c.

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

Referenced by __init_manager(), and strings_to_mask().

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

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

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

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

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

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

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

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

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

Definition at line 4968 of file manager.c.

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

Referenced by do_message().

04969 {
04970    mansession_lock(s);
04971    astman_send_error(s, m, error);
04972    s->parsing = MESSAGE_OKAY;
04973    mansession_unlock(s);
04974 }

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

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

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

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

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

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

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

Definition at line 1466 of file manager.c.

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

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

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

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

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 1709 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, mansession_session::sessionstart, mansession_session::sin, unref_mansession(), ast_cli_entry::usage, mansession_session::username, and mansession_session::writeperm.

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

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

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

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

Definition at line 2696 of file manager.c.

References ast_category_append(), ast_category_delete(), ast_category_destroy(), 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().

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

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

Referenced by astman_append_json().

02619 {
02620    for (; *in; in++) {
02621       if (*in == '\\' || *in == '\"') {
02622          *out++ = '\\';
02623       }
02624       *out++ = *in;
02625    }
02626    *out = '\0';
02627 }

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

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

Referenced by astman_get_variables_order().

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

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

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

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

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

04661 {
04662    int res;
04663    const char *module = astman_get_header(m, "Module");
04664    const char *id = astman_get_header(m, "ActionID");
04665    char idText[256];
04666 #if !defined(LOW_MEMORY)
04667    const char *version;
04668 #endif
04669    char filename[PATH_MAX];
04670    char *cut;
04671 
04672    ast_copy_string(filename, module, sizeof(filename));
04673    if ((cut = strchr(filename, '.'))) {
04674       *cut = '\0';
04675    } else {
04676       cut = filename + strlen(filename);
04677    }
04678    snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".so");
04679    ast_log(LOG_DEBUG, "**** ModuleCheck .so file %s\n", filename);
04680    res = ast_module_check(filename);
04681    if (!res) {
04682       astman_send_error(s, m, "Module not loaded");
04683       return 0;
04684    }
04685    snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".c");
04686    ast_log(LOG_DEBUG, "**** ModuleCheck .c file %s\n", filename);
04687 #if !defined(LOW_MEMORY)
04688    version = ast_file_version_find(filename);
04689 #endif
04690 
04691    if (!ast_strlen_zero(id)) {
04692       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
04693    } else {
04694       idText[0] = '\0';
04695    }
04696    astman_append(s, "Response: Success\r\n%s", idText);
04697 #if !defined(LOW_MEMORY)
04698    astman_append(s, "Version: %s\r\n\r\n", version ? version : "");
04699 #endif
04700    return 0;
04701 }

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

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

04704 {
04705    int res;
04706    const char *module = astman_get_header(m, "Module");
04707    const char *loadtype = astman_get_header(m, "LoadType");
04708 
04709    if (!loadtype || strlen(loadtype) == 0) {
04710       astman_send_error(s, m, "Incomplete ModuleLoad action.");
04711    }
04712    if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0) {
04713       astman_send_error(s, m, "Need module name");
04714    }
04715 
04716    if (!strcasecmp(loadtype, "load")) {
04717       res = ast_load_resource(module);
04718       if (res) {
04719          astman_send_error(s, m, "Could not load module.");
04720       } else {
04721          astman_send_ack(s, m, "Module loaded.");
04722       }
04723    } else if (!strcasecmp(loadtype, "unload")) {
04724       res = ast_unload_resource(module, AST_FORCE_SOFT);
04725       if (res) {
04726          astman_send_error(s, m, "Could not unload module.");
04727       } else {
04728          astman_send_ack(s, m, "Module unloaded.");
04729       }
04730    } else if (!strcasecmp(loadtype, "reload")) {
04731       if (!ast_strlen_zero(module)) {
04732          res = ast_module_reload(module);
04733          if (res == 0) {
04734             astman_send_error(s, m, "No such module.");
04735          } else if (res == 1) {
04736             astman_send_error(s, m, "Module does not support reload action.");
04737          } else {
04738             astman_send_ack(s, m, "Module reloaded.");
04739          }
04740       } else {
04741          ast_module_reload(NULL);   /* Reload all modules */
04742          astman_send_ack(s, m, "All modules reloaded");
04743       }
04744    } else
04745       astman_send_error(s, m, "Incomplete ModuleLoad action.");
04746    return 0;
04747 }

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

Definition at line 5404 of file manager.c.

References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.

Referenced by __init_manager().

05405 {
05406    /* Notify managers of change */
05407    char hint[512];
05408    ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten);
05409 
05410    manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state);
05411    return 0;
05412 }

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

Definition at line 1404 of file manager.c.

References CMP_MATCH, str, and mansession_session::username.

Referenced by __init_manager().

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

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

References ast_mutex_lock, and mansession::lock.

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

02152 {
02153    ast_mutex_lock(&s->lock);
02154 }

static void mansession_unlock ( struct mansession s  )  [static]

Unlock the 'mansession' structure.

Definition at line 2157 of file manager.c.

References ast_mutex_unlock, and mansession::lock.

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

02158 {
02159    ast_mutex_unlock(&s->lock);
02160 }

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

Definition at line 4394 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 action_waitevent(), and process_events().

04395 {
04396    int result = 0;
04397 
04398    ast_debug(3, "Examining event:\n%s\n", eventdata);
04399    if (!ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) {
04400       return 1; /* no filtering means match all */
04401    } else if (ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) {
04402       /* white filters only: implied black all filter processed first, then white filters */
04403       ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04404    } else if (!ao2_container_count(s->session->whitefilters) && ao2_container_count(s->session->blackfilters)) {
04405       /* black filters only: implied white all filter processed first, then black filters */
04406       ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04407    } else {
04408       /* white and black filters: implied black all filter processed first, then white filters, and lastly black filters */
04409       ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04410       if (result) {
04411          result = 0;
04412          ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
04413       }
04414    }
04415 
04416    return result;
04417 }

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

04425 {
04426    int ret = 0;
04427 
04428    ao2_lock(s->session);
04429    if (s->session->f != NULL) {
04430       struct eventqent *eqe = s->session->last_ev;
04431 
04432       while ((eqe = advance_event(eqe))) {
04433          if (!ret && s->session->authenticated &&
04434              (s->session->readperm & eqe->category) == eqe->category &&
04435              (s->session->send_events & eqe->category) == eqe->category) {
04436                if (match_filter(s, eqe->eventdata)) {
04437                   if (send_string(s, eqe->eventdata) < 0)
04438                      ret = -1;   /* don't send more */
04439                }
04440          }
04441          s->session->last_ev = eqe;
04442       }
04443    }
04444    ao2_unlock(s->session);
04445    return ret;
04446 }

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

Definition at line 4762 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(), generic_http_callback(), and http_post_callback().

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

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

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

static void purge_sessions ( int  n_max  )  [static]

remove at most n_max stale session from the list.

Definition at line 5181 of file manager.c.

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

Referenced by purge_old_stuff().

05182 {
05183    struct mansession_session *session;
05184    time_t now = time(NULL);
05185    struct ao2_iterator i;
05186 
05187    if (!sessions) {
05188       return;
05189    }
05190 
05191    i = ao2_iterator_init(sessions, 0);
05192    while ((session = ao2_iterator_next(&i)) && n_max > 0) {
05193       ao2_lock(session);
05194       if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) {
05195          if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) {
05196             ast_verb(2, "HTTP Manager '%s' timed out from %s\n",
05197                session->username, ast_inet_ntoa(session->sin.sin_addr));
05198          }
05199          ao2_unlock(session);
05200          session_destroy(session);
05201          n_max--;
05202       } else {
05203          ao2_unlock(session);
05204          unref_mansession(session);
05205       }
05206    }
05207    ao2_iterator_destroy(&i);
05208 }

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

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

02273 {
02274    struct sockaddr_in sin_local;
02275    char session_id[32];
02276    struct ast_security_event_successful_auth successful_auth = {
02277       .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH,
02278       .common.version    = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
02279       .common.service    = "AMI",
02280       .common.account_id = s->session->username,
02281       .common.session_tv = &s->session->sessionstart_tv,
02282       .common.local_addr = {
02283          .sin       = mansession_encode_sin_local(s, &sin_local),
02284          .transport = mansession_get_transport(s),
02285       },
02286       .common.remote_addr = {
02287          .sin       = &s->session->sin,
02288          .transport = mansession_get_transport(s),
02289       },
02290       .common.session_id = session_id,
02291    };
02292 
02293    snprintf(session_id, sizeof(session_id), "%p", s->session);
02294 
02295    ast_security_event_report(AST_SEC_EVT(&successful_auth));
02296 }

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

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

02221 {
02222    struct sockaddr_in sin_local;
02223    char session_id[32];
02224    struct ast_security_event_failed_acl failed_acl_event = {
02225       .common.event_type = AST_SECURITY_EVENT_FAILED_ACL,
02226       .common.version    = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
02227       .common.service    = "AMI",
02228       .common.account_id = username,
02229       .common.session_tv = &s->session->sessionstart_tv,
02230       .common.local_addr = {
02231          .sin       = mansession_encode_sin_local(s, &sin_local),
02232          .transport = mansession_get_transport(s),
02233       },
02234       .common.remote_addr = {
02235          .sin       = &s->session->sin,
02236          .transport = mansession_get_transport(s),
02237       },
02238       .common.session_id = session_id,
02239    };
02240 
02241    snprintf(session_id, sizeof(session_id), "%p", s->session);
02242 
02243    ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
02244 }

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

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

02360 {
02361    struct sockaddr_in sin_local;
02362    char session_id[32];
02363    struct ast_security_event_chal_resp_failed chal_resp_failed = {
02364       .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED,
02365       .common.version    = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
02366       .common.service    = "AMI",
02367       .common.account_id = s->session->username,
02368       .common.session_tv = &s->session->sessionstart_tv,
02369       .common.local_addr = {
02370          .sin       = mansession_encode_sin_local(s, &sin_local),
02371          .transport = mansession_get_transport(s),
02372       },
02373       .common.remote_addr = {
02374          .sin       = &s->session->sin,
02375          .transport = mansession_get_transport(s),
02376       },
02377       .common.session_id = session_id,
02378 
02379       .challenge         = s->session->challenge,
02380       .response          = response,
02381       .expected_response = expected_response,
02382    };
02383 
02384    snprintf(session_id, sizeof(session_id), "%p", s->session);
02385 
02386    ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
02387 }

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

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

02247 {
02248    struct sockaddr_in sin_local;
02249    char session_id[32];
02250    struct ast_security_event_inval_password inval_password = {
02251       .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD,
02252       .common.version    = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
02253       .common.service    = "AMI",
02254       .common.account_id = username,
02255       .common.session_tv = &s->session->sessionstart_tv,
02256       .common.local_addr = {
02257          .sin       = mansession_encode_sin_local(s, &sin_local),
02258          .transport = mansession_get_transport(s),
02259       },
02260       .common.remote_addr = {
02261          .sin       = &s->session->sin,
02262          .transport = mansession_get_transport(s),
02263       },
02264       .common.session_id = session_id,
02265    };
02266 
02267    snprintf(session_id, sizeof(session_id), "%p", s->session);
02268 
02269    ast_security_event_report(AST_SEC_EVT(&inval_password));
02270 }

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

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

02195 {
02196    struct sockaddr_in sin_local;
02197    char session_id[32];
02198    struct ast_security_event_inval_acct_id inval_acct_id = {
02199       .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID,
02200       .common.version    = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
02201       .common.service    = "AMI",
02202       .common.account_id = username,
02203       .common.session_tv = &s->session->sessionstart_tv,
02204       .common.local_addr = {
02205          .sin       = mansession_encode_sin_local(s, &sin_local),
02206          .transport = mansession_get_transport(s),
02207       },
02208       .common.remote_addr = {
02209          .sin       = &s->session->sin,
02210          .transport = mansession_get_transport(s),
02211       },
02212       .common.session_id = session_id,
02213    };
02214 
02215    snprintf(session_id, sizeof(session_id), "%p", s);
02216 
02217    ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
02218 }

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

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

02329 {
02330    struct sockaddr_in sin_local;
02331    char session_id[32];
02332    char request_type[64];
02333    struct ast_security_event_req_bad_format req_bad_format = {
02334       .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT,
02335       .common.version    = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
02336       .common.service    = "AMI",
02337       .common.account_id = s->session->username,
02338       .common.session_tv = &s->session->sessionstart_tv,
02339       .common.local_addr = {
02340          .sin       = mansession_encode_sin_local(s, &sin_local),
02341          .transport = mansession_get_transport(s),
02342       },
02343       .common.remote_addr = {
02344          .sin       = &s->session->sin,
02345          .transport = mansession_get_transport(s),
02346       },
02347       .common.session_id = session_id,
02348 
02349       .request_type      = request_type,
02350    };
02351 
02352    snprintf(session_id, sizeof(session_id), "%p", s->session);
02353    snprintf(request_type, sizeof(request_type), "Action: %s", action);
02354 
02355    ast_security_event_report(AST_SEC_EVT(&req_bad_format));
02356 }

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

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

02299 {
02300    struct sockaddr_in sin_local;
02301    char session_id[32];
02302    char request_type[64];
02303    struct ast_security_event_req_not_allowed req_not_allowed = {
02304       .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED,
02305       .common.version    = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
02306       .common.service    = "AMI",
02307       .common.account_id = s->session->username,
02308       .common.session_tv = &s->session->sessionstart_tv,
02309       .common.local_addr = {
02310          .sin       = mansession_encode_sin_local(s, &sin_local),
02311          .transport = mansession_get_transport(s),
02312       },
02313       .common.remote_addr = {
02314          .sin       = &s->session->sin,
02315          .transport = mansession_get_transport(s),
02316       },
02317       .common.session_id = session_id,
02318 
02319       .request_type      = request_type,
02320    };
02321 
02322    snprintf(session_id, sizeof(session_id), "%p", s->session);
02323    snprintf(request_type, sizeof(request_type), "Action: %s", action);
02324 
02325    ast_security_event_report(AST_SEC_EVT(&req_not_allowed));
02326 }

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

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

02390 {
02391    struct sockaddr_in sin_local;
02392    char session_id[32];
02393    struct ast_security_event_session_limit session_limit = {
02394       .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT,
02395       .common.version    = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
02396       .common.service    = "AMI",
02397       .common.account_id = s->session->username,
02398       .common.session_tv = &s->session->sessionstart_tv,
02399       .common.local_addr = {
02400          .sin       = mansession_encode_sin_local(s, &sin_local),
02401          .transport = mansession_get_transport(s),
02402       },
02403       .common.remote_addr = {
02404          .sin       = &s->session->sin,
02405          .transport = mansession_get_transport(s),
02406       },
02407       .common.session_id = session_id,
02408    };
02409 
02410    snprintf(session_id, sizeof(session_id), "%p", s->session);
02411 
02412    ast_security_event_report(AST_SEC_EVT(&session_limit));
02413 }

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

02030 {
02031    int res;
02032    FILE *f = s->f ? s->f : s->session->f;
02033    int fd = s->f ? s->fd : s->session->fd;
02034 
02035    /* It's a result from one of the hook's action invocation */
02036    if (s->hook) {
02037       /*
02038        * to send responses, we're using the same function
02039        * as for receiving events. We call the event "HookResponse"
02040        */
02041       s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string);
02042       return 0;
02043    }
02044        
02045    if ((res = ast_careful_fwrite(f, fd, string, strlen(string), s->session->writetimeout))) {
02046       s->write_error = 1;
02047    }
02048 
02049    return res;
02050 }

static void session_destroy ( struct mansession_session s  )  [static]

Definition at line 1411 of file manager.c.

References ao2_unlink, and unref_mansession().

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

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

static void session_destructor ( void *  obj  )  [static]

Definition at line 1345 of file manager.c.

References 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, eventqent::usecount, and mansession_session::whitefilters.

Referenced by build_mansession().

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

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 5073 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_tcptls_stream_set_exclusive_input(), ast_tcptls_stream_set_timeout_disable(), ast_tcptls_stream_set_timeout_sequence(), ast_tvnow(), ast_verb, astman_append(), mansession_session::authenticated, mansession_session::authstart, 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, ast_tcptls_session_instance::stream_cookie, unauth_sessions, mansession_session::username, and mansession::write_error.

05074 {
05075    struct ast_tcptls_session_instance *ser = data;
05076    struct mansession_session *session;
05077    struct mansession s = {
05078       .tcptls_session = data,
05079    };
05080    int flags;
05081    int res;
05082    struct sockaddr_in ser_remote_address_tmp;
05083    struct protoent *p;
05084 
05085    if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
05086       fclose(ser->f);
05087       ast_atomic_fetchadd_int(&unauth_sessions, -1);
05088       goto done;
05089    }
05090 
05091    ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
05092    session = build_mansession(ser_remote_address_tmp);
05093 
05094    if (session == NULL) {
05095       fclose(ser->f);
05096       ast_atomic_fetchadd_int(&unauth_sessions, -1);
05097       goto done;
05098    }
05099 
05100    /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
05101     * This is necessary to prevent delays (caused by buffering) as we
05102     * write to the socket in bits and pieces. */
05103    p = getprotobyname("tcp");
05104    if (p) {
05105       int arg = 1;
05106       if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
05107          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));
05108       }
05109    } else {
05110       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");
05111    }
05112 
05113    /* make sure socket is non-blocking */
05114    flags = fcntl(ser->fd, F_GETFL);
05115    flags |= O_NONBLOCK;
05116    fcntl(ser->fd, F_SETFL, flags);
05117 
05118    ao2_lock(session);
05119    /* Hook to the tail of the event queue */
05120    session->last_ev = grab_last();
05121 
05122    ast_mutex_init(&s.lock);
05123 
05124    /* these fields duplicate those in the 'ser' structure */
05125    session->fd = s.fd = ser->fd;
05126    session->f = s.f = ser->f;
05127    session->sin = ser_remote_address_tmp;
05128    s.session = session;
05129 
05130    AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
05131 
05132    if(time(&session->authstart) == -1) {
05133       ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
05134       ast_atomic_fetchadd_int(&unauth_sessions, -1);
05135       ao2_unlock(session);
05136       session_destroy(session);
05137       goto done;
05138    }
05139    ao2_unlock(session);
05140 
05141    /*
05142     * We cannot let the stream exclusively wait for data to arrive.
05143     * We have to wake up the task to send async events.
05144     */
05145    ast_tcptls_stream_set_exclusive_input(ser->stream_cookie, 0);
05146 
05147    ast_tcptls_stream_set_timeout_sequence(ser->stream_cookie,
05148       ast_tvnow(), authtimeout * 1000);
05149 
05150    astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION);   /* welcome prompt */
05151    for (;;) {
05152       if ((res = do_message(&s)) < 0 || s.write_error) {
05153          break;
05154       }
05155       if (session->authenticated) {
05156          ast_tcptls_stream_set_timeout_disable(ser->stream_cookie);
05157       }
05158    }
05159    /* session is over, explain why and terminate */
05160    if (session->authenticated) {
05161       if (manager_displayconnects(session)) {
05162          ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
05163       }
05164    } else {
05165       ast_atomic_fetchadd_int(&unauth_sessions, -1);
05166       if (displayconnects) {
05167          ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
05168       }
05169    }
05170 
05171    session_destroy(session);
05172 
05173    ast_mutex_destroy(&s.lock);
05174 done:
05175    ao2_ref(ser, -1);
05176    ser = NULL;
05177    return NULL;
05178 }

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

02167 {
02168    int maskint = strings_to_mask(eventmask);
02169 
02170    ao2_lock(s->session);
02171    if (maskint >= 0) {
02172       s->session->send_events = maskint;
02173    }
02174    ao2_unlock(s->session);
02175 
02176    return maskint;
02177 }

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

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

Referenced by set_eventmask().

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

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

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

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

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

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

Definition at line 4365 of file manager.c.

References CMP_MATCH, and CMP_STOP.

Referenced by match_filter().

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


Variable Documentation

int allowmultiplelogin = 1 [static]

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

Referenced by astman_append().

int authlimit [static]

Definition at line 908 of file manager.c.

int authtimeout [static]

Definition at line 907 of file manager.c.

int broken_events_action [static]

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

Referenced by reload_config().

const int DEFAULT_AUTHTIMEOUT = 30 [static]

Default setting for authtimeout

Definition at line 895 of file manager.c.

Referenced by reload_config().

const int DEFAULT_BROKENEVENTSACTION = 0 [static]

Default setting for brokeneventsaction

Definition at line 894 of file manager.c.

const int DEFAULT_DISPLAYCONNECTS = 1 [static]

Default setting for displaying manager connections

Definition at line 891 of file manager.c.

const int DEFAULT_ENABLED = 0 [static]

Default setting for manager to be enabled

Definition at line 889 of file manager.c.

const int DEFAULT_HTTPTIMEOUT = 60 [static]

Default manager http timeout

Definition at line 893 of file manager.c.

const int DEFAULT_MANAGERDEBUG = 0 [static]

Default setting for manager debug

Definition at line 897 of file manager.c.

const int DEFAULT_TIMESTAMPEVENTS = 0 [static]

Default setting for timestampevents

Definition at line 892 of file manager.c.

const int DEFAULT_WEBENABLED = 0 [static]

Default setting for the web interface to be enabled

Definition at line 890 of file manager.c.

int displayconnects [static]

Definition at line 899 of file manager.c.

char global_realm[MAXHOSTNAMELEN] [static]

Default realm

Definition at line 912 of file manager.c.

Referenced by __init_manager(), auth_http_callback(), and manager_set_defaults().

int httptimeout [static]

Definition at line 902 of file manager.c.

char* manager_channelvars [static]

Definition at line 909 of file manager.c.

int manager_debug = 0 [static]

enable some debugging code in the manager

Definition at line 906 of file manager.c.

int manager_enabled = 0 [static]

Definition at line 904 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 5265 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 5238 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]

Definition at line 1023 of file manager.c.

int timestampevents [static]

Definition at line 901 of file manager.c.

int unauth_sessions = 0 [static]

Definition at line 914 of file manager.c.

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

Definition at line 2060 of file manager.c.

Referenced by action_userevent().

int webmanager_enabled = 0 [static]

Definition at line 905 of file manager.c.

const char* words[AST_MAX_CMD_LEN] [inherited]

Definition at line 929 of file manager.c.


Generated on Thu Apr 16 06:48:11 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6