Sat Feb 11 06:37:01 2012

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
 In case you didn't read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data. More...
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)

Enumerations

enum  add_filter_result { FILTER_SUCCESS, FILTER_ALLOC_FAILED, FILTER_COMPILE_FAIL }
enum  error_type {
  UNKNOWN_ACTION = 1, UNKNOWN_CATEGORY, UNSPECIFIED_CATEGORY, UNSPECIFIED_ARGUMENT,
  FAILURE_ALLOCATION, FAILURE_NEWCAT, FAILURE_DELCAT, FAILURE_EMPTYCAT,
  FAILURE_UPDATE, FAILURE_DELETE, FAILURE_APPEND
}

Functions

int __ast_manager_event_multichan (int category, const char *event, int chancount, struct ast_channel **chans, const char *file, int line, const char *func, const char *fmt,...)
static const char * __astman_get_header (const struct message *m, char *var, int mode)
 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 int action_filter (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)
 events are appended to a queue from where they can be dispatched to clients.
int ast_hook_send_action (struct manager_custom_hook *hook, const char *msg)
 access for hooks to send action messages to ami
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)
 support functions to register/unregister AMI action handlers,
void ast_manager_unregister_hook (struct manager_custom_hook *hook)
 Delete a custom hook to be called when an event is fired.
void astman_append (struct mansession *s, const char *fmt,...)
static void astman_append_json (struct mansession *s, const char *str)
const char * astman_get_header (const struct message *m, char *var)
 Return the first matching variable from an array.
struct ast_variableastman_get_variables (const struct message *m)
 Get a linked list of the Variable: headers.
void astman_send_ack (struct mansession *s, const struct message *m, char *msg)
 Send ack in manager transaction.
void astman_send_error (struct mansession *s, const struct message *m, char *error)
 Send error in manager transaction.
void astman_send_listack (struct mansession *s, const struct message *m, char *msg, char *listflag)
 Send ack in manager list transaction.
void astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg)
 Send response in manager transaction.
static void astman_send_response_full (struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag)
 send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field.
static void astman_start_ack (struct mansession *s, const struct message *m)
static int authenticate (struct mansession *s, const struct message *m)
static const char * authority_to_str (int authority, struct ast_str **res)
 Convert authority code to a list of options.
static int blackfilter_cmp_fn (void *obj, void *arg, void *data, int flags)
static struct mansession_sessionbuild_mansession (struct sockaddr_in sin)
 Allocate manager session structure and add it to the list of sessions.
static int check_blacklist (const char *cmd)
int check_manager_enabled (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 get_input (struct mansession *s, char *output)
static struct ast_manager_userget_manager_by_name_locked (const char *name)
static int get_perm (const char *instr)
static struct eventqentgrab_last (void)
static char * handle_manager_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager reload.
static char * handle_mandebug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmanager (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmanagers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmancmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_showmancmds (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list commands.
static char * handle_showmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list connected.
static char * handle_showmaneventq (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list eventq.
static enum error_type handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn)
 helper function for action_updateconfig
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 enum add_filter_result manager_add_filter (const char *filter_pattern, struct ao2_container *whitefilters, struct ao2_container *blackfilters)
static int manager_displayconnects (struct mansession_session *session)
 Get displayconnects config option.
static int manager_modulecheck (struct mansession *s, const struct message *m)
 Manager function to check if module is loaded.
static int manager_moduleload (struct mansession *s, const struct message *m)
static int manager_state_cb (const char *context, const char *exten, enum ast_extension_states 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)
 Process an AMI message, performing desired action. Return 0 on success, -1 on error that require the session to be destroyed.
static void purge_events (void)
static void purge_sessions (int n_max)
 remove at most n_max stale session from the list.
static void report_auth_success (const struct mansession *s)
static void report_failed_acl (const struct mansession *s, const char *username)
static void report_failed_challenge_response (const struct mansession *s, const char *response, const char *expected_response)
static void report_inval_password (const struct mansession *s, const char *username)
static void report_invalid_user (const struct mansession *s, const char *username)
static void report_req_bad_format (const struct mansession *s, const char *action)
static void report_req_not_allowed (const struct mansession *s, const char *action)
static void report_session_limit (const struct mansession *s)
static int send_string (struct mansession *s, char *string)
static void session_destroy (struct mansession_session *s)
static void session_destructor (void *obj)
static void * session_do (void *data)
 The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ).
static int set_eventmask (struct mansession *s, const char *eventmask)
 Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm.
static int strings_to_mask (const char *string)
static struct mansession_sessionunref_mansession (struct mansession_session *s)
 Unreference manager session object. If no more references, then go ahead and delete it.
static int whitefilter_cmp_fn (void *obj, void *arg, void *data, int flags)

Variables

static int allowmultiplelogin = 1
static struct ast_threadstorage astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , }
static int authlimit
static int authtimeout
static int block_sockets
static int broken_events_action = 0
struct {
   const char *   words [AST_MAX_CMD_LEN]
command_blacklist []
static int displayconnects = 1
static char global_realm [MAXHOSTNAMELEN]
static int httptimeout = 60
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

callback to display list of locally configured nodes


Define Documentation

#define ASTMAN_APPEND_BUF_INITSIZE   256

initial allocated size for the astman_append_buf

Definition at line 2030 of file manager.c.

Referenced by astman_append().

#define DEFAULT_REALM   "asterisk"

Definition at line 942 of file manager.c.

Referenced by __init_manager(), and reload_config().

#define GET_HEADER_FIRST_MATCH   0

Definition at line 1791 of file manager.c.

Referenced by astman_get_header().

#define GET_HEADER_LAST_MATCH   1

Definition at line 1792 of file manager.c.

Referenced by __astman_get_header().

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 1793 of file manager.c.

Referenced by __astman_get_header(), and process_message().

#define MANAGER_EVENT_BUF_INITSIZE   256

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

Referenced by check_blacklist().

#define MSG_MOREDATA   ((char *)astman_send_response)

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.
Todo:
XXX MSG_MOREDATA should go to a header file.

Definition at line 2065 of file manager.c.

Referenced by astman_send_response_full(), and astman_start_ack().


Enumeration Type Documentation

Enumerator:
FILTER_SUCCESS 
FILTER_ALLOC_FAILED 
FILTER_COMPILE_FAIL 

Definition at line 894 of file manager.c.

00894                        {
00895    FILTER_SUCCESS,
00896    FILTER_ALLOC_FAILED,
00897    FILTER_COMPILE_FAIL,
00898 };

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


Function Documentation

int __ast_manager_event_multichan ( int  category,
const char *  event,
int  chancount,
struct ast_channel **  chans,
const char *  file,
int  line,
const char *  func,
const char *  contents,
  ... 
)

External routines may send asterisk manager events this way

Parameters:
category Event category, matches manager authorization
event Event name
chancount Number of channels in chans parameter
chans A pointer to an array of channels involved in the event
contents Format string describing event
Since:
1.8

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

05201 {
05202    struct mansession_session *session;
05203    struct manager_custom_hook *hook;
05204    struct ast_str *auth = ast_str_alloca(80);
05205    const char *cat_str;
05206    va_list ap;
05207    struct timeval now;
05208    struct ast_str *buf;
05209    int i;
05210 
05211    if (!(sessions && ao2_container_count(sessions)) && AST_RWLIST_EMPTY(&manager_hooks)) {
05212       return 0;
05213    }
05214    
05215    if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) {
05216       return -1;
05217    }
05218 
05219    cat_str = authority_to_str(category, &auth);
05220    ast_str_set(&buf, 0,
05221          "Event: %s\r\nPrivilege: %s\r\n",
05222           event, cat_str);
05223 
05224    if (timestampevents) {
05225       now = ast_tvnow();
05226       ast_str_append(&buf, 0,
05227             "Timestamp: %ld.%06lu\r\n",
05228              (long)now.tv_sec, (unsigned long) now.tv_usec);
05229    }
05230    if (manager_debug) {
05231       static int seq;
05232       ast_str_append(&buf, 0,
05233             "SequenceNumber: %d\r\n",
05234              ast_atomic_fetchadd_int(&seq, 1));
05235       ast_str_append(&buf, 0,
05236             "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func);
05237    }
05238 
05239    va_start(ap, fmt);
05240    ast_str_append_va(&buf, 0, fmt, ap);
05241    va_end(ap);
05242    for (i = 0; i < chancount; i++) {
05243       append_channel_vars(&buf, chans[i]);
05244    }
05245 
05246    ast_str_append(&buf, 0, "\r\n");
05247 
05248    append_event(ast_str_buffer(buf), category);
05249 
05250    /* Wake up any sleeping sessions */
05251    if (sessions) {
05252       struct ao2_iterator i;
05253       i = ao2_iterator_init(sessions, 0);
05254       while ((session = ao2_iterator_next(&i))) {
05255          ao2_lock(session);
05256          if (session->waiting_thread != AST_PTHREADT_NULL) {
05257             pthread_kill(session->waiting_thread, SIGURG);
05258          } else {
05259             /* We have an event to process, but the mansession is
05260              * not waiting for it. We still need to indicate that there
05261              * is an event waiting so that get_input processes the pending
05262              * event instead of polling.
05263              */
05264             session->pending_event = 1;
05265          }
05266          ao2_unlock(session);
05267          unref_mansession(session);
05268       }
05269       ao2_iterator_destroy(&i);
05270    }
05271 
05272    if (!AST_RWLIST_EMPTY(&manager_hooks)) {
05273       AST_RWLIST_RDLOCK(&manager_hooks);
05274       AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) {
05275          hook->helper(category, event, ast_str_buffer(buf));
05276       }
05277       AST_RWLIST_UNLOCK(&manager_hooks);
05278    }
05279 
05280    return 0;
05281 }

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

01809 {
01810    int x, l = strlen(var);
01811    const char *result = "";
01812 
01813    for (x = 0; x < m->hdrcount; x++) {
01814       const char *h = m->headers[x];
01815       if (!strncasecmp(var, h, l) && h[l] == ':') {
01816          const char *value = h + l + 1;
01817          value = ast_skip_blanks(value); /* ignore leading spaces in the value */
01818          /* found a potential candidate */
01819          if ((mode & GET_HEADER_SKIP_EMPTY) && ast_strlen_zero(value)) {
01820             continue;   /* not interesting */
01821          }
01822          if (mode & GET_HEADER_LAST_MATCH) {
01823             result = value;   /* record the last match so far */
01824          } else {
01825             return value;
01826          }
01827       }
01828    }
01829 
01830    return result;
01831 }

static void __fini_actions ( void   )  [static]

Definition at line 1083 of file manager.c.

01101 {

static void __fini_all_events ( void   )  [static]

Definition at line 928 of file manager.c.

00960 {

static void __fini_channelvars ( void   )  [static]

Definition at line 1056 of file manager.c.

01064 {

static void __fini_manager_hooks ( void   )  [static]

Definition at line 1086 of file manager.c.

01101 {

static void __fini_users ( void   )  [static]

Definition at line 1080 of file manager.c.

01101 {

static void __init_actions ( void   )  [static]

Definition at line 1083 of file manager.c.

01101 {

static void __init_all_events ( void   )  [static]

Definition at line 928 of file manager.c.

00960 {

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

02036 {

static void __init_channelvars ( void   )  [static]

Definition at line 1056 of file manager.c.

01064 {

static void __init_manager_event_buf ( void   )  [static]

Definition at line 5196 of file manager.c.

05201 {

static void __init_manager_event_funcbuf ( void   )  [static]

Definition at line 5169 of file manager.c.

05172 {

static void __init_manager_hooks ( void   )  [static]

Definition at line 1086 of file manager.c.

01101 {

static void __init_userevent_buf ( void   )  [static]

Definition at line 2027 of file manager.c.

02036 {

static void __init_users ( void   )  [static]

Definition at line 1080 of file manager.c.

01101 {

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

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

03801 {
03802    const char *channel = astman_get_header(m, "Channel");
03803    const char *pchannel = astman_get_header(m, "ChannelPrefix");
03804    const char *msgtype = astman_get_header(m, "MsgType");
03805    const char *chargetype = astman_get_header(m, "ChargeType");
03806    const char *currencyname = astman_get_header(m, "CurrencyName");
03807    const char *currencyamount = astman_get_header(m, "CurrencyAmount");
03808    const char *mult = astman_get_header(m, "CurrencyMultiplier");
03809    const char *totaltype = astman_get_header(m, "TotalType");
03810    const char *aocbillingid = astman_get_header(m, "AOCBillingId");
03811    const char *association_id= astman_get_header(m, "ChargingAssociationId");
03812    const char *association_num = astman_get_header(m, "ChargingAssociationNumber");
03813    const char *association_plan = astman_get_header(m, "ChargingAssociationPlan");
03814 
03815    enum ast_aoc_type _msgtype;
03816    enum ast_aoc_charge_type _chargetype;
03817    enum ast_aoc_currency_multiplier _mult = AST_AOC_MULT_ONE;
03818    enum ast_aoc_total_type _totaltype = AST_AOC_TOTAL;
03819    enum ast_aoc_billing_id _billingid = AST_AOC_BILLING_NA;
03820    unsigned int _currencyamount = 0;
03821    int _association_id = 0;
03822    unsigned int _association_plan = 0;
03823    struct ast_channel *chan = NULL;
03824 
03825    struct ast_aoc_decoded *decoded = NULL;
03826    struct ast_aoc_encoded *encoded = NULL;
03827    size_t encoded_size = 0;
03828 
03829    if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) {
03830       astman_send_error(s, m, "Channel and PartialChannel are not specified. Specify at least one of these.");
03831       goto aocmessage_cleanup;
03832    }
03833 
03834    if (!(chan = ast_channel_get_by_name(channel)) && !ast_strlen_zero(pchannel)) {
03835       chan = ast_channel_get_by_name_prefix(pchannel, strlen(pchannel));
03836    }
03837 
03838    if (!chan) {
03839       astman_send_error(s, m, "No such channel");
03840       goto aocmessage_cleanup;
03841    }
03842 
03843    if (ast_strlen_zero(msgtype) || (strcasecmp(msgtype, "d") && strcasecmp(msgtype, "e"))) {
03844       astman_send_error(s, m, "Invalid MsgType");
03845       goto aocmessage_cleanup;
03846    }
03847 
03848    if (ast_strlen_zero(chargetype)) {
03849       astman_send_error(s, m, "ChargeType not specified");
03850       goto aocmessage_cleanup;
03851    }
03852 
03853    _msgtype = strcasecmp(msgtype, "d") ? AST_AOC_E : AST_AOC_D;
03854 
03855    if (!strcasecmp(chargetype, "NA")) {
03856       _chargetype = AST_AOC_CHARGE_NA;
03857    } else if (!strcasecmp(chargetype, "Free")) {
03858       _chargetype = AST_AOC_CHARGE_FREE;
03859    } else if (!strcasecmp(chargetype, "Currency")) {
03860       _chargetype = AST_AOC_CHARGE_CURRENCY;
03861    } else if (!strcasecmp(chargetype, "Unit")) {
03862       _chargetype = AST_AOC_CHARGE_UNIT;
03863    } else {
03864       astman_send_error(s, m, "Invalid ChargeType");
03865       goto aocmessage_cleanup;
03866    }
03867 
03868    if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
03869 
03870       if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u", &_currencyamount) != 1)) {
03871          astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency");
03872          goto aocmessage_cleanup;
03873       }
03874 
03875       if (ast_strlen_zero(mult)) {
03876          astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency.");
03877          goto aocmessage_cleanup;
03878       } else if (!strcasecmp(mult, "onethousandth")) {
03879          _mult = AST_AOC_MULT_ONETHOUSANDTH;
03880       } else if (!strcasecmp(mult, "onehundredth")) {
03881          _mult = AST_AOC_MULT_ONEHUNDREDTH;
03882       } else if (!strcasecmp(mult, "onetenth")) {
03883          _mult = AST_AOC_MULT_ONETENTH;
03884       } else if (!strcasecmp(mult, "one")) {
03885          _mult = AST_AOC_MULT_ONE;
03886       } else if (!strcasecmp(mult, "ten")) {
03887          _mult = AST_AOC_MULT_TEN;
03888       } else if (!strcasecmp(mult, "hundred")) {
03889          _mult = AST_AOC_MULT_HUNDRED;
03890       } else if (!strcasecmp(mult, "thousand")) {
03891          _mult = AST_AOC_MULT_THOUSAND;
03892       } else {
03893          astman_send_error(s, m, "Invalid ChargeMultiplier");
03894          goto aocmessage_cleanup;
03895       }
03896    }
03897 
03898    /* create decoded object and start setting values */
03899    if (!(decoded = ast_aoc_create(_msgtype, _chargetype, 0))) {
03900          astman_send_error(s, m, "Message Creation Failed");
03901          goto aocmessage_cleanup;
03902    }
03903 
03904    if (_msgtype == AST_AOC_D) {
03905       if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype, "subtotal")) {
03906          _totaltype = AST_AOC_SUBTOTAL;
03907       }
03908 
03909       if (ast_strlen_zero(aocbillingid)) {
03910          /* ignore this is optional */
03911       } else if (!strcasecmp(aocbillingid, "Normal")) {
03912          _billingid = AST_AOC_BILLING_NORMAL;
03913       } else if (!strcasecmp(aocbillingid, "ReverseCharge")) {
03914          _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
03915       } else if (!strcasecmp(aocbillingid, "CreditCard")) {
03916          _billingid = AST_AOC_BILLING_CREDIT_CARD;
03917       } else {
03918          astman_send_error(s, m, "Invalid AOC-D AOCBillingId");
03919          goto aocmessage_cleanup;
03920       }
03921    } else {
03922       if (ast_strlen_zero(aocbillingid)) {
03923          /* ignore this is optional */
03924       } else if (!strcasecmp(aocbillingid, "Normal")) {
03925          _billingid = AST_AOC_BILLING_NORMAL;
03926       } else if (!strcasecmp(aocbillingid, "ReverseCharge")) {
03927          _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
03928       } else if (!strcasecmp(aocbillingid, "CreditCard")) {
03929          _billingid = AST_AOC_BILLING_CREDIT_CARD;
03930       } else if (!strcasecmp(aocbillingid, "CallFwdUnconditional")) {
03931          _billingid = AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL;
03932       } else if (!strcasecmp(aocbillingid, "CallFwdBusy")) {
03933          _billingid = AST_AOC_BILLING_CALL_FWD_BUSY;
03934       } else if (!strcasecmp(aocbillingid, "CallFwdNoReply")) {
03935          _billingid = AST_AOC_BILLING_CALL_FWD_NO_REPLY;
03936       } else if (!strcasecmp(aocbillingid, "CallDeflection")) {
03937          _billingid = AST_AOC_BILLING_CALL_DEFLECTION;
03938       } else if (!strcasecmp(aocbillingid, "CallTransfer")) {
03939          _billingid = AST_AOC_BILLING_CALL_TRANSFER;
03940       } else {
03941          astman_send_error(s, m, "Invalid AOC-E AOCBillingId");
03942          goto aocmessage_cleanup;
03943       }
03944 
03945       if (!ast_strlen_zero(association_id) && (sscanf(association_id, "%30d", &_association_id) != 1)) {
03946          astman_send_error(s, m, "Invalid ChargingAssociationId");
03947          goto aocmessage_cleanup;
03948       }
03949       if (!ast_strlen_zero(association_plan) && (sscanf(association_plan, "%30u", &_association_plan) != 1)) {
03950          astman_send_error(s, m, "Invalid ChargingAssociationPlan");
03951          goto aocmessage_cleanup;
03952       }
03953 
03954       if (_association_id) {
03955          ast_aoc_set_association_id(decoded, _association_id);
03956       } else if (!ast_strlen_zero(association_num)) {
03957          ast_aoc_set_association_number(decoded, association_num, _association_plan);
03958       }
03959    }
03960 
03961    if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
03962       ast_aoc_set_currency_info(decoded, _currencyamount, _mult, ast_strlen_zero(currencyname) ? NULL : currencyname);
03963    } else if (_chargetype == AST_AOC_CHARGE_UNIT) {
03964       struct ast_aoc_unit_entry entry;
03965       int i;
03966 
03967       /* multiple unit entries are possible, lets get them all */
03968       for (i = 0; i < 32; i++) {
03969          if (aocmessage_get_unit_entry(m, &entry, i)) {
03970             break; /* that's the end then */
03971          }
03972 
03973          ast_aoc_add_unit_entry(decoded, entry.valid_amount, entry.amount, entry.valid_type, entry.type);
03974       }
03975 
03976       /* at least one unit entry is required */
03977       if (!i) {
03978          astman_send_error(s, m, "Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit");
03979          goto aocmessage_cleanup;
03980       }
03981 
03982    }
03983 
03984    ast_aoc_set_billing_id(decoded, _billingid);
03985    ast_aoc_set_total_type(decoded, _totaltype);
03986 
03987 
03988    if ((encoded = ast_aoc_encode(decoded, &encoded_size, NULL)) && !ast_indicate_data(chan, AST_CONTROL_AOC, encoded, encoded_size)) {
03989       astman_send_ack(s, m, "AOC Message successfully queued on channel");
03990    } else {
03991       astman_send_error(s, m, "Error encoding AOC message, could not queue onto channel");
03992    }
03993 
03994 aocmessage_cleanup:
03995 
03996    ast_aoc_destroy_decoded(decoded);
03997    ast_aoc_destroy_encoded(encoded);
03998 
03999    if (chan) {
04000       chan = ast_channel_unref(chan);
04001    }
04002    return 0;
04003 }

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

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

03547 {
03548    const char *name = astman_get_header(m, "Channel");
03549    const char *exten = astman_get_header(m, "Exten");
03550    const char *context = astman_get_header(m, "Context");
03551    struct ast_channel *chan = NULL;
03552    struct ast_call_feature *atxfer_feature = NULL;
03553    char *feature_code = NULL;
03554 
03555    if (ast_strlen_zero(name)) {
03556       astman_send_error(s, m, "No channel specified");
03557       return 0;
03558    }
03559    if (ast_strlen_zero(exten)) {
03560       astman_send_error(s, m, "No extension specified");
03561       return 0;
03562    }
03563 
03564    if (!(atxfer_feature = ast_find_call_feature("atxfer"))) {
03565       astman_send_error(s, m, "No attended transfer feature found");
03566       return 0;
03567    }
03568 
03569    if (!(chan = ast_channel_get_by_name(name))) {
03570       astman_send_error(s, m, "Channel specified does not exist");
03571       return 0;
03572    }
03573 
03574    if (!ast_strlen_zero(context)) {
03575       pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context);
03576    }
03577 
03578    for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) {
03579       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code };
03580       ast_queue_frame(chan, &f);
03581    }
03582 
03583    for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) {
03584       struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code };
03585       ast_queue_frame(chan, &f);
03586    }
03587 
03588    chan = ast_channel_unref(chan);
03589 
03590    astman_send_ack(s, m, "Atxfer successfully queued");
03591 
03592    return 0;
03593 }

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

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

03113 {
03114    const char *authtype = astman_get_header(m, "AuthType");
03115 
03116    if (!strcasecmp(authtype, "MD5")) {
03117       if (ast_strlen_zero(s->session->challenge)) {
03118          snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
03119       }
03120       mansession_lock(s);
03121       astman_start_ack(s, m);
03122       astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
03123       mansession_unlock(s);
03124    } else {
03125       astman_send_error(s, m, "Must specify AuthType");
03126    }
03127    return 0;
03128 }

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

Manager command "command" - execute CLI command.

Definition at line 3631 of file manager.c.

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

Referenced by __init_manager().

03632 {
03633    const char *cmd = astman_get_header(m, "Command");
03634    const char *id = astman_get_header(m, "ActionID");
03635    char *buf, *final_buf;
03636    char template[] = "/tmp/ast-ami-XXXXXX";  /* template for temporary file */
03637    int fd;
03638    off_t l;
03639 
03640    if (ast_strlen_zero(cmd)) {
03641       astman_send_error(s, m, "No command provided");
03642       return 0;
03643    }
03644 
03645    if (check_blacklist(cmd)) {
03646       astman_send_error(s, m, "Command blacklisted");
03647       return 0;
03648    }
03649 
03650    fd = mkstemp(template);
03651 
03652    astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
03653    if (!ast_strlen_zero(id)) {
03654       astman_append(s, "ActionID: %s\r\n", id);
03655    }
03656    /* FIXME: Wedge a ActionID response in here, waiting for later changes */
03657    ast_cli_command(fd, cmd);  /* XXX need to change this to use a FILE * */
03658    l = lseek(fd, 0, SEEK_END);   /* how many chars available */
03659 
03660    /* This has a potential to overflow the stack.  Hence, use the heap. */
03661    buf = ast_calloc(1, l + 1);
03662    final_buf = ast_calloc(1, l + 1);
03663    if (buf) {
03664       lseek(fd, 0, SEEK_SET);
03665       if (read(fd, buf, l) < 0) {
03666          ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
03667       }
03668       buf[l] = '\0';
03669       if (final_buf) {
03670          term_strip(final_buf, buf, l);
03671          final_buf[l] = '\0';
03672       }
03673       astman_append(s, "%s", S_OR(final_buf, buf));
03674       ast_free(buf);
03675    }
03676    close(fd);
03677    unlink(template);
03678    astman_append(s, "--END COMMAND--\r\n\r\n");
03679    if (final_buf) {
03680       ast_free(final_buf);
03681    }
03682    return 0;
03683 }

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

Show PBX core settings information.

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

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

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

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

Referenced by __init_manager().

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

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

Show PBX core status information.

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

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

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

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

02889 {
02890    int fd;
02891    const char *fn = astman_get_header(m, "Filename");
02892    struct ast_str *filepath = ast_str_alloca(PATH_MAX);
02893    ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR);
02894    ast_str_append(&filepath, 0, "%s", fn);
02895 
02896    if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
02897       close(fd);
02898       astman_send_ack(s, m, "New configuration file created successfully");
02899    } else {
02900       astman_send_error(s, m, strerror(errno));
02901    }
02902 
02903    return 0;
02904 }

static void action_destroy ( void *  obj  )  [static]

Definition at line 5369 of file manager.c.

References ast_string_field_free_memory.

Referenced by ast_manager_register2().

05370 {
05371    struct manager_action *doomed = obj;
05372 
05373    if (doomed->synopsis) {
05374       /* The string fields were initialized. */
05375       ast_string_field_free_memory(doomed);
05376    }
05377 }

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

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

03032 {
03033    const char *mask = astman_get_header(m, "EventMask");
03034    int res, x;
03035    const char *id = astman_get_header(m, "ActionID");
03036    char id_text[256];
03037 
03038    if (!ast_strlen_zero(id)) {
03039       snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
03040    } else {
03041       id_text[0] = '\0';
03042    }
03043 
03044    res = set_eventmask(s, mask);
03045    if (broken_events_action) {
03046       /* if this option is set we should not return a response on
03047        * error, or when all events are set */
03048 
03049       if (res > 0) {
03050          for (x = 0; x < ARRAY_LEN(perms); x++) {
03051             if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) {
03052                return 0;
03053             }
03054          }
03055          astman_append(s, "Response: Success\r\n%s"
03056                 "Events: On\r\n\r\n", id_text);
03057       } else if (res == 0)
03058          astman_append(s, "Response: Success\r\n%s"
03059                 "Events: Off\r\n\r\n", id_text);
03060       return 0;
03061    }
03062 
03063    if (res > 0)
03064       astman_append(s, "Response: Success\r\n%s"
03065              "Events: On\r\n\r\n", id_text);
03066    else if (res == 0)
03067       astman_append(s, "Response: Success\r\n%s"
03068              "Events: Off\r\n\r\n", id_text);
03069    else
03070       astman_send_error(s, m, "Invalid event mask");
03071 
03072    return 0;
03073 }

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

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

04211 {
04212    const char *exten = astman_get_header(m, "Exten");
04213    const char *context = astman_get_header(m, "Context");
04214    char hint[256] = "";
04215    int status;
04216    if (ast_strlen_zero(exten)) {
04217       astman_send_error(s, m, "Extension not specified");
04218       return 0;
04219    }
04220    if (ast_strlen_zero(context)) {
04221       context = "default";
04222    }
04223    status = ast_extension_state(NULL, context, exten);
04224    ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
04225    astman_start_ack(s, m);
04226    astman_append(s,   "Message: Extension Status\r\n"
04227             "Exten: %s\r\n"
04228             "Context: %s\r\n"
04229             "Hint: %s\r\n"
04230             "Status: %d\r\n\r\n",
04231             exten, context, hint, status);
04232    return 0;
04233 }

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

Definition at line 4302 of file manager.c.

References astman_get_header(), astman_send_ack(), astman_send_error(), mansession_session::blackfilters, filter(), FILTER_ALLOC_FAILED, FILTER_COMPILE_FAIL, FILTER_SUCCESS, manager_add_filter(), mansession::session, and mansession_session::whitefilters.

Referenced by __init_manager().

04303 {
04304    const char *filter = astman_get_header(m, "Filter");
04305         const char *operation = astman_get_header(m, "Operation");
04306         int res;
04307 
04308         if (!strcasecmp(operation, "Add")) {
04309       res = manager_add_filter(filter, s->session->whitefilters, s->session->blackfilters);
04310 
04311            if (res != FILTER_SUCCESS) {
04312               if (res == FILTER_ALLOC_FAILED) {
04313             astman_send_error(s, m, "Internal Error. Failed to allocate regex for filter");
04314                       return 0;
04315               } else if (res == FILTER_COMPILE_FAIL) {
04316             astman_send_error(s, m, "Filter did not compile.  Check the syntax of the filter given.");
04317                       return 0;
04318               } else {
04319             astman_send_error(s, m, "Internal Error. Failed adding filter.");
04320                       return 0;
04321                    }
04322       }
04323 
04324       astman_send_ack(s, m, "Success");
04325                 return 0;
04326         }
04327 
04328    astman_send_error(s, m, "Unknown operation");
04329    return 0;
04330 }

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

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

01101 {
01102    struct manager_action *act;
01103 
01104    AST_RWLIST_RDLOCK(&actions);
01105    AST_RWLIST_TRAVERSE(&actions, act, list) {
01106       if (!strcasecmp(name, act->action)) {
01107          ao2_t_ref(act, +1, "found action object");
01108          break;
01109       }
01110    }
01111    AST_RWLIST_UNLOCK(&actions);
01112 
01113    return act;
01114 }

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

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

02507 {
02508    struct ast_config *cfg;
02509    const char *fn = astman_get_header(m, "Filename");
02510    const char *category = astman_get_header(m, "Category");
02511    int catcount = 0;
02512    int lineno = 0;
02513    char *cur_category = NULL;
02514    struct ast_variable *v;
02515    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02516 
02517    if (ast_strlen_zero(fn)) {
02518       astman_send_error(s, m, "Filename not specified");
02519       return 0;
02520    }
02521    cfg = ast_config_load2(fn, "manager", config_flags);
02522    if (cfg == CONFIG_STATUS_FILEMISSING) {
02523       astman_send_error(s, m, "Config file not found");
02524       return 0;
02525    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02526       astman_send_error(s, m, "Config file has invalid format");
02527       return 0;
02528    }
02529 
02530    astman_start_ack(s, m);
02531    while ((cur_category = ast_category_browse(cfg, cur_category))) {
02532       if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) {
02533          lineno = 0;
02534          astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category);
02535          for (v = ast_variable_browse(cfg, cur_category); v; v = v->next) {
02536             astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value);
02537          }
02538          catcount++;
02539       }
02540    }
02541    if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
02542       astman_append(s, "No categories found\r\n");
02543    }
02544    ast_config_destroy(cfg);
02545    astman_append(s, "\r\n");
02546 
02547    return 0;
02548 }

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

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

02617 {
02618    struct ast_config *cfg;
02619    const char *fn = astman_get_header(m, "Filename");
02620    char *category = NULL;
02621    struct ast_variable *v;
02622    int comma1 = 0;
02623    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02624 
02625    if (ast_strlen_zero(fn)) {
02626       astman_send_error(s, m, "Filename not specified");
02627       return 0;
02628    }
02629 
02630    if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
02631       astman_send_error(s, m, "Config file not found");
02632       return 0;
02633    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02634       astman_send_error(s, m, "Config file has invalid format");
02635       return 0;
02636    }
02637 
02638    astman_start_ack(s, m);
02639    astman_append(s, "JSON: {");
02640    while ((category = ast_category_browse(cfg, category))) {
02641       int comma2 = 0;
02642 
02643       astman_append(s, "%s\"", comma1 ? "," : "");
02644       astman_append_json(s, category);
02645       astman_append(s, "\":[");
02646       comma1 = 1;
02647       for (v = ast_variable_browse(cfg, category); v; v = v->next) {
02648          astman_append(s, "%s\"", comma2 ? "," : "");
02649          astman_append_json(s, v->name);
02650          astman_append(s, "\":\"");
02651          astman_append_json(s, v->value);
02652          astman_append(s, "\"");
02653          comma2 = 1;
02654       }
02655       astman_append(s, "]");
02656    }
02657    astman_append(s, "}\r\n\r\n");
02658 
02659    ast_config_destroy(cfg);
02660 
02661    return 0;
02662 }

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

Definition at line 3206 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(), LOG_ERROR, pbx_retrieve_variable(), and S_OR.

Referenced by __init_manager().

03207 {
03208    struct ast_channel *c = NULL;
03209    const char *name = astman_get_header(m, "Channel");
03210    const char *varname = astman_get_header(m, "Variable");
03211    char *varval;
03212    char workspace[1024];
03213 
03214    if (ast_strlen_zero(varname)) {
03215       astman_send_error(s, m, "No variable specified");
03216       return 0;
03217    }
03218 
03219    if (!ast_strlen_zero(name)) {
03220       if (!(c = ast_channel_get_by_name(name))) {
03221          astman_send_error(s, m, "No such channel");
03222          return 0;
03223       }
03224    }
03225 
03226    workspace[0] = '\0';
03227    if (varname[strlen(varname) - 1] == ')') {
03228       if (!c) {
03229          c = ast_dummy_channel_alloc();
03230          if (c) {
03231             ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
03232          } else
03233             ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03234       } else {
03235          ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
03236       }
03237       varval = workspace;
03238    } else {
03239       pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
03240    }
03241 
03242    if (c) {
03243       c = ast_channel_unref(c);
03244    }
03245 
03246    astman_start_ack(s, m);
03247    astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, S_OR(varval, ""));
03248 
03249    return 0;
03250 }

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

Definition at line 3130 of file manager.c.

References ast_channel_get_by_name(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_debug, ast_log(), AST_SOFTHANGUP_EXPLICIT, ast_softhangup_nolock(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), cause, ast_channel::hangupcause, and LOG_NOTICE.

Referenced by __init_manager().

03131 {
03132    struct ast_channel *c = NULL;
03133    int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */
03134    const char *name = astman_get_header(m, "Channel");
03135    const char *cause = astman_get_header(m, "Cause");
03136 
03137    if (ast_strlen_zero(name)) {
03138       astman_send_error(s, m, "No channel specified");
03139       return 0;
03140    }
03141 
03142    if (!ast_strlen_zero(cause)) {
03143       char *endptr;
03144       causecode = strtol(cause, &endptr, 10);
03145       if (causecode < 0 || causecode > 127 || *endptr != '\0') {
03146          ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause);
03147          /* keep going, better to hangup without cause than to not hang up at all */
03148          causecode = 0; /* do not set channel's hangupcause */
03149       }
03150    }
03151 
03152    if (!(c = ast_channel_get_by_name(name))) {
03153       astman_send_error(s, m, "No such channel");
03154       return 0;
03155    }
03156 
03157    ast_channel_lock(c);
03158    if (causecode > 0) {
03159       ast_debug(1, "Setting hangupcause of channel %s to %d (is %d now)\n",
03160             ast_channel_name(c), causecode, c->hangupcause);
03161       c->hangupcause = causecode;
03162    }
03163    ast_softhangup_nolock(c, AST_SOFTHANGUP_EXPLICIT);
03164    ast_channel_unlock(c);
03165 
03166    c = ast_channel_unref(c);
03167 
03168    astman_send_ack(s, m, "Channel Hungup");
03169 
03170    return 0;
03171 }

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

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

02551 {
02552    struct ast_config *cfg;
02553    const char *fn = astman_get_header(m, "Filename");
02554    char *category = NULL;
02555    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
02556    int catcount = 0;
02557 
02558    if (ast_strlen_zero(fn)) {
02559       astman_send_error(s, m, "Filename not specified");
02560       return 0;
02561    }
02562    if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
02563       astman_send_error(s, m, "Config file not found");
02564       return 0;
02565    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02566       astman_send_error(s, m, "Config file has invalid format");
02567       return 0;
02568    }
02569    astman_start_ack(s, m);
02570    while ((category = ast_category_browse(cfg, category))) {
02571       astman_append(s, "Category-%06d: %s\r\n", catcount, category);
02572       catcount++;
02573    }
02574    if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
02575       astman_append(s, "Error: no categories found\r\n");
02576    }
02577    ast_config_destroy(cfg);
02578    astman_append(s, "\r\n");
02579 
02580    return 0;
02581 }

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

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

03013 {
03014    struct manager_action *cur;
03015    struct ast_str *temp = ast_str_alloca(256);
03016 
03017    astman_start_ack(s, m);
03018    AST_RWLIST_RDLOCK(&actions);
03019    AST_RWLIST_TRAVERSE(&actions, cur, list) {
03020       if ((s->session->writeperm & cur->authority) || cur->authority == 0) {
03021          astman_append(s, "%s: %s (Priv: %s)\r\n",
03022             cur->action, cur->synopsis, authority_to_str(cur->authority, &temp));
03023       }
03024    }
03025    AST_RWLIST_UNLOCK(&actions);
03026    astman_append(s, "\r\n");
03027 
03028    return 0;
03029 }

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

Definition at line 3081 of file manager.c.

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

Referenced by __init_manager().

03082 {
03083 
03084    /* still authenticated - don't process again */
03085    if (s->session->authenticated) {
03086       astman_send_ack(s, m, "Already authenticated");
03087       return 0;
03088    }
03089 
03090    if (authenticate(s, m)) {
03091       sleep(1);
03092       astman_send_error(s, m, "Authentication failed");
03093       return -1;
03094    }
03095    s->session->authenticated = 1;
03096    ast_atomic_fetchadd_int(&unauth_sessions, -1);
03097    if (manager_displayconnects(s->session)) {
03098       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));
03099    }
03100    astman_send_ack(s, m, "Authentication accepted");
03101    if ((s->session->send_events & EVENT_FLAG_SYSTEM)
03102       && ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
03103       struct ast_str *auth = ast_str_alloca(80);
03104       const char *cat_str = authority_to_str(EVENT_FLAG_SYSTEM, &auth);
03105       astman_append(s, "Event: FullyBooted\r\n"
03106          "Privilege: %s\r\n"
03107          "Status: Fully Booted\r\n\r\n", cat_str);
03108    }
03109    return 0;
03110 }

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

Definition at line 3075 of file manager.c.

References astman_send_response().

Referenced by __init_manager().

03076 {
03077    astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
03078    return -1;
03079 }

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

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

04190 {
04191    const char *mailbox = astman_get_header(m, "Mailbox");
04192    int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;;
04193 
04194    if (ast_strlen_zero(mailbox)) {
04195       astman_send_error(s, m, "Mailbox not specified");
04196       return 0;
04197    }
04198    ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs);
04199    astman_start_ack(s, m);
04200    astman_append(s,   "Message: Mailbox Message Count\r\n"
04201             "Mailbox: %s\r\n"
04202             "UrgMessages: %d\r\n"
04203             "NewMessages: %d\r\n"
04204             "OldMessages: %d\r\n"
04205             "\r\n",
04206             mailbox, urgentmsgs, newmsgs, oldmsgs);
04207    return 0;
04208 }

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

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

04173 {
04174    const char *mailbox = astman_get_header(m, "Mailbox");
04175    int ret;
04176 
04177    if (ast_strlen_zero(mailbox)) {
04178       astman_send_error(s, m, "Mailbox not specified");
04179       return 0;
04180    }
04181    ret = ast_app_has_voicemail(mailbox, NULL);
04182    astman_start_ack(s, m);
04183    astman_append(s, "Message: Mailbox Status\r\n"
04184           "Mailbox: %s\r\n"
04185           "Waiting: %d\r\n\r\n", mailbox, ret);
04186    return 0;
04187 }

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

Definition at line 4005 of file manager.c.

References app, ast_callerid_parse(), ast_calloc, ast_copy_string(), ast_exists_extension(), ast_findlabel_extension(), ast_format_cap_add(), ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_format_cap_remove_all(), ast_format_set(), 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(), fast_originate_helper::cap, cid_name, cid_num, context, ast_frame::data, destroy_fast_originate_helper(), EVENT_FLAG_SYSTEM, exten, fast_originate(), fast_originate_helper::priority, mansession::session, strcasestr(), fast_originate_helper::timeout, fast_originate_helper::vars, and mansession_session::writeperm.

Referenced by __init_manager().

04006 {
04007    const char *name = astman_get_header(m, "Channel");
04008    const char *exten = astman_get_header(m, "Exten");
04009    const char *context = astman_get_header(m, "Context");
04010    const char *priority = astman_get_header(m, "Priority");
04011    const char *timeout = astman_get_header(m, "Timeout");
04012    const char *callerid = astman_get_header(m, "CallerID");
04013    const char *account = astman_get_header(m, "Account");
04014    const char *app = astman_get_header(m, "Application");
04015    const char *appdata = astman_get_header(m, "Data");
04016    const char *async = astman_get_header(m, "Async");
04017    const char *id = astman_get_header(m, "ActionID");
04018    const char *codecs = astman_get_header(m, "Codecs");
04019    struct ast_variable *vars;
04020    char *tech, *data;
04021    char *l = NULL, *n = NULL;
04022    int pi = 0;
04023    int res;
04024    int to = 30000;
04025    int reason = 0;
04026    char tmp[256];
04027    char tmp2[256];
04028    struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
04029    struct ast_format tmp_fmt;
04030    pthread_t th;
04031 
04032    if (!cap) {
04033       astman_send_error(s, m, "Internal Error. Memory allocation failure.");
04034    }
04035    ast_format_cap_add(cap, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0));
04036 
04037    if (ast_strlen_zero(name)) {
04038       astman_send_error(s, m, "Channel not specified");
04039       res = 0;
04040       goto fast_orig_cleanup;
04041    }
04042    if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) {
04043       if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
04044          astman_send_error(s, m, "Invalid priority");
04045          res = 0;
04046          goto fast_orig_cleanup;
04047       }
04048    }
04049    if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) {
04050       astman_send_error(s, m, "Invalid timeout");
04051       res = 0;
04052       goto fast_orig_cleanup;
04053    }
04054    ast_copy_string(tmp, name, sizeof(tmp));
04055    tech = tmp;
04056    data = strchr(tmp, '/');
04057    if (!data) {
04058       astman_send_error(s, m, "Invalid channel");
04059       res = 0;
04060       goto fast_orig_cleanup;
04061    }
04062    *data++ = '\0';
04063    ast_copy_string(tmp2, callerid, sizeof(tmp2));
04064    ast_callerid_parse(tmp2, &n, &l);
04065    if (n) {
04066       if (ast_strlen_zero(n)) {
04067          n = NULL;
04068       }
04069    }
04070    if (l) {
04071       ast_shrink_phone_number(l);
04072       if (ast_strlen_zero(l)) {
04073          l = NULL;
04074       }
04075    }
04076    if (!ast_strlen_zero(codecs)) {
04077       ast_format_cap_remove_all(cap);
04078       ast_parse_allow_disallow(NULL, cap, codecs, 1);
04079    }
04080 
04081    if (!ast_strlen_zero(app)) {
04082       /* To run the System application (or anything else that goes to
04083        * shell), you must have the additional System privilege */
04084       if (!(s->session->writeperm & EVENT_FLAG_SYSTEM)
04085          && (
04086             strcasestr(app, "system") ||      /* System(rm -rf /)
04087                                                  TrySystem(rm -rf /)       */
04088             strcasestr(app, "exec") ||        /* Exec(System(rm -rf /))
04089                                                  TryExec(System(rm -rf /)) */
04090             strcasestr(app, "agi") ||         /* AGI(/bin/rm,-rf /)
04091                                                  EAGI(/bin/rm,-rf /)       */
04092             strstr(appdata, "SHELL") ||       /* NoOp(${SHELL(rm -rf /)})  */
04093             strstr(appdata, "EVAL")           /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
04094             )) {
04095          astman_send_error(s, m, "Originate with certain 'Application' arguments requires the additional System privilege, which you do not have.");
04096          res = 0;
04097          goto fast_orig_cleanup;
04098       }
04099    }
04100 
04101    /* Check early if the extension exists. If not, we need to bail out here. */
04102    if (exten && context && pi) {
04103       if (! ast_exists_extension(NULL, context, exten, pi, l)) {
04104          /* The extension does not exist. */
04105          astman_send_error(s, m, "Extension does not exist.");
04106          res = 0;
04107          goto fast_orig_cleanup;
04108       }
04109    }
04110 
04111    /* Allocate requested channel variables */
04112    vars = astman_get_variables(m);
04113 
04114    if (ast_true(async)) {
04115       struct fast_originate_helper *fast;
04116 
04117       fast = ast_calloc(1, sizeof(*fast));
04118       if (!fast || ast_string_field_init(fast, 252)) {
04119          ast_free(fast);
04120          ast_variables_destroy(vars);
04121          res = -1;
04122       } else {
04123          if (!ast_strlen_zero(id)) {
04124             ast_string_field_build(fast, idtext, "ActionID: %s\r\n", id);
04125          }
04126          ast_string_field_set(fast, tech, tech);
04127          ast_string_field_set(fast, data, data);
04128          ast_string_field_set(fast, app, app);
04129          ast_string_field_set(fast, appdata, appdata);
04130          ast_string_field_set(fast, cid_num, l);
04131          ast_string_field_set(fast, cid_name, n);
04132          ast_string_field_set(fast, context, context);
04133          ast_string_field_set(fast, exten, exten);
04134          ast_string_field_set(fast, account, account);
04135          fast->vars = vars;
04136          fast->cap = cap;
04137          cap = NULL; /* transfered originate helper the capabilities structure.  It is now responsible for freeing it. */
04138          fast->timeout = to;
04139          fast->priority = pi;
04140          if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) {
04141             destroy_fast_originate_helper(fast);
04142             res = -1;
04143          } else {
04144             res = 0;
04145          }
04146       }
04147    } else if (!ast_strlen_zero(app)) {
04148       res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
04149       /* Any vars memory was passed to ast_pbx_outgoing_app(). */
04150    } else {
04151       if (exten && context && pi) {
04152          res = ast_pbx_outgoing_exten(tech, cap, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
04153          /* Any vars memory was passed to ast_pbx_outgoing_exten(). */
04154       } else {
04155          astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
04156          ast_variables_destroy(vars);
04157          res = 0;
04158          goto fast_orig_cleanup;
04159       }
04160    }
04161    if (!res) {
04162       astman_send_ack(s, m, "Originate successfully queued");
04163    } else {
04164       astman_send_error(s, m, "Originate failed");
04165    }
04166 
04167 fast_orig_cleanup:
04168    ast_format_cap_destroy(cap);
04169    return 0;
04170 }

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

Definition at line 2488 of file manager.c.

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

Referenced by __init_manager().

02489 {
02490    const char *actionid = astman_get_header(m, "ActionID");
02491    struct timeval now = ast_tvnow();
02492 
02493    astman_append(s, "Response: Success\r\n");
02494    if (!ast_strlen_zero(actionid)){
02495       astman_append(s, "ActionID: %s\r\n", actionid);
02496    }
02497    astman_append(
02498       s,
02499       "Ping: Pong\r\n"
02500       "Timestamp: %ld.%06lu\r\n"
02501       "\r\n",
02502       (long) now.tv_sec, (unsigned long) now.tv_usec);
02503    return 0;
02504 }

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

action_redirect: The redirect manager command

Definition at line 3446 of file manager.c.

References ast_async_goto(), ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_check_hangup_locked(), ast_findlabel_extension(), AST_FLAG_BRIDGE_HANGUP_DONT, ast_set_flag, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), context, exten, ast_channel::pbx, and ast_channel::priority.

Referenced by __init_manager().

03447 {
03448    const char *name = astman_get_header(m, "Channel");
03449    const char *name2 = astman_get_header(m, "ExtraChannel");
03450    const char *exten = astman_get_header(m, "Exten");
03451    const char *exten2 = astman_get_header(m, "ExtraExten");
03452    const char *context = astman_get_header(m, "Context");
03453    const char *context2 = astman_get_header(m, "ExtraContext");
03454    const char *priority = astman_get_header(m, "Priority");
03455    const char *priority2 = astman_get_header(m, "ExtraPriority");
03456    struct ast_channel *chan, *chan2 = NULL;
03457    int pi, pi2 = 0;
03458    int res;
03459 
03460    if (ast_strlen_zero(name)) {
03461       astman_send_error(s, m, "Channel not specified");
03462       return 0;
03463    }
03464 
03465    if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) {
03466       if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
03467          astman_send_error(s, m, "Invalid priority");
03468          return 0;
03469       }
03470    }
03471 
03472    if (!ast_strlen_zero(priority2) && (sscanf(priority2, "%30d", &pi2) != 1)) {
03473       if ((pi2 = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL)) < 1) {
03474          astman_send_error(s, m, "Invalid ExtraPriority");
03475          return 0;
03476       }
03477    }
03478 
03479    if (!(chan = ast_channel_get_by_name(name))) {
03480       char buf[256];
03481       snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
03482       astman_send_error(s, m, buf);
03483       return 0;
03484    }
03485 
03486    if (ast_check_hangup_locked(chan)) {
03487       astman_send_error(s, m, "Redirect failed, channel not up.");
03488       chan = ast_channel_unref(chan);
03489       return 0;
03490    }
03491 
03492    if (!ast_strlen_zero(name2)) {
03493       chan2 = ast_channel_get_by_name(name2);
03494    }
03495 
03496    if (chan2 && ast_check_hangup_locked(chan2)) {
03497       astman_send_error(s, m, "Redirect failed, extra channel not up.");
03498       chan = ast_channel_unref(chan);
03499       chan2 = ast_channel_unref(chan2);
03500       return 0;
03501    }
03502 
03503    if (chan->pbx) {
03504       ast_channel_lock(chan);
03505       ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
03506       ast_channel_unlock(chan);
03507    }
03508 
03509    res = ast_async_goto(chan, context, exten, pi);
03510    if (!res) {
03511       if (!ast_strlen_zero(name2)) {
03512          if (chan2) {
03513             if (chan2->pbx) {
03514                ast_channel_lock(chan2);
03515                ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
03516                ast_channel_unlock(chan2);
03517             }
03518             if (!ast_strlen_zero(context2)) {
03519                res = ast_async_goto(chan2, context2, exten2, pi2);
03520             } else {
03521                res = ast_async_goto(chan2, context, exten, pi);
03522             }
03523          } else {
03524             res = -1;
03525          }
03526          if (!res) {
03527             astman_send_ack(s, m, "Dual Redirect successful");
03528          } else {
03529             astman_send_error(s, m, "Secondary redirect failed");
03530          }
03531       } else {
03532          astman_send_ack(s, m, "Redirect successful");
03533       }
03534    } else {
03535       astman_send_error(s, m, "Redirect failed");
03536    }
03537 
03538    chan = ast_channel_unref(chan);
03539    if (chan2) {
03540       chan2 = ast_channel_unref(chan2);
03541    }
03542 
03543    return 0;
03544 }

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

Send a reload event.

Definition at line 4536 of file manager.c.

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

Referenced by __init_manager().

04537 {
04538    const char *module = astman_get_header(m, "Module");
04539    int res = ast_module_reload(S_OR(module, NULL));
04540 
04541    if (res == 2) {
04542       astman_send_ack(s, m, "Module Reloaded");
04543    } else {
04544       astman_send_error(s, m, s == 0 ? "No such module" : "Module does not support reload");
04545    }
04546    return 0;
04547 }

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

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

03412 {
03413    struct ast_channel *c = NULL;
03414    const char *name = astman_get_header(m, "Channel");
03415    const char *textmsg = astman_get_header(m, "Message");
03416    int res = 0;
03417 
03418    if (ast_strlen_zero(name)) {
03419       astman_send_error(s, m, "No channel specified");
03420       return 0;
03421    }
03422 
03423    if (ast_strlen_zero(textmsg)) {
03424       astman_send_error(s, m, "No Message specified");
03425       return 0;
03426    }
03427 
03428    if (!(c = ast_channel_get_by_name(name))) {
03429       astman_send_error(s, m, "No such channel");
03430       return 0;
03431    }
03432 
03433    res = ast_sendtext(c, textmsg);
03434    c = ast_channel_unref(c);
03435 
03436    if (res >= 0) {
03437       astman_send_ack(s, m, "Success");
03438    } else {
03439       astman_send_error(s, m, "Failure");
03440    }
03441 
03442    return res;
03443 }

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

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

03174 {
03175    struct ast_channel *c = NULL;
03176    const char *name = astman_get_header(m, "Channel");
03177    const char *varname = astman_get_header(m, "Variable");
03178    const char *varval = astman_get_header(m, "Value");
03179    int res = 0;
03180    
03181    if (ast_strlen_zero(varname)) {
03182       astman_send_error(s, m, "No variable specified");
03183       return 0;
03184    }
03185 
03186    if (!ast_strlen_zero(name)) {
03187       if (!(c = ast_channel_get_by_name(name))) {
03188          astman_send_error(s, m, "No such channel");
03189          return 0;
03190       }
03191    }
03192 
03193    res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
03194 
03195    if (c) {
03196       c = ast_channel_unref(c);
03197    }
03198    if (res == 0) {
03199       astman_send_ack(s, m, "Variable Set"); 
03200    } else {
03201       astman_send_error(s, m, "Variable not set");
03202    }
03203    return 0;
03204 }

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

Manager "status" command to show channels.

Definition at line 3254 of file manager.c.

References ast_channel::_bridge, ast_channel::_state, AST_APP_ARG, ast_channel_accountcode(), ast_channel_get_by_name(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_name(), ast_channel_uniqueid(), 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, ast_party_connected_line::id, ast_party_caller::id, ast_party_id::name, ast_party_id::number, ast_channel::pbx, pbx_retrieve_variable(), ast_channel::priority, S_COR, S_OR, ast_cdr::start, ast_party_name::str, ast_party_number::str, str, ast_party_name::valid, and ast_party_number::valid.

Referenced by __init_manager().

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

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

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

04236 {
04237    struct ast_channel *c;
04238    const char *name = astman_get_header(m, "Channel");
04239    double timeout = atof(astman_get_header(m, "Timeout"));
04240    struct timeval when = { timeout, 0 };
04241 
04242    if (ast_strlen_zero(name)) {
04243       astman_send_error(s, m, "No channel specified");
04244       return 0;
04245    }
04246 
04247    if (!timeout || timeout < 0) {
04248       astman_send_error(s, m, "No timeout specified");
04249       return 0;
04250    }
04251 
04252    if (!(c = ast_channel_get_by_name(name))) {
04253       astman_send_error(s, m, "No such channel");
04254       return 0;
04255    }
04256 
04257    when.tv_usec = (timeout - when.tv_sec) * 1000000.0;
04258 
04259    ast_channel_lock(c);
04260    ast_channel_setwhentohangup_tv(c, when);
04261    ast_channel_unlock(c);
04262    c = ast_channel_unref(c);
04263 
04264    astman_send_ack(s, m, "Timeout Set");
04265 
04266    return 0;
04267 }

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

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

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

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

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

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

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

Definition at line 2906 of file manager.c.

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

Referenced by __init_manager().

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

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

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

01779 {
01780    struct eventqent *next;
01781 
01782    AST_RWLIST_RDLOCK(&all_events);
01783    if ((next = AST_RWLIST_NEXT(e, eq_next))) {
01784       ast_atomic_fetchadd_int(&next->usecount, 1);
01785       ast_atomic_fetchadd_int(&e->usecount, -1);
01786    }
01787    AST_RWLIST_UNLOCK(&all_events);
01788    return next;
01789 }

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

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

03776 {
03777    const char *unitamount;
03778    const char *unittype;
03779    struct ast_str *str = ast_str_alloca(32);
03780 
03781    memset(entry, 0, sizeof(*entry));
03782 
03783    ast_str_set(&str, 0, "UnitAmount(%u)", entry_num);
03784    unitamount = astman_get_header(m, ast_str_buffer(str));
03785 
03786    ast_str_set(&str, 0, "UnitType(%u)", entry_num);
03787    unittype = astman_get_header(m, ast_str_buffer(str));
03788 
03789    if (!ast_strlen_zero(unitamount) && (sscanf(unitamount, "%30u", &entry->amount) == 1)) {
03790       entry->valid_amount = 1;
03791    }
03792 
03793    if (!ast_strlen_zero(unittype) && sscanf(unittype, "%30u", &entry->type) == 1) {
03794       entry->valid_type = 1;
03795    }
03796 
03797    return 0;
03798 }

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

Definition at line 5171 of file manager.c.

References ast_channel_name(), ast_func_read2(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_str_append(), ast_str_buffer(), ast_str_thread_get(), manager_channel_variable::isfunc, manager_event_funcbuf, manager_channel_variable::name, pbx_builtin_getvar_helper(), and var.

Referenced by __ast_manager_event_multichan().

05172 {
05173    struct manager_channel_variable *var;
05174 
05175    AST_RWLIST_RDLOCK(&channelvars);
05176    AST_LIST_TRAVERSE(&channelvars, var, entry) {
05177       const char *val;
05178       struct ast_str *res;
05179 
05180       if (var->isfunc) {
05181          res = ast_str_thread_get(&manager_event_funcbuf, 16);
05182          if (res && ast_func_read2(chan, var->name, &res, 0) == 0) {
05183             val = ast_str_buffer(res);
05184          } else {
05185             val = NULL;
05186          }
05187       } else {
05188          val = pbx_builtin_getvar_helper(chan, var->name);
05189       }
05190       ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", ast_channel_name(chan), var->name, val ? val : "");
05191    }
05192    AST_RWLIST_UNLOCK(&channelvars);
05193 }

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

events are appended to a queue from where they can be dispatched to clients.

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

05146 {
05147    struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str));
05148    static int seq;   /* sequence number */
05149 
05150    if (!tmp) {
05151       return -1;
05152    }
05153 
05154    /* need to init all fields, because ast_malloc() does not */
05155    tmp->usecount = 0;
05156    tmp->category = category;
05157    tmp->seq = ast_atomic_fetchadd_int(&seq, 1);
05158    tmp->tv = ast_tvnow();
05159    AST_RWLIST_NEXT(tmp, eq_next) = NULL;
05160    strcpy(tmp->eventdata, str);
05161 
05162    AST_RWLIST_WRLOCK(&all_events);
05163    AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next);
05164    AST_RWLIST_UNLOCK(&all_events);
05165 
05166    return 0;
05167 }

int ast_hook_send_action ( struct manager_custom_hook hook,
const char *  msg 
)

access for hooks to send action messages to ami

Registered hooks can call this function to invoke actions and they will receive responses through registered callback.

Definition at line 1920 of file manager.c.

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

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

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

References eventqent::next.

Referenced by get_perm().

01249 {
01250    const char *val = bigstr, *next;
01251 
01252    do {
01253       if ((next = strchr(val, delim))) {
01254          if (!strncmp(val, smallstr, (next - val))) {
01255             return 1;
01256          } else {
01257             continue;
01258          }
01259       } else {
01260          return !strcmp(smallstr, val);
01261       }
01262    } while (*(val = (next + 1)));
01263 
01264    return 0;
01265 }

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

05382 {
05383    struct manager_action *cur;
05384 
05385    cur = ao2_alloc(sizeof(*cur), action_destroy);
05386    if (!cur) {
05387       return -1;
05388    }
05389    if (ast_string_field_init(cur, 128)) {
05390       ao2_t_ref(cur, -1, "action object creation failed");
05391       return -1;
05392    }
05393 
05394    cur->action = action;
05395    cur->authority = auth;
05396    cur->func = func;
05397 #ifdef AST_XML_DOCS
05398    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
05399       char *tmpxml;
05400 
05401       tmpxml = ast_xmldoc_build_synopsis("manager", action, NULL);
05402       ast_string_field_set(cur, synopsis, tmpxml);
05403       ast_free(tmpxml);
05404 
05405       tmpxml = ast_xmldoc_build_syntax("manager", action, NULL);
05406       ast_string_field_set(cur, syntax, tmpxml);
05407       ast_free(tmpxml);
05408 
05409       tmpxml = ast_xmldoc_build_description("manager", action, NULL);
05410       ast_string_field_set(cur, description, tmpxml);
05411       ast_free(tmpxml);
05412 
05413       tmpxml = ast_xmldoc_build_seealso("manager", action, NULL);
05414       ast_string_field_set(cur, seealso, tmpxml);
05415       ast_free(tmpxml);
05416 
05417       tmpxml = ast_xmldoc_build_arguments("manager", action, NULL);
05418       ast_string_field_set(cur, arguments, tmpxml);
05419       ast_free(tmpxml);
05420 
05421       cur->docsrc = AST_XML_DOC;
05422    } else
05423 #endif
05424    {
05425       ast_string_field_set(cur, synopsis, synopsis);
05426       ast_string_field_set(cur, description, description);
05427 #ifdef AST_XML_DOCS
05428       cur->docsrc = AST_STATIC_DOC;
05429 #endif
05430    }
05431    if (ast_manager_register_struct(cur)) {
05432       ao2_t_ref(cur, -1, "action object registration failed");
05433       return -1;
05434    }
05435 
05436    ao2_t_ref(cur, -1, "action object registration successful");
05437    return 0;
05438 }

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 1117 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 5326 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().

05327 {
05328    struct manager_action *cur, *prev = NULL;
05329 
05330    AST_RWLIST_WRLOCK(&actions);
05331    AST_RWLIST_TRAVERSE(&actions, cur, list) {
05332       int ret;
05333 
05334       ret = strcasecmp(cur->action, act->action);
05335       if (ret == 0) {
05336          ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action);
05337          AST_RWLIST_UNLOCK(&actions);
05338          return -1;
05339       }
05340       if (ret > 0) { /* Insert these alphabetically */
05341          prev = cur;
05342          break;
05343       }
05344    }
05345 
05346    ao2_t_ref(act, +1, "action object added to list");
05347    act->registered = 1;
05348    if (prev) {
05349       AST_RWLIST_INSERT_AFTER(&actions, prev, act, list);
05350    } else {
05351       AST_RWLIST_INSERT_HEAD(&actions, act, list);
05352    }
05353 
05354    ast_verb(2, "Manager registered action %s\n", act->action);
05355 
05356    AST_RWLIST_UNLOCK(&actions);
05357 
05358    return 0;
05359 }

int ast_manager_unregister ( char *  action  ) 

support functions to register/unregister AMI action handlers,

Unregister a registered manager command.

Definition at line 5286 of file manager.c.

References manager_action::action, ao2_lock, ao2_t_ref, ao2_unlock, 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(), and unload_module().

05287 {
05288    struct manager_action *cur;
05289 
05290    AST_RWLIST_WRLOCK(&actions);
05291    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) {
05292       if (!strcasecmp(action, cur->action)) {
05293          AST_RWLIST_REMOVE_CURRENT(list);
05294          break;
05295       }
05296    }
05297    AST_RWLIST_TRAVERSE_SAFE_END;
05298    AST_RWLIST_UNLOCK(&actions);
05299 
05300    if (cur) {
05301       /*
05302        * We have removed the action object from the container so we
05303        * are no longer in a hurry.
05304        */
05305       ao2_lock(cur);
05306       cur->registered = 0;
05307       ao2_unlock(cur);
05308 
05309       ao2_t_ref(cur, -1, "action object removed from list");
05310       ast_verb(2, "Manager unregistered action %s\n", action);
05311    }
05312 
05313    return 0;
05314 }

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

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

Referenced by __iax2_show_peers(), _sip_show_peer(), _sip_show_peers(), _skinny_show_device(), _skinny_show_devices(), _skinny_show_line(), _skinny_show_lines(), action_agents(), action_challenge(), action_command(), action_confbridgelist(), action_confbridgelistrooms(), 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_meetmelistrooms(), 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_mixmonitor(), manager_modulecheck(), manager_mute_mixmonitor(), manager_mutestream(), manager_parking_status(), manager_queue_rule_show(), manager_queues_show(), manager_queues_status(), manager_queues_summary(), manager_rpt_local_nodes(), manager_rpt_status(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_show_registry(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), manager_stop_mixmonitor(), rpt_manager_do_stats(), rpt_manager_success(), and session_do().

02036 {
02037    va_list ap;
02038    struct ast_str *buf;
02039 
02040    if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
02041       return;
02042    }
02043 
02044    va_start(ap, fmt);
02045    ast_str_set_va(&buf, 0, fmt, ap);
02046    va_end(ap);
02047 
02048    if (s->f != NULL || s->session->f != NULL) {
02049       send_string(s, ast_str_buffer(buf));
02050    } else {
02051       ast_verbose("fd == -1 in astman_append, should not happen\n");
02052    }
02053 }

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

Definition at line 2607 of file manager.c.

References astman_append(), and json_escape().

Referenced by action_getconfigjson().

02608 {
02609    char *buf;
02610 
02611    buf = alloca(2 * strlen(str) + 1);
02612    json_escape(buf, str);
02613    astman_append(s, "%s", buf);
02614 }

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 1841 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_confbridgekick(), action_confbridgelist(), action_confbridgelistrooms(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdishowchannels(), action_events(), action_extensionstate(), action_filter(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_lock_unlock_helper(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_meetmelistrooms(), action_mute_unmute_helper(), 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_mixmonitor(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_optimize_away(), manager_park(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_queue_rule_show(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), manager_rpt_status(), manager_show_dialplan(), manager_show_registry(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), manager_stop_mixmonitor(), meetmemute(), process_message(), rpt_manager_do_stats(), rpt_manager_success(), start_monitor_action(), and stop_monitor_action().

01842 {
01843    return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH);
01844 }

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

Get a linked list of the Variable: headers.

Definition at line 1899 of file manager.c.

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

Referenced by action_originate(), and manager_sipnotify().

01900 {
01901    int varlen;
01902    int x;
01903    struct ast_variable *head = NULL;
01904 
01905    static const char var_hdr[] = "Variable:";
01906 
01907    /* Process all "Variable:" headers. */
01908    varlen = strlen(var_hdr);
01909    for (x = 0; x < m->hdrcount; x++) {
01910       if (strncasecmp(var_hdr, m->headers[x], varlen)) {
01911          continue;
01912       }
01913       head = man_do_variable_value(head, m->headers[x] + varlen);
01914    }
01915 
01916    return head;
01917 }

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

Send ack in manager transaction.

Definition at line 2104 of file manager.c.

References astman_send_response_full().

Referenced by action_add_agi_cmd(), action_agent_logoff(), action_agents(), action_aocmessage(), action_atxfer(), action_bridge(), action_confbridgekick(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_dahdishowchannels(), action_filter(), action_hangup(), action_lock_unlock_helper(), action_login(), action_mute_unmute_helper(), action_originate(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), change_monitor_action(), do_pause_or_unpause(), manager_add_queue_member(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_jabber_send(), manager_list_voicemail_users(), manager_moduleload(), manager_optimize_away(), manager_park(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), manager_sipnotify(), meetmemute(), start_monitor_action(), and stop_monitor_action().

02105 {
02106    astman_send_response_full(s, m, "Success", msg, NULL);
02107 }

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

Send error in manager transaction.

Definition at line 2099 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_confbridgekick(), action_confbridgelist(), action_confbridgelistrooms(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_coreshowchannels(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_events(), action_extensionstate(), action_filter(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_lock_unlock_helper(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_meetmelistrooms(), action_mute_unmute_helper(), 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(), manager_add_queue_member(), manager_data_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_jabber_send(), manager_mixmonitor(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_optimize_away(), manager_park(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_remove_queue_member(), manager_rpt_status(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_line(), manager_stop_mixmonitor(), meetmemute(), process_message(), rpt_manager_do_stats(), start_monitor_action(), and stop_monitor_action().

02100 {
02101    astman_send_response_full(s, m, "Error", error, NULL);
02102 }

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

References astman_send_response_full().

Referenced by action_logoff(), and action_waitevent().

02095 {
02096    astman_send_response_full(s, m, resp, msg, NULL);
02097 }

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

send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field.

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

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

02075 {
02076    const char *id = astman_get_header(m, "ActionID");
02077 
02078    astman_append(s, "Response: %s\r\n", resp);
02079    if (!ast_strlen_zero(id)) {
02080       astman_append(s, "ActionID: %s\r\n", id);
02081    }
02082    if (listflag) {
02083       astman_append(s, "EventList: %s\r\n", listflag);   /* Start, complete, cancelled */
02084    }
02085    if (msg == MSG_MOREDATA) {
02086       return;
02087    } else if (msg) {
02088       astman_append(s, "Message: %s\r\n\r\n", msg);
02089    } else {
02090       astman_append(s, "\r\n");
02091    }
02092 }

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

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

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

Convert authority code to a list of options.

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

01225 {
01226    int i;
01227    char *sep = "";
01228 
01229    ast_str_reset(*res);
01230    for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
01231       if (authority & perms[i].num) {
01232          ast_str_append(res, 0, "%s%s", sep, perms[i].label);
01233          sep = ",";
01234       }
01235    }
01236 
01237    if (ast_str_strlen(*res) == 0)   /* replace empty string with something sensible */
01238       ast_str_append(res, 0, "<none>");
01239 
01240    return ast_str_buffer(*res);
01241 }

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

Definition at line 4283 of file manager.c.

References CMP_MATCH, and CMP_STOP.

Referenced by match_filter().

04284 {
04285    regex_t *regex_filter = obj;
04286    const char *eventdata = arg;
04287    int *result = data;
04288 
04289    if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
04290       *result = 0;
04291       return (CMP_MATCH | CMP_STOP);
04292    }
04293 
04294    *result = 1;
04295    return 0;
04296 }

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

01366 {
01367    struct mansession_session *newsession;
01368 
01369    if (!(newsession = ao2_alloc(sizeof(*newsession), session_destructor))) {
01370       return NULL;
01371    }
01372 
01373    if (!(newsession->whitefilters = ao2_container_alloc(1, NULL, NULL))) {
01374       ao2_ref(newsession, -1);
01375       return NULL;
01376    }
01377 
01378    if (!(newsession->blackfilters = ao2_container_alloc(1, NULL, NULL))) {
01379       ao2_ref(newsession, -1); /* session_destructor will cleanup the other filter */
01380       return NULL;
01381    }
01382 
01383    newsession->fd = -1;
01384    newsession->waiting_thread = AST_PTHREADT_NULL;
01385    newsession->writetimeout = 100;
01386    newsession->send_events = -1;
01387    newsession->sin = sin;
01388 
01389    ao2_link(sessions, newsession);
01390 
01391    return newsession;
01392 }

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

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

03596 {
03597    char *cmd_copy, *cur_cmd;
03598    char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, };
03599    int i;
03600 
03601    cmd_copy = ast_strdupa(cmd);
03602    for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) {
03603       cur_cmd = ast_strip(cur_cmd);
03604       if (ast_strlen_zero(cur_cmd)) {
03605          i--;
03606          continue;
03607       }
03608 
03609       cmd_words[i] = cur_cmd;
03610    }
03611 
03612    for (i = 0; i < ARRAY_LEN(command_blacklist); i++) {
03613       int j, match = 1;
03614 
03615       for (j = 0; command_blacklist[i].words[j]; j++) {
03616          if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) {
03617             match = 0;
03618             break;
03619          }
03620       }
03621 
03622       if (match) {
03623          return 1;
03624       }
03625    }
03626 
03627    return 0;
03628 }

int check_manager_enabled ( void   ) 

Check if AMI is enabled.

Definition at line 1132 of file manager.c.

Referenced by handle_show_settings().

01133 {
01134    return manager_enabled;
01135 }

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

Definition at line 1408 of file manager.c.

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

Referenced by process_message().

01409 {
01410    struct mansession_session *session = ao2_find(sessions, (char *) name, 0);
01411    int inuse = 0;
01412 
01413    if (session) {
01414       inuse = 1;
01415       unref_mansession(session);
01416    }
01417    return inuse;
01418 }

int check_webmanager_enabled ( void   ) 

Check if AMI/HTTP is enabled.

Definition at line 1137 of file manager.c.

Referenced by action_coresettings(), and handle_show_settings().

01138 {
01139    return (webmanager_enabled && manager_enabled);
01140 }

static void destroy_fast_originate_helper ( struct fast_originate_helper doomed  )  [static]

static int do_message ( struct mansession s  )  [static]

Definition at line 4937 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(), message::hdrcount, message::headers, mansession_session::inbuf, LOG_ERROR, mansession_lock(), mansession_unlock(), process_events(), process_message(), mansession::session, and mansession_session::sin.

Referenced by session_do().

04938 {
04939    struct message m = { 0 };
04940    char header_buf[sizeof(s->session->inbuf)] = { '\0' };
04941    int res;
04942    int idx;
04943    int hdr_loss;
04944    time_t now;
04945 
04946    hdr_loss = 0;
04947    for (;;) {
04948       /* Check if any events are pending and do them if needed */
04949       if (process_events(s)) {
04950          res = -1;
04951          break;
04952       }
04953       res = get_input(s, header_buf);
04954       if (res == 0) {
04955          /* No input line received. */
04956          if (!s->session->authenticated) {
04957             if (time(&now) == -1) {
04958                ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
04959                res = -1;
04960                break;
04961             }
04962 
04963             if (now - s->session->authstart > authtimeout) {
04964                if (displayconnects) {
04965                   ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout);
04966                }
04967                res = -1;
04968                break;
04969             }
04970          }
04971          continue;
04972       } else if (res > 0) {
04973          /* Input line received. */
04974          if (ast_strlen_zero(header_buf)) {
04975             if (hdr_loss) {
04976                mansession_lock(s);
04977                astman_send_error(s, &m, "Too many lines in message or allocation failure");
04978                mansession_unlock(s);
04979                res = 0;
04980             } else {
04981                res = process_message(s, &m) ? -1 : 0;
04982             }
04983             break;
04984          } else if (m.hdrcount < ARRAY_LEN(m.headers)) {
04985             m.headers[m.hdrcount] = ast_strdup(header_buf);
04986             if (!m.headers[m.hdrcount]) {
04987                /* Allocation failure. */
04988                hdr_loss = 1;
04989             } else {
04990                ++m.hdrcount;
04991             }
04992          } else {
04993             /* Too many lines in message. */
04994             hdr_loss = 1;
04995          }
04996       } else {
04997          /* Input error. */
04998          break;
04999       }
05000    }
05001 
05002    /* Free AMI request headers. */
05003    for (idx = 0; idx < m.hdrcount; ++idx) {
05004       ast_free((void *) m.headers[idx]);
05005    }
05006    return res;
05007 }

static void event_filter_destructor ( void *  obj  )  [static]

Definition at line 1328 of file manager.c.

Referenced by manager_add_filter().

01329 {
01330    regex_t *regex_filter = obj;
01331    regfree(regex_filter);
01332 }

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

Definition at line 3721 of file manager.c.

References fast_originate_helper::account, fast_originate_helper::app, fast_originate_helper::appdata, ast_channel_name(), AST_CHANNEL_NAME, ast_channel_uniqueid(), ast_channel_unlock, ast_manager_event_multichan, ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_strlen_zero(), fast_originate_helper::cap, 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::idtext, fast_originate_helper::priority, S_OR, fast_originate_helper::tech, fast_originate_helper::timeout, and fast_originate_helper::vars.

Referenced by action_originate().

03722 {
03723    struct fast_originate_helper *in = data;
03724    int res;
03725    int reason = 0;
03726    struct ast_channel *chan = NULL, *chans[1];
03727    char requested_channel[AST_CHANNEL_NAME];
03728 
03729    if (!ast_strlen_zero(in->app)) {
03730       res = ast_pbx_outgoing_app(in->tech, in->cap, in->data,
03731          in->timeout, in->app, in->appdata, &reason, 1,
03732          S_OR(in->cid_num, NULL),
03733          S_OR(in->cid_name, NULL),
03734          in->vars, in->account, &chan);
03735    } else {
03736       res = ast_pbx_outgoing_exten(in->tech, in->cap, in->data,
03737          in->timeout, in->context, in->exten, in->priority, &reason, 1,
03738          S_OR(in->cid_num, NULL),
03739          S_OR(in->cid_name, NULL),
03740          in->vars, in->account, &chan);
03741    }
03742    /* Any vars memory was passed to the ast_pbx_outgoing_xxx() calls. */
03743    in->vars = NULL;
03744 
03745    if (!chan) {
03746       snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);
03747    }
03748    /* Tell the manager what happened with the channel */
03749    chans[0] = chan;
03750    ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans,
03751       "%s"
03752       "Response: %s\r\n"
03753       "Channel: %s\r\n"
03754       "Context: %s\r\n"
03755       "Exten: %s\r\n"
03756       "Reason: %d\r\n"
03757       "Uniqueid: %s\r\n"
03758       "CallerIDNum: %s\r\n"
03759       "CallerIDName: %s\r\n",
03760       in->idtext, res ? "Failure" : "Success",
03761       chan ? ast_channel_name(chan) : requested_channel, in->context, in->exten, reason,
03762       chan ? ast_channel_uniqueid(chan) : "<null>",
03763       S_OR(in->cid_num, "<unknown>"),
03764       S_OR(in->cid_name, "<unknown>")
03765       );
03766 
03767    /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
03768    if (chan) {
03769       ast_channel_unlock(chan);
03770    }
03771    destroy_fast_originate_helper(in);
03772    return NULL;
03773 }

static void free_channelvars ( void   )  [static]

Definition at line 7049 of file manager.c.

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

Referenced by __init_manager(), and load_channelvars().

07050 {
07051    struct manager_channel_variable *var;
07052    AST_RWLIST_WRLOCK(&channelvars);
07053    while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) {
07054       ast_free(var);
07055    }
07056    AST_RWLIST_UNLOCK(&channelvars);
07057 }

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 4840 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, mansession_session::pending_event, mansession::session, mansession_session::sin, ast_frame::src, and mansession_session::waiting_thread.

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

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

01426 {
01427    struct ast_manager_user *user = NULL;
01428 
01429    AST_RWLIST_TRAVERSE(&users, user, list) {
01430       if (!strcasecmp(user->username, name)) {
01431          break;
01432       }
01433    }
01434 
01435    return user;
01436 }

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

Definition at line 1267 of file manager.c.

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

Referenced by __init_manager(), and strings_to_mask().

01268 {
01269    int x = 0, ret = 0;
01270 
01271    if (!instr) {
01272       return 0;
01273    }
01274 
01275    for (x = 0; x < ARRAY_LEN(perms); x++) {
01276       if (ast_instring(instr, perms[x].label, ',')) {
01277          ret |= perms[x].num;
01278       }
01279    }
01280 
01281    return ret;
01282 }

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

01147 {
01148    struct eventqent *ret;
01149 
01150    AST_RWLIST_WRLOCK(&all_events);
01151    ret = AST_RWLIST_LAST(&all_events);
01152    /* the list is never empty now, but may become so when
01153     * we optimize it in the future, so be prepared.
01154     */
01155    if (ret) {
01156       ast_atomic_fetchadd_int(&ret->usecount, 1);
01157    }
01158    AST_RWLIST_UNLOCK(&all_events);
01159    return ret;
01160 }

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

01760 {
01761    switch (cmd) {
01762    case CLI_INIT:
01763       e->command = "manager reload";
01764       e->usage =
01765          "Usage: manager reload\n"
01766          "       Reloads the manager configuration.\n";
01767       return NULL;
01768    case CLI_GENERATE:
01769       return NULL;
01770    }
01771    if (a->argc > 2) {
01772       return CLI_SHOWUSAGE;
01773    }
01774    reload_manager();
01775    return CLI_SUCCESS;
01776 }

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

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

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

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

Definition at line 1558 of file manager.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_strdup, authority_to_str(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_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, ast_manager_user::username, ast_cli_args::word, and ast_manager_user::writeperm.

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

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

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

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

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

Definition at line 1456 of file manager.c.

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

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

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

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

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

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

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

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

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

helper function for action_updateconfig

Definition at line 2665 of file manager.c.

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

Referenced by action_updateconfig().

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

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

Referenced by astman_append_json().

02588 {
02589    for (; *in; in++) {
02590       if (*in == '\\' || *in == '\"') {
02591          *out++ = '\\';
02592       }
02593       *out++ = *in;
02594    }
02595    *out = '\0';
02596 }

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

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

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

static enum add_filter_result manager_add_filter ( const char *  filter_pattern,
struct ao2_container whitefilters,
struct ao2_container blackfilters 
) [static]

Definition at line 4351 of file manager.c.

References ao2_t_alloc, ao2_t_link, ao2_t_ref, event_filter_destructor(), FILTER_ALLOC_FAILED, FILTER_COMPILE_FAIL, and FILTER_SUCCESS.

Referenced by __init_manager(), and action_filter().

04351                                                                                                                                                      {
04352    regex_t *new_filter = ao2_t_alloc(sizeof(*new_filter), event_filter_destructor, "event_filter allocation");
04353    int is_blackfilter;
04354 
04355    if (!new_filter) {
04356       return FILTER_ALLOC_FAILED;
04357    }
04358 
04359    if (filter_pattern[0] == '!') {
04360       is_blackfilter = 1;
04361       filter_pattern++;
04362    } else {
04363       is_blackfilter = 0;
04364    }
04365 
04366    if (regcomp(new_filter, filter_pattern, 0)) {
04367       ao2_t_ref(new_filter, -1, "failed to make regx");
04368       return FILTER_COMPILE_FAIL;
04369    }
04370 
04371    if (is_blackfilter) {
04372       ao2_t_link(blackfilters, new_filter, "link new filter into black user container");
04373    } else {
04374       ao2_t_link(whitefilters, new_filter, "link new filter into white user container");
04375    }
04376 
04377         return FILTER_SUCCESS;
04378 }

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

01443 {
01444    struct ast_manager_user *user = NULL;
01445    int ret = 0;
01446 
01447    AST_RWLIST_RDLOCK(&users);
01448    if ((user = get_manager_by_name_locked (session->username))) {
01449       ret = user->displayconnects;
01450    }
01451    AST_RWLIST_UNLOCK(&users);
01452 
01453    return ret;
01454 }

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

Manager function to check if module is loaded.

Definition at line 4634 of file manager.c.

References ast_copy_string(), ast_debug, ast_file_version_find(), ast_module_check(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), and version.

Referenced by __init_manager().

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

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

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

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

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

Definition at line 5316 of file manager.c.

References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.

Referenced by __init_manager().

05317 {
05318    /* Notify managers of change */
05319    char hint[512];
05320    ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten);
05321 
05322    manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state);
05323    return 0;
05324 }

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

Definition at line 1394 of file manager.c.

References CMP_MATCH, str, and mansession_session::username.

Referenced by __init_manager().

01395 {
01396    struct mansession_session *s = obj;
01397    char *str = arg;
01398    return !strcasecmp(s->username, str) ? CMP_MATCH : 0;
01399 }

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

References ast_mutex_lock, and mansession::lock.

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

02121 {
02122    ast_mutex_lock(&s->lock);
02123 }

static void mansession_unlock ( struct mansession s  )  [static]

Unlock the 'mansession' structure.

Definition at line 2126 of file manager.c.

References ast_mutex_unlock, and mansession::lock.

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

02127 {
02128    ast_mutex_unlock(&s->lock);
02129 }

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

Definition at line 4380 of file manager.c.

References ao2_container_count(), ao2_t_callback_data, ast_debug, blackfilter_cmp_fn(), mansession_session::blackfilters, OBJ_NODATA, mansession::session, whitefilter_cmp_fn(), and mansession_session::whitefilters.

Referenced by process_events().

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

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

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

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

Process an AMI message, performing desired action. Return 0 on success, -1 on error that require the session to be destroyed.

Definition at line 4736 of file manager.c.

References __astman_get_header(), manager_action::action, action_find(), 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().

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

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

01167 {
01168    struct eventqent *ev;
01169    struct timeval now = ast_tvnow();
01170 
01171    AST_RWLIST_WRLOCK(&all_events);
01172    while ( (ev = AST_RWLIST_FIRST(&all_events)) &&
01173        ev->usecount == 0 && AST_RWLIST_NEXT(ev, eq_next)) {
01174       AST_RWLIST_REMOVE_HEAD(&all_events, eq_next);
01175       ast_free(ev);
01176    }
01177 
01178    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&all_events, ev, eq_next) {
01179       /* Never release the last event */
01180       if (!AST_RWLIST_NEXT(ev, eq_next)) {
01181          break;
01182       }
01183 
01184       /* 2.5 times whatever the HTTP timeout is (maximum 2.5 hours) is the maximum time that we will definitely cache an event */
01185       if (ev->usecount == 0 && ast_tvdiff_sec(now, ev->tv) > (httptimeout > 3600 ? 3600 : httptimeout) * 2.5) {
01186          AST_RWLIST_REMOVE_CURRENT(eq_next);
01187          ast_free(ev);
01188       }
01189    }
01190    AST_RWLIST_TRAVERSE_SAFE_END;
01191    AST_RWLIST_UNLOCK(&all_events);
01192 }

static void purge_sessions ( int  n_max  )  [static]

remove at most n_max stale session from the list.

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

05117 {
05118    struct mansession_session *session;
05119    time_t now = time(NULL);
05120    struct ao2_iterator i;
05121 
05122    i = ao2_iterator_init(sessions, 0);
05123    while ((session = ao2_iterator_next(&i)) && n_max > 0) {
05124       ao2_lock(session);
05125       if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) {
05126          if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) {
05127             ast_verb(2, "HTTP Manager '%s' timed out from %s\n",
05128                session->username, ast_inet_ntoa(session->sin.sin_addr));
05129          }
05130          ao2_unlock(session);
05131          session_destroy(session);
05132          n_max--;
05133       } else {
05134          ao2_unlock(session);
05135          unref_mansession(session);
05136       }
05137    }
05138    ao2_iterator_destroy(&i);
05139 }

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

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

02242 {
02243    struct sockaddr_in sin_local;
02244    char session_id[32];
02245    struct ast_security_event_successful_auth successful_auth = {
02246       .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH,
02247       .common.version    = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
02248       .common.service    = "AMI",
02249       .common.account_id = s->session->username,
02250       .common.session_tv = &s->session->sessionstart_tv,
02251       .common.local_addr = {
02252          .sin       = mansession_encode_sin_local(s, &sin_local),
02253          .transport = mansession_get_transport(s),
02254       },
02255       .common.remote_addr = {
02256          .sin       = &s->session->sin,
02257          .transport = mansession_get_transport(s),
02258       },
02259       .common.session_id = session_id,
02260    };
02261 
02262    snprintf(session_id, sizeof(session_id), "%p", s->session);
02263 
02264    ast_security_event_report(AST_SEC_EVT(&successful_auth));
02265 }

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

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

02190 {
02191    struct sockaddr_in sin_local;
02192    char session_id[32];
02193    struct ast_security_event_failed_acl failed_acl_event = {
02194       .common.event_type = AST_SECURITY_EVENT_FAILED_ACL,
02195       .common.version    = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
02196       .common.service    = "AMI",
02197       .common.account_id = username,
02198       .common.session_tv = &s->session->sessionstart_tv,
02199       .common.local_addr = {
02200          .sin       = mansession_encode_sin_local(s, &sin_local),
02201          .transport = mansession_get_transport(s),
02202       },
02203       .common.remote_addr = {
02204          .sin       = &s->session->sin,
02205          .transport = mansession_get_transport(s),
02206       },
02207       .common.session_id = session_id,
02208    };
02209 
02210    snprintf(session_id, sizeof(session_id), "%p", s->session);
02211 
02212    ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
02213 }

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

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

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

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

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

02216 {
02217    struct sockaddr_in sin_local;
02218    char session_id[32];
02219    struct ast_security_event_inval_password inval_password = {
02220       .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD,
02221       .common.version    = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
02222       .common.service    = "AMI",
02223       .common.account_id = username,
02224       .common.session_tv = &s->session->sessionstart_tv,
02225       .common.local_addr = {
02226          .sin       = mansession_encode_sin_local(s, &sin_local),
02227          .transport = mansession_get_transport(s),
02228       },
02229       .common.remote_addr = {
02230          .sin       = &s->session->sin,
02231          .transport = mansession_get_transport(s),
02232       },
02233       .common.session_id = session_id,
02234    };
02235 
02236    snprintf(session_id, sizeof(session_id), "%p", s->session);
02237 
02238    ast_security_event_report(AST_SEC_EVT(&inval_password));
02239 }

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

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

02164 {
02165    struct sockaddr_in sin_local;
02166    char session_id[32];
02167    struct ast_security_event_inval_acct_id inval_acct_id = {
02168       .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID,
02169       .common.version    = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
02170       .common.service    = "AMI",
02171       .common.account_id = username,
02172       .common.session_tv = &s->session->sessionstart_tv,
02173       .common.local_addr = {
02174          .sin       = mansession_encode_sin_local(s, &sin_local),
02175          .transport = mansession_get_transport(s),
02176       },
02177       .common.remote_addr = {
02178          .sin       = &s->session->sin,
02179          .transport = mansession_get_transport(s),
02180       },
02181       .common.session_id = session_id,
02182    };
02183 
02184    snprintf(session_id, sizeof(session_id), "%p", s);
02185 
02186    ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
02187 }

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

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

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

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

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

02268 {
02269    struct sockaddr_in sin_local;
02270    char session_id[32];
02271    char request_type[64];
02272    struct ast_security_event_req_not_allowed req_not_allowed = {
02273       .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED,
02274       .common.version    = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
02275       .common.service    = "AMI",
02276       .common.account_id = s->session->username,
02277       .common.session_tv = &s->session->sessionstart_tv,
02278       .common.local_addr = {
02279          .sin       = mansession_encode_sin_local(s, &sin_local),
02280          .transport = mansession_get_transport(s),
02281       },
02282       .common.remote_addr = {
02283          .sin       = &s->session->sin,
02284          .transport = mansession_get_transport(s),
02285       },
02286       .common.session_id = session_id,
02287 
02288       .request_type      = request_type,
02289    };
02290 
02291    snprintf(session_id, sizeof(session_id), "%p", s->session);
02292    snprintf(request_type, sizeof(request_type), "Action: %s", action);
02293 
02294    ast_security_event_report(AST_SEC_EVT(&req_not_allowed));
02295 }

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

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

02359 {
02360    struct sockaddr_in sin_local;
02361    char session_id[32];
02362    struct ast_security_event_session_limit session_limit = {
02363       .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT,
02364       .common.version    = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
02365       .common.service    = "AMI",
02366       .common.account_id = s->session->username,
02367       .common.session_tv = &s->session->sessionstart_tv,
02368       .common.local_addr = {
02369          .sin       = mansession_encode_sin_local(s, &sin_local),
02370          .transport = mansession_get_transport(s),
02371       },
02372       .common.remote_addr = {
02373          .sin       = &s->session->sin,
02374          .transport = mansession_get_transport(s),
02375       },
02376       .common.session_id = session_id,
02377    };
02378 
02379    snprintf(session_id, sizeof(session_id), "%p", s->session);
02380 
02381    ast_security_event_report(AST_SEC_EVT(&session_limit));
02382 }

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

01996 {
01997    int res;
01998    FILE *f = s->f ? s->f : s->session->f;
01999    int fd = s->f ? s->fd : s->session->fd;
02000 
02001    /* It's a result from one of the hook's action invocation */
02002    if (s->hook) {
02003       /*
02004        * to send responses, we're using the same function
02005        * as for receiving events. We call the event "HookResponse"
02006        */
02007       s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string);
02008       return 0;
02009    }
02010        
02011    if ((res = ast_careful_fwrite(f, fd, string, strlen(string), s->session->writetimeout))) {
02012       s->write_error = 1;
02013    }
02014 
02015    return res;
02016 }

static void session_destroy ( struct mansession_session s  )  [static]

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

01402 {
01403    unref_mansession(s);
01404    ao2_unlink(sessions, s);
01405 }

static void session_destructor ( void *  obj  )  [static]

Definition at line 1334 of file manager.c.

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

Referenced by build_mansession().

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

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

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

05018 {
05019    struct ast_tcptls_session_instance *ser = data;
05020    struct mansession_session *session;
05021    struct mansession s = {
05022       .tcptls_session = data,
05023    };
05024    int flags;
05025    int res;
05026    struct sockaddr_in ser_remote_address_tmp;
05027    struct protoent *p;
05028 
05029    if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
05030       fclose(ser->f);
05031       ast_atomic_fetchadd_int(&unauth_sessions, -1);
05032       goto done;
05033    }
05034 
05035    ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
05036    session = build_mansession(ser_remote_address_tmp);
05037 
05038    if (session == NULL) {
05039       fclose(ser->f);
05040       ast_atomic_fetchadd_int(&unauth_sessions, -1);
05041       goto done;
05042    }
05043 
05044    /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
05045     * This is necessary to prevent delays (caused by buffering) as we
05046     * write to the socket in bits and peices. */
05047    p = getprotobyname("tcp");
05048    if (p) {
05049       int arg = 1;
05050       if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
05051          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));
05052       }
05053    } else {
05054       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");
05055    }
05056 
05057    flags = fcntl(ser->fd, F_GETFL);
05058    if (!block_sockets) { /* make sure socket is non-blocking */
05059       flags |= O_NONBLOCK;
05060    } else {
05061       flags &= ~O_NONBLOCK;
05062    }
05063    fcntl(ser->fd, F_SETFL, flags);
05064 
05065    ao2_lock(session);
05066    /* Hook to the tail of the event queue */
05067    session->last_ev = grab_last();
05068 
05069    ast_mutex_init(&s.lock);
05070 
05071    /* these fields duplicate those in the 'ser' structure */
05072    session->fd = s.fd = ser->fd;
05073    session->f = s.f = ser->f;
05074    session->sin = ser_remote_address_tmp;
05075    s.session = session;
05076 
05077    AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
05078 
05079    if(time(&session->authstart) == -1) {
05080       ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
05081       ast_atomic_fetchadd_int(&unauth_sessions, -1);
05082       ao2_unlock(session);
05083       session_destroy(session);
05084       goto done;
05085    }
05086    ao2_unlock(session);
05087 
05088    astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION);   /* welcome prompt */
05089    for (;;) {
05090       if ((res = do_message(&s)) < 0 || s.write_error) {
05091          break;
05092       }
05093    }
05094    /* session is over, explain why and terminate */
05095    if (session->authenticated) {
05096       if (manager_displayconnects(session)) {
05097          ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
05098       }
05099    } else {
05100       ast_atomic_fetchadd_int(&unauth_sessions, -1);
05101       if (displayconnects) {
05102          ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
05103       }
05104    }
05105 
05106    session_destroy(session);
05107 
05108    ast_mutex_destroy(&s.lock);
05109 done:
05110    ao2_ref(ser, -1);
05111    ser = NULL;
05112    return NULL;
05113 }

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

02136 {
02137    int maskint = strings_to_mask(eventmask);
02138 
02139    ao2_lock(s->session);
02140    if (maskint >= 0) {
02141       s->session->send_events = maskint;
02142    }
02143    ao2_unlock(s->session);
02144 
02145    return maskint;
02146 }

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

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

Referenced by set_eventmask().

01289 {
01290    const char *p;
01291 
01292    if (ast_strlen_zero(string)) {
01293       return -1;
01294    }
01295 
01296    for (p = string; *p; p++) {
01297       if (*p < '0' || *p > '9') {
01298          break;
01299       }
01300    }
01301    if (!*p) { /* all digits */
01302       return atoi(string);
01303    }
01304    if (ast_false(string)) {
01305       return 0;
01306    }
01307    if (ast_true(string)) { /* all permissions */
01308       int x, ret = 0;
01309       for (x = 0; x < ARRAY_LEN(perms); x++) {
01310          ret |= perms[x].num;
01311       }
01312       return ret;
01313    }
01314    return get_perm(string);
01315 }

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

References ao2_ref, and ast_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().

01320 {
01321    int refcount = ao2_ref(s, -1);
01322         if (manager_debug) {
01323       ast_debug(1, "Mansession: %p refcount now %d\n", s, refcount - 1);
01324    }
01325    return s;
01326 }

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

Definition at line 4269 of file manager.c.

References CMP_MATCH, and CMP_STOP.

Referenced by match_filter().

04270 {
04271    regex_t *regex_filter = obj;
04272    const char *eventdata = arg;
04273    int *result = data;
04274 
04275    if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
04276       *result = 1;
04277       return (CMP_MATCH | CMP_STOP);
04278    }
04279 
04280    return 0;
04281 }


Variable Documentation

int allowmultiplelogin = 1 [static]

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

Referenced by astman_append().

int authlimit [static]

Definition at line 939 of file manager.c.

int authtimeout [static]

Definition at line 938 of file manager.c.

int block_sockets [static]

Definition at line 945 of file manager.c.

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

int broken_events_action = 0 [static]

Definition at line 934 of file manager.c.

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

Referenced by check_blacklist().

int displayconnects = 1 [static]

Definition at line 930 of file manager.c.

char global_realm[MAXHOSTNAMELEN] [static]

Default realm

Definition at line 943 of file manager.c.

Referenced by __init_manager(), and auth_http_callback().

int httptimeout = 60 [static]

Definition at line 933 of file manager.c.

char* manager_channelvars [static]

Definition at line 940 of file manager.c.

int manager_debug = 0 [static]

enable some debugging code in the manager

Definition at line 937 of file manager.c.

int manager_enabled = 0 [static]

Definition at line 935 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 5196 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 5169 of file manager.c.

Referenced by append_channel_vars().

struct permalias perms[] [static]

helper functions to convert back and forth between string and numeric representation of set of flags

Referenced by action_events(), authority_to_str(), get_perm(), and strings_to_mask().

struct ao2_container* sessions = NULL [static]

Definition at line 1048 of file manager.c.

int timestampevents [static]

Definition at line 932 of file manager.c.

int unauth_sessions = 0 [static]

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

Referenced by action_userevent().

int webmanager_enabled = 0 [static]

Definition at line 936 of file manager.c.

const char* words[AST_MAX_CMD_LEN] [inherited]

Definition at line 961 of file manager.c.


Generated on Sat Feb 11 06:37:02 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6