Mon Mar 12 2012 21:47:04

Asterisk developer's documentation


AMI functions

callback to display queues status in manager More...

Data Structures

struct  actions
 list of actions registered More...
struct  all_events
struct  ast_manager_user
 user descriptor, as read from the config file. More...
struct  channelvars
struct  eventqent
struct  fast_originate_helper
 helper function for originate More...
struct  manager_channel_variable
struct  manager_hooks
 list of hooks registered More...
struct  mansession
struct  mansession_session
struct  permalias
struct  users
 list of users found in the config file More...

Defines

#define ASTMAN_APPEND_BUF_INITSIZE   256
 initial allocated size for the astman_append_buf
#define DEFAULT_REALM   "asterisk"
#define GET_HEADER_FIRST_MATCH   0
#define GET_HEADER_LAST_MATCH   1
#define GET_HEADER_SKIP_EMPTY   2
#define MANAGER_EVENT_BUF_INITSIZE   256
#define MAX_BLACKLIST_CMD_LEN   2
 Descriptor for a manager session, either on the AMI socket or over HTTP.
#define MSG_MOREDATA   ((char *)astman_send_response)
 send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field.

Enumerations

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

Functions

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

Variables

static struct actions actions
static struct all_events all_events
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
static struct channelvars channelvars
struct {
   const char *   words [AST_MAX_CMD_LEN]
command_blacklist []
static const int DEFAULT_AUTHLIMIT = 50
static const int DEFAULT_AUTHTIMEOUT = 30
static const int DEFAULT_BLOCKSOCKETS = 0
static const int DEFAULT_BROKENEVENTSACTION = 0
static const int DEFAULT_DISPLAYCONNECTS = 1
static const int DEFAULT_ENABLED = 0
static const int DEFAULT_HTTPTIMEOUT = 60
static const int DEFAULT_MANAGERDEBUG = 0
static const int DEFAULT_TIMESTAMPEVENTS = 0
static const int DEFAULT_WEBENABLED = 0
static int displayconnects
static char global_realm [MAXHOSTNAMELEN]
static int httptimeout
static char * manager_channelvars
static int manager_debug = 0
static int manager_enabled = 0
static struct ast_threadstorage manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , }
static struct ast_threadstorage manager_event_funcbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_funcbuf , .custom_init = NULL , }
static struct manager_hooks manager_hooks
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 struct users users
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 1989 of file manager.c.

Referenced by astman_append().

#define DEFAULT_REALM   "asterisk"

Definition at line 902 of file manager.c.

Referenced by __init_manager(), and reload_config().

#define GET_HEADER_FIRST_MATCH   0

Definition at line 1750 of file manager.c.

Referenced by astman_get_header().

#define GET_HEADER_LAST_MATCH   1

Definition at line 1751 of file manager.c.

Referenced by __astman_get_header().

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 1752 of file manager.c.

Referenced by __astman_get_header(), and process_message().

#define MANAGER_EVENT_BUF_INITSIZE   256

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

Referenced by check_blacklist().

#define MSG_MOREDATA   ((char *)astman_send_response)

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

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

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

Definition at line 2030 of file manager.c.

Referenced by astman_send_response_full(), and astman_start_ack().


Enumeration Type Documentation

enum error_type

Doxygen group

Enumerator:
UNKNOWN_ACTION 
UNKNOWN_CATEGORY 
UNSPECIFIED_CATEGORY 
UNSPECIFIED_ARGUMENT 
FAILURE_ALLOCATION 
FAILURE_NEWCAT 
FAILURE_DELCAT 
FAILURE_EMPTYCAT 
FAILURE_UPDATE 
FAILURE_DELETE 
FAILURE_APPEND 

Definition at line 834 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:
categoryEvent category, matches manager authorization
eventEvent name
chancountNumber of channels in chans parameter
chansA pointer to an array of channels involved in the event
contentsFormat string describing event
Since:
1.8

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

{
   struct mansession_session *session;
   struct manager_custom_hook *hook;
   struct ast_str *auth = ast_str_alloca(80);
   const char *cat_str;
   va_list ap;
   struct timeval now;
   struct ast_str *buf;
   int i;

   if (!(sessions && ao2_container_count(sessions)) && AST_RWLIST_EMPTY(&manager_hooks)) {
      return 0;
   }
   
   if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) {
      return -1;
   }

   cat_str = authority_to_str(category, &auth);
   ast_str_set(&buf, 0,
         "Event: %s\r\nPrivilege: %s\r\n",
          event, cat_str);

   if (timestampevents) {
      now = ast_tvnow();
      ast_str_append(&buf, 0,
            "Timestamp: %ld.%06lu\r\n",
             (long)now.tv_sec, (unsigned long) now.tv_usec);
   }
   if (manager_debug) {
      static int seq;
      ast_str_append(&buf, 0,
            "SequenceNumber: %d\r\n",
             ast_atomic_fetchadd_int(&seq, 1));
      ast_str_append(&buf, 0,
            "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func);
   }

   va_start(ap, fmt);
   ast_str_append_va(&buf, 0, fmt, ap);
   va_end(ap);
   for (i = 0; i < chancount; i++) {
      append_channel_vars(&buf, chans[i]);
   }

   ast_str_append(&buf, 0, "\r\n");

   append_event(ast_str_buffer(buf), category);

   /* Wake up any sleeping sessions */
   if (sessions) {
      struct ao2_iterator i;
      i = ao2_iterator_init(sessions, 0);
      while ((session = ao2_iterator_next(&i))) {
         ao2_lock(session);
         if (session->waiting_thread != AST_PTHREADT_NULL) {
            pthread_kill(session->waiting_thread, SIGURG);
         } else {
            /* We have an event to process, but the mansession is
             * not waiting for it. We still need to indicate that there
             * is an event waiting so that get_input processes the pending
             * event instead of polling.
             */
            session->pending_event = 1;
         }
         ao2_unlock(session);
         unref_mansession(session);
      }
      ao2_iterator_destroy(&i);
   }

   if (!AST_RWLIST_EMPTY(&manager_hooks)) {
      AST_RWLIST_RDLOCK(&manager_hooks);
      AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) {
         hook->helper(category, event, ast_str_buffer(buf));
      }
      AST_RWLIST_UNLOCK(&manager_hooks);
   }

   return 0;
}
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 1767 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().

{
   int x, l = strlen(var);
   const char *result = "";

   for (x = 0; x < m->hdrcount; x++) {
      const char *h = m->headers[x];
      if (!strncasecmp(var, h, l) && h[l] == ':') {
         const char *value = h + l + 1;
         value = ast_skip_blanks(value); /* ignore leading spaces in the value */
         /* found a potential candidate */
         if ((mode & GET_HEADER_SKIP_EMPTY) && ast_strlen_zero(value)) {
            continue;   /* not interesting */
         }
         if (mode & GET_HEADER_LAST_MATCH) {
            result = value;   /* record the last match so far */
         } else {
            return value;
         }
      }
   }

   return result;
}
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 1985 of file manager.c.

{
static void __init_manager_event_buf ( void  ) [static]

Definition at line 5028 of file manager.c.

{
static void __init_manager_event_funcbuf ( void  ) [static]

Definition at line 5001 of file manager.c.

{
static void __init_userevent_buf ( void  ) [static]

Definition at line 1986 of file manager.c.

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

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

{
   const char *channel = astman_get_header(m, "Channel");
   const char *pchannel = astman_get_header(m, "ChannelPrefix");
   const char *msgtype = astman_get_header(m, "MsgType");
   const char *chargetype = astman_get_header(m, "ChargeType");
   const char *currencyname = astman_get_header(m, "CurrencyName");
   const char *currencyamount = astman_get_header(m, "CurrencyAmount");
   const char *mult = astman_get_header(m, "CurrencyMultiplier");
   const char *totaltype = astman_get_header(m, "TotalType");
   const char *aocbillingid = astman_get_header(m, "AOCBillingId");
   const char *association_id= astman_get_header(m, "ChargingAssociationId");
   const char *association_num = astman_get_header(m, "ChargingAssociationNumber");
   const char *association_plan = astman_get_header(m, "ChargingAssociationPlan");

   enum ast_aoc_type _msgtype;
   enum ast_aoc_charge_type _chargetype;
   enum ast_aoc_currency_multiplier _mult = AST_AOC_MULT_ONE;
   enum ast_aoc_total_type _totaltype = AST_AOC_TOTAL;
   enum ast_aoc_billing_id _billingid = AST_AOC_BILLING_NA;
   unsigned int _currencyamount = 0;
   int _association_id = 0;
   unsigned int _association_plan = 0;
   struct ast_channel *chan = NULL;

   struct ast_aoc_decoded *decoded = NULL;
   struct ast_aoc_encoded *encoded = NULL;
   size_t encoded_size = 0;

   if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) {
      astman_send_error(s, m, "Channel and PartialChannel are not specified. Specify at least one of these.");
      goto aocmessage_cleanup;
   }

   if (!(chan = ast_channel_get_by_name(channel)) && !ast_strlen_zero(pchannel)) {
      chan = ast_channel_get_by_name_prefix(pchannel, strlen(pchannel));
   }

   if (!chan) {
      astman_send_error(s, m, "No such channel");
      goto aocmessage_cleanup;
   }

   if (ast_strlen_zero(msgtype) || (strcasecmp(msgtype, "d") && strcasecmp(msgtype, "e"))) {
      astman_send_error(s, m, "Invalid MsgType");
      goto aocmessage_cleanup;
   }

   if (ast_strlen_zero(chargetype)) {
      astman_send_error(s, m, "ChargeType not specified");
      goto aocmessage_cleanup;
   }

   _msgtype = strcasecmp(msgtype, "d") ? AST_AOC_E : AST_AOC_D;

   if (!strcasecmp(chargetype, "NA")) {
      _chargetype = AST_AOC_CHARGE_NA;
   } else if (!strcasecmp(chargetype, "Free")) {
      _chargetype = AST_AOC_CHARGE_FREE;
   } else if (!strcasecmp(chargetype, "Currency")) {
      _chargetype = AST_AOC_CHARGE_CURRENCY;
   } else if (!strcasecmp(chargetype, "Unit")) {
      _chargetype = AST_AOC_CHARGE_UNIT;
   } else {
      astman_send_error(s, m, "Invalid ChargeType");
      goto aocmessage_cleanup;
   }

   if (_chargetype == AST_AOC_CHARGE_CURRENCY) {

      if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u", &_currencyamount) != 1)) {
         astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency");
         goto aocmessage_cleanup;
      }

      if (ast_strlen_zero(mult)) {
         astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency.");
         goto aocmessage_cleanup;
      } else if (!strcasecmp(mult, "onethousandth")) {
         _mult = AST_AOC_MULT_ONETHOUSANDTH;
      } else if (!strcasecmp(mult, "onehundredth")) {
         _mult = AST_AOC_MULT_ONEHUNDREDTH;
      } else if (!strcasecmp(mult, "onetenth")) {
         _mult = AST_AOC_MULT_ONETENTH;
      } else if (!strcasecmp(mult, "one")) {
         _mult = AST_AOC_MULT_ONE;
      } else if (!strcasecmp(mult, "ten")) {
         _mult = AST_AOC_MULT_TEN;
      } else if (!strcasecmp(mult, "hundred")) {
         _mult = AST_AOC_MULT_HUNDRED;
      } else if (!strcasecmp(mult, "thousand")) {
         _mult = AST_AOC_MULT_THOUSAND;
      } else {
         astman_send_error(s, m, "Invalid ChargeMultiplier");
         goto aocmessage_cleanup;
      }
   }

   /* create decoded object and start setting values */
   if (!(decoded = ast_aoc_create(_msgtype, _chargetype, 0))) {
         astman_send_error(s, m, "Message Creation Failed");
         goto aocmessage_cleanup;
   }

   if (_msgtype == AST_AOC_D) {
      if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype, "subtotal")) {
         _totaltype = AST_AOC_SUBTOTAL;
      }

      if (ast_strlen_zero(aocbillingid)) {
         /* ignore this is optional */
      } else if (!strcasecmp(aocbillingid, "Normal")) {
         _billingid = AST_AOC_BILLING_NORMAL;
      } else if (!strcasecmp(aocbillingid, "ReverseCharge")) {
         _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
      } else if (!strcasecmp(aocbillingid, "CreditCard")) {
         _billingid = AST_AOC_BILLING_CREDIT_CARD;
      } else {
         astman_send_error(s, m, "Invalid AOC-D AOCBillingId");
         goto aocmessage_cleanup;
      }
   } else {
      if (ast_strlen_zero(aocbillingid)) {
         /* ignore this is optional */
      } else if (!strcasecmp(aocbillingid, "Normal")) {
         _billingid = AST_AOC_BILLING_NORMAL;
      } else if (!strcasecmp(aocbillingid, "ReverseCharge")) {
         _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
      } else if (!strcasecmp(aocbillingid, "CreditCard")) {
         _billingid = AST_AOC_BILLING_CREDIT_CARD;
      } else if (!strcasecmp(aocbillingid, "CallFwdUnconditional")) {
         _billingid = AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL;
      } else if (!strcasecmp(aocbillingid, "CallFwdBusy")) {
         _billingid = AST_AOC_BILLING_CALL_FWD_BUSY;
      } else if (!strcasecmp(aocbillingid, "CallFwdNoReply")) {
         _billingid = AST_AOC_BILLING_CALL_FWD_NO_REPLY;
      } else if (!strcasecmp(aocbillingid, "CallDeflection")) {
         _billingid = AST_AOC_BILLING_CALL_DEFLECTION;
      } else if (!strcasecmp(aocbillingid, "CallTransfer")) {
         _billingid = AST_AOC_BILLING_CALL_TRANSFER;
      } else {
         astman_send_error(s, m, "Invalid AOC-E AOCBillingId");
         goto aocmessage_cleanup;
      }

      if (!ast_strlen_zero(association_id) && (sscanf(association_id, "%30d", &_association_id) != 1)) {
         astman_send_error(s, m, "Invalid ChargingAssociationId");
         goto aocmessage_cleanup;
      }
      if (!ast_strlen_zero(association_plan) && (sscanf(association_plan, "%30u", &_association_plan) != 1)) {
         astman_send_error(s, m, "Invalid ChargingAssociationPlan");
         goto aocmessage_cleanup;
      }

      if (_association_id) {
         ast_aoc_set_association_id(decoded, _association_id);
      } else if (!ast_strlen_zero(association_num)) {
         ast_aoc_set_association_number(decoded, association_num, _association_plan);
      }
   }

   if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
      ast_aoc_set_currency_info(decoded, _currencyamount, _mult, ast_strlen_zero(currencyname) ? NULL : currencyname);
   } else if (_chargetype == AST_AOC_CHARGE_UNIT) {
      struct ast_aoc_unit_entry entry;
      int i;

      /* multiple unit entries are possible, lets get them all */
      for (i = 0; i < 32; i++) {
         if (aocmessage_get_unit_entry(m, &entry, i)) {
            break; /* that's the end then */
         }

         ast_aoc_add_unit_entry(decoded, entry.valid_amount, entry.amount, entry.valid_type, entry.type);
      }

      /* at least one unit entry is required */
      if (!i) {
         astman_send_error(s, m, "Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit");
         goto aocmessage_cleanup;
      }

   }

   ast_aoc_set_billing_id(decoded, _billingid);
   ast_aoc_set_total_type(decoded, _totaltype);


   if ((encoded = ast_aoc_encode(decoded, &encoded_size, NULL)) && !ast_indicate_data(chan, AST_CONTROL_AOC, encoded, encoded_size)) {
      astman_send_ack(s, m, "AOC Message successfully queued on channel");
   } else {
      astman_send_error(s, m, "Error encoding AOC message, could not queue onto channel");
   }

aocmessage_cleanup:

   ast_aoc_destroy_decoded(decoded);
   ast_aoc_destroy_encoded(encoded);

   if (chan) {
      chan = ast_channel_unref(chan);
   }
   return 0;
}
static int action_atxfer ( struct mansession s,
const struct message m 
) [static]

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

{
   const char *name = astman_get_header(m, "Channel");
   const char *exten = astman_get_header(m, "Exten");
   const char *context = astman_get_header(m, "Context");
   struct ast_channel *chan = NULL;
   struct ast_call_feature *atxfer_feature = NULL;
   char *feature_code = NULL;

   if (ast_strlen_zero(name)) {
      astman_send_error(s, m, "No channel specified");
      return 0;
   }
   if (ast_strlen_zero(exten)) {
      astman_send_error(s, m, "No extension specified");
      return 0;
   }

   if (!(atxfer_feature = ast_find_call_feature("atxfer"))) {
      astman_send_error(s, m, "No attended transfer feature found");
      return 0;
   }

   if (!(chan = ast_channel_get_by_name(name))) {
      astman_send_error(s, m, "Channel specified does not exist");
      return 0;
   }

   if (!ast_strlen_zero(context)) {
      pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context);
   }

   for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) {
      struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code };
      ast_queue_frame(chan, &f);
   }

   for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) {
      struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code };
      ast_queue_frame(chan, &f);
   }

   chan = ast_channel_unref(chan);

   astman_send_ack(s, m, "Atxfer successfully queued");

   return 0;
}
static int action_challenge ( struct mansession s,
const struct message m 
) [static]

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

{
   const char *authtype = astman_get_header(m, "AuthType");

   if (!strcasecmp(authtype, "MD5")) {
      if (ast_strlen_zero(s->session->challenge)) {
         snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
      }
      mansession_lock(s);
      astman_start_ack(s, m);
      astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
      mansession_unlock(s);
   } else {
      astman_send_error(s, m, "Must specify AuthType");
   }
   return 0;
}
static int action_command ( struct mansession s,
const struct message m 
) [static]

Manager command "command" - execute CLI command.

Definition at line 3591 of file manager.c.

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

{
   const char *cmd = astman_get_header(m, "Command");
   const char *id = astman_get_header(m, "ActionID");
   char *buf, *final_buf;
   char template[] = "/tmp/ast-ami-XXXXXX";  /* template for temporary file */
   int fd;
   off_t l;

   if (ast_strlen_zero(cmd)) {
      astman_send_error(s, m, "No command provided");
      return 0;
   }

   if (check_blacklist(cmd)) {
      astman_send_error(s, m, "Command blacklisted");
      return 0;
   }

   fd = mkstemp(template);

   astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
   if (!ast_strlen_zero(id)) {
      astman_append(s, "ActionID: %s\r\n", id);
   }
   /* FIXME: Wedge a ActionID response in here, waiting for later changes */
   ast_cli_command(fd, cmd);  /* XXX need to change this to use a FILE * */
   l = lseek(fd, 0, SEEK_END);   /* how many chars available */

   /* This has a potential to overflow the stack.  Hence, use the heap. */
   buf = ast_calloc(1, l + 1);
   final_buf = ast_calloc(1, l + 1);
   if (buf) {
      lseek(fd, 0, SEEK_SET);
      if (read(fd, buf, l) < 0) {
         ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
      }
      buf[l] = '\0';
      if (final_buf) {
         term_strip(final_buf, buf, l);
         final_buf[l] = '\0';
      }
      astman_append(s, "%s", S_OR(final_buf, buf));
      ast_free(buf);
   }
   close(fd);
   unlink(template);
   astman_append(s, "--END COMMAND--\r\n\r\n");
   if (final_buf) {
      ast_free(final_buf);
   }
   return 0;
}
static int action_coresettings ( struct mansession s,
const struct message m 
) [static]

Show PBX core settings information.

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

{
   const char *actionid = astman_get_header(m, "ActionID");
   char idText[150];

   if (!ast_strlen_zero(actionid)) {
      snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
   } else {
      idText[0] = '\0';
   }

   astman_append(s, "Response: Success\r\n"
         "%s"
         "AMIversion: %s\r\n"
         "AsteriskVersion: %s\r\n"
         "SystemName: %s\r\n"
         "CoreMaxCalls: %d\r\n"
         "CoreMaxLoadAvg: %f\r\n"
         "CoreRunUser: %s\r\n"
         "CoreRunGroup: %s\r\n"
         "CoreMaxFilehandles: %d\r\n"
         "CoreRealTimeEnabled: %s\r\n"
         "CoreCDRenabled: %s\r\n"
         "CoreHTTPenabled: %s\r\n"
         "\r\n",
         idText,
         AMI_VERSION,
         ast_get_version(),
         ast_config_AST_SYSTEM_NAME,
         option_maxcalls,
         option_maxload,
         ast_config_AST_RUN_USER,
         ast_config_AST_RUN_GROUP,
         option_maxfiles,
         AST_CLI_YESNO(ast_realtime_enabled()),
         AST_CLI_YESNO(check_cdr_enabled()),
         AST_CLI_YESNO(check_webmanager_enabled())
         );
   return 0;
}
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 4383 of file manager.c.

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

Referenced by __init_manager().

{
   const char *actionid = astman_get_header(m, "ActionID");
   char idText[256];
   struct ast_channel *c = NULL;
   int numchans = 0;
   int duration, durh, durm, durs;
   struct ast_channel_iterator *iter;

   if (!ast_strlen_zero(actionid)) {
      snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
   } else {
      idText[0] = '\0';
   }

   if (!(iter = ast_channel_iterator_all_new())) {
      astman_send_error(s, m, "Memory Allocation Failure");
      return 1;
   }

   astman_send_listack(s, m, "Channels will follow", "start");

   for (; (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) {
      struct ast_channel *bc;
      char durbuf[10] = "";

      ast_channel_lock(c);

      bc = ast_bridged_channel(c);
      if (c->cdr && !ast_tvzero(c->cdr->start)) {
         duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
         durh = duration / 3600;
         durm = (duration % 3600) / 60;
         durs = duration % 60;
         snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
      }

      astman_append(s,
         "Event: CoreShowChannel\r\n"
         "%s"
         "Channel: %s\r\n"
         "UniqueID: %s\r\n"
         "Context: %s\r\n"
         "Extension: %s\r\n"
         "Priority: %d\r\n"
         "ChannelState: %d\r\n"
         "ChannelStateDesc: %s\r\n"
         "Application: %s\r\n"
         "ApplicationData: %s\r\n"
         "CallerIDnum: %s\r\n"
         "CallerIDname: %s\r\n"
         "ConnectedLineNum: %s\r\n"
         "ConnectedLineName: %s\r\n"
         "Duration: %s\r\n"
         "AccountCode: %s\r\n"
         "BridgedChannel: %s\r\n"
         "BridgedUniqueID: %s\r\n"
         "\r\n", idText, c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state,
         ast_state2str(c->_state), c->appl ? c->appl : "", c->data ? S_OR(c->data, "") : "",
         S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""),
         S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""),
         S_COR(c->connected.id.number.valid, c->connected.id.number.str, ""),
         S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""),
         durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : "");

      ast_channel_unlock(c);

      numchans++;
   }

   astman_append(s,
      "Event: CoreShowChannelsComplete\r\n"
      "EventList: Complete\r\n"
      "ListItems: %d\r\n"
      "%s"
      "\r\n", numchans, idText);

   ast_channel_iterator_destroy(iter);

   return 0;
}
static int action_corestatus ( struct mansession s,
const struct message m 
) [static]

Show PBX core status information.

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

{
   const char *actionid = astman_get_header(m, "ActionID");
   char idText[150];
   char startuptime[150], startupdate[150];
   char reloadtime[150], reloaddate[150];
   struct ast_tm tm;

   if (!ast_strlen_zero(actionid)) {
      snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
   } else {
      idText[0] = '\0';
   }

   ast_localtime(&ast_startuptime, &tm, NULL);
   ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm);
   ast_strftime(startupdate, sizeof(startupdate), "%Y-%m-%d", &tm);
   ast_localtime(&ast_lastreloadtime, &tm, NULL);
   ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm);
   ast_strftime(reloaddate, sizeof(reloaddate), "%Y-%m-%d", &tm);

   astman_append(s, "Response: Success\r\n"
         "%s"
         "CoreStartupDate: %s\r\n"
         "CoreStartupTime: %s\r\n"
         "CoreReloadDate: %s\r\n"
         "CoreReloadTime: %s\r\n"
         "CoreCurrentCalls: %d\r\n"
         "\r\n",
         idText,
         startupdate,
         startuptime,
         reloaddate,
         reloadtime,
         ast_active_channels()
         );
   return 0;
}
static int action_createconfig ( struct mansession s,
const struct message m 
) [static]

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

{
   int fd;
   const char *fn = astman_get_header(m, "Filename");
   struct ast_str *filepath = ast_str_alloca(PATH_MAX);
   ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR);
   ast_str_append(&filepath, 0, "%s", fn);

   if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
      close(fd);
      astman_send_ack(s, m, "New configuration file created successfully");
   } else {
      astman_send_error(s, m, strerror(errno));
   }

   return 0;
}
static void action_destroy ( void *  obj) [static]

Definition at line 5201 of file manager.c.

References ast_string_field_free_memory, and manager_action::synopsis.

Referenced by ast_manager_register2().

{
   struct manager_action *doomed = obj;

   if (doomed->synopsis) {
      /* The string fields were initialized. */
      ast_string_field_free_memory(doomed);
   }
}
static int action_events ( struct mansession s,
const struct message m 
) [static]

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

{
   const char *mask = astman_get_header(m, "EventMask");
   int res, x;
   const char *id = astman_get_header(m, "ActionID");
   char id_text[256];

   if (!ast_strlen_zero(id)) {
      snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
   } else {
      id_text[0] = '\0';
   }

   res = set_eventmask(s, mask);
   if (broken_events_action) {
      /* if this option is set we should not return a response on
       * error, or when all events are set */

      if (res > 0) {
         for (x = 0; x < ARRAY_LEN(perms); x++) {
            if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) {
               return 0;
            }
         }
         astman_append(s, "Response: Success\r\n%s"
                "Events: On\r\n\r\n", id_text);
      } else if (res == 0)
         astman_append(s, "Response: Success\r\n%s"
                "Events: Off\r\n\r\n", id_text);
      return 0;
   }

   if (res > 0)
      astman_append(s, "Response: Success\r\n%s"
             "Events: On\r\n\r\n", id_text);
   else if (res == 0)
      astman_append(s, "Response: Success\r\n%s"
             "Events: Off\r\n\r\n", id_text);
   else
      astman_send_error(s, m, "Invalid event mask");

   return 0;
}
static int action_extensionstate ( struct mansession s,
const struct message m 
) [static]

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

{
   const char *exten = astman_get_header(m, "Exten");
   const char *context = astman_get_header(m, "Context");
   char hint[256] = "";
   int status;
   if (ast_strlen_zero(exten)) {
      astman_send_error(s, m, "Extension not specified");
      return 0;
   }
   if (ast_strlen_zero(context)) {
      context = "default";
   }
   status = ast_extension_state(NULL, context, exten);
   ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten);
   astman_start_ack(s, m);
   astman_append(s,   "Message: Extension Status\r\n"
            "Exten: %s\r\n"
            "Context: %s\r\n"
            "Hint: %s\r\n"
            "Status: %d\r\n\r\n",
            exten, context, hint, status);
   return 0;
}
static struct manager_action* action_find ( const char *  name) [static, read]

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

{
   struct manager_action *act;

   AST_RWLIST_RDLOCK(&actions);
   AST_RWLIST_TRAVERSE(&actions, act, list) {
      if (!strcasecmp(name, act->action)) {
         ao2_t_ref(act, +1, "found action object");
         break;
      }
   }
   AST_RWLIST_UNLOCK(&actions);

   return act;
}
static int action_getconfig ( struct mansession s,
const struct message m 
) [static]

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

{
   struct ast_config *cfg;
   const char *fn = astman_get_header(m, "Filename");
   const char *category = astman_get_header(m, "Category");
   int catcount = 0;
   int lineno = 0;
   char *cur_category = NULL;
   struct ast_variable *v;
   struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };

   if (ast_strlen_zero(fn)) {
      astman_send_error(s, m, "Filename not specified");
      return 0;
   }
   cfg = ast_config_load2(fn, "manager", config_flags);
   if (cfg == CONFIG_STATUS_FILEMISSING) {
      astman_send_error(s, m, "Config file not found");
      return 0;
   } else if (cfg == CONFIG_STATUS_FILEINVALID) {
      astman_send_error(s, m, "Config file has invalid format");
      return 0;
   }

   astman_start_ack(s, m);
   while ((cur_category = ast_category_browse(cfg, cur_category))) {
      if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) {
         lineno = 0;
         astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category);
         for (v = ast_variable_browse(cfg, cur_category); v; v = v->next) {
            astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value);
         }
         catcount++;
      }
   }
   if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
      astman_append(s, "No categories found\r\n");
   }
   ast_config_destroy(cfg);
   astman_append(s, "\r\n");

   return 0;
}
static int action_getconfigjson ( struct mansession s,
const struct message m 
) [static]

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

{
   struct ast_config *cfg;
   const char *fn = astman_get_header(m, "Filename");
   char *category = NULL;
   struct ast_variable *v;
   int comma1 = 0;
   struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };

   if (ast_strlen_zero(fn)) {
      astman_send_error(s, m, "Filename not specified");
      return 0;
   }

   if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
      astman_send_error(s, m, "Config file not found");
      return 0;
   } else if (cfg == CONFIG_STATUS_FILEINVALID) {
      astman_send_error(s, m, "Config file has invalid format");
      return 0;
   }

   astman_start_ack(s, m);
   astman_append(s, "JSON: {");
   while ((category = ast_category_browse(cfg, category))) {
      int comma2 = 0;

      astman_append(s, "%s\"", comma1 ? "," : "");
      astman_append_json(s, category);
      astman_append(s, "\":[");
      comma1 = 1;
      for (v = ast_variable_browse(cfg, category); v; v = v->next) {
         astman_append(s, "%s\"", comma2 ? "," : "");
         astman_append_json(s, v->name);
         astman_append(s, "\":\"");
         astman_append_json(s, v->value);
         astman_append(s, "\"");
         comma2 = 1;
      }
      astman_append(s, "]");
   }
   astman_append(s, "}\r\n\r\n");

   ast_config_destroy(cfg);

   return 0;
}
static int action_getvar ( struct mansession s,
const struct message m 
) [static]

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

{
   struct ast_channel *c = NULL;
   const char *name = astman_get_header(m, "Channel");
   const char *varname = astman_get_header(m, "Variable");
   char *varval;
   char workspace[1024];

   if (ast_strlen_zero(varname)) {
      astman_send_error(s, m, "No variable specified");
      return 0;
   }

   if (!ast_strlen_zero(name)) {
      if (!(c = ast_channel_get_by_name(name))) {
         astman_send_error(s, m, "No such channel");
         return 0;
      }
   }

   workspace[0] = '\0';
   if (varname[strlen(varname) - 1] == ')') {
      if (!c) {
         c = ast_dummy_channel_alloc();
         if (c) {
            ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
         } else
            ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
      } else {
         ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
      }
      varval = workspace;
   } else {
      pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
   }

   if (c) {
      c = ast_channel_unref(c);
   }

   astman_start_ack(s, m);
   astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, S_OR(varval, ""));

   return 0;
}
static int action_hangup ( struct mansession s,
const struct message m 
) [static]

Definition at line 3087 of file manager.c.

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

Referenced by __init_manager().

{
   struct ast_channel *c = NULL;
   int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */
   const char *name = astman_get_header(m, "Channel");
   const char *cause = astman_get_header(m, "Cause");

   if (ast_strlen_zero(name)) {
      astman_send_error(s, m, "No channel specified");
      return 0;
   }

   if (!ast_strlen_zero(cause)) {
      char *endptr;
      causecode = strtol(cause, &endptr, 10);
      if (causecode < 0 || causecode > 127 || *endptr != '\0') {
         ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause);
         /* keep going, better to hangup without cause than to not hang up at all */
         causecode = 0; /* do not set channel's hangupcause */
      }
   }

   if (!(c = ast_channel_get_by_name(name))) {
      astman_send_error(s, m, "No such channel");
      return 0;
   }

   ast_channel_lock(c);
   if (causecode > 0) {
      ast_debug(1, "Setting hangupcause of channel %s to %d (is %d now)\n",
            c->name, causecode, c->hangupcause);
      c->hangupcause = causecode;
   }
   ast_softhangup_nolock(c, AST_SOFTHANGUP_EXPLICIT);
   ast_channel_unlock(c);

   c = ast_channel_unref(c);

   astman_send_ack(s, m, "Channel Hungup");

   return 0;
}
static int action_listcategories ( struct mansession s,
const struct message m 
) [static]

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

{
   struct ast_config *cfg;
   const char *fn = astman_get_header(m, "Filename");
   char *category = NULL;
   struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
   int catcount = 0;

   if (ast_strlen_zero(fn)) {
      astman_send_error(s, m, "Filename not specified");
      return 0;
   }
   if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
      astman_send_error(s, m, "Config file not found");
      return 0;
   } else if (cfg == CONFIG_STATUS_FILEINVALID) {
      astman_send_error(s, m, "Config file has invalid format");
      return 0;
   }
   astman_start_ack(s, m);
   while ((category = ast_category_browse(cfg, category))) {
      astman_append(s, "Category-%06d: %s\r\n", catcount, category);
      catcount++;
   }
   if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
      astman_append(s, "Error: no categories found\r\n");
   }
   ast_config_destroy(cfg);
   astman_append(s, "\r\n");

   return 0;
}
static int action_listcommands ( struct mansession s,
const struct message m 
) [static]
static int action_login ( struct mansession s,
const struct message m 
) [static]

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

{

   /* still authenticated - don't process again */
   if (s->session->authenticated) {
      astman_send_ack(s, m, "Already authenticated");
      return 0;
   }

   if (authenticate(s, m)) {
      sleep(1);
      astman_send_error(s, m, "Authentication failed");
      return -1;
   }
   s->session->authenticated = 1;
   ast_atomic_fetchadd_int(&unauth_sessions, -1);
   if (manager_displayconnects(s->session)) {
      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));
   }
   astman_send_ack(s, m, "Authentication accepted");
   if ((s->session->send_events & EVENT_FLAG_SYSTEM)
      && ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
      struct ast_str *auth = ast_str_alloca(80);
      const char *cat_str = authority_to_str(EVENT_FLAG_SYSTEM, &auth);
      astman_append(s, "Event: FullyBooted\r\n"
         "Privilege: %s\r\n"
         "Status: Fully Booted\r\n\r\n", cat_str);
   }
   return 0;
}
static int action_logoff ( struct mansession s,
const struct message m 
) [static]

Definition at line 3032 of file manager.c.

References astman_send_response().

Referenced by __init_manager().

{
   astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
   return -1;
}
static int action_mailboxcount ( struct mansession s,
const struct message m 
) [static]

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

{
   const char *mailbox = astman_get_header(m, "Mailbox");
   int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;;

   if (ast_strlen_zero(mailbox)) {
      astman_send_error(s, m, "Mailbox not specified");
      return 0;
   }
   ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs);
   astman_start_ack(s, m);
   astman_append(s,   "Message: Mailbox Message Count\r\n"
            "Mailbox: %s\r\n"
            "UrgMessages: %d\r\n"
            "NewMessages: %d\r\n"
            "OldMessages: %d\r\n"
            "\r\n",
            mailbox, urgentmsgs, newmsgs, oldmsgs);
   return 0;
}
static int action_mailboxstatus ( struct mansession s,
const struct message m 
) [static]

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

{
   const char *mailbox = astman_get_header(m, "Mailbox");
   int ret;

   if (ast_strlen_zero(mailbox)) {
      astman_send_error(s, m, "Mailbox not specified");
      return 0;
   }
   ret = ast_app_has_voicemail(mailbox, NULL);
   astman_start_ack(s, m);
   astman_append(s, "Message: Mailbox Status\r\n"
          "Mailbox: %s\r\n"
          "Waiting: %d\r\n\r\n", mailbox, ret);
   return 0;
}
static int action_originate ( struct mansession s,
const struct message m 
) [static]

Definition at line 3947 of file manager.c.

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

Referenced by __init_manager().

{
   const char *name = astman_get_header(m, "Channel");
   const char *exten = astman_get_header(m, "Exten");
   const char *context = astman_get_header(m, "Context");
   const char *priority = astman_get_header(m, "Priority");
   const char *timeout = astman_get_header(m, "Timeout");
   const char *callerid = astman_get_header(m, "CallerID");
   const char *account = astman_get_header(m, "Account");
   const char *app = astman_get_header(m, "Application");
   const char *appdata = astman_get_header(m, "Data");
   const char *async = astman_get_header(m, "Async");
   const char *id = astman_get_header(m, "ActionID");
   const char *codecs = astman_get_header(m, "Codecs");
   struct ast_variable *vars;
   char *tech, *data;
   char *l = NULL, *n = NULL;
   int pi = 0;
   int res;
   int to = 30000;
   int reason = 0;
   char tmp[256];
   char tmp2[256];
   format_t format = AST_FORMAT_SLINEAR;

   pthread_t th;
   if (ast_strlen_zero(name)) {
      astman_send_error(s, m, "Channel not specified");
      return 0;
   }
   if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) {
      if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
         astman_send_error(s, m, "Invalid priority");
         return 0;
      }
   }
   if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) {
      astman_send_error(s, m, "Invalid timeout");
      return 0;
   }
   ast_copy_string(tmp, name, sizeof(tmp));
   tech = tmp;
   data = strchr(tmp, '/');
   if (!data) {
      astman_send_error(s, m, "Invalid channel");
      return 0;
   }
   *data++ = '\0';
   ast_copy_string(tmp2, callerid, sizeof(tmp2));
   ast_callerid_parse(tmp2, &n, &l);
   if (n) {
      if (ast_strlen_zero(n)) {
         n = NULL;
      }
   }
   if (l) {
      ast_shrink_phone_number(l);
      if (ast_strlen_zero(l)) {
         l = NULL;
      }
   }
   if (!ast_strlen_zero(codecs)) {
      format = 0;
      ast_parse_allow_disallow(NULL, &format, codecs, 1);
   }
   if (!ast_strlen_zero(app)) {
      /* To run the System application (or anything else that goes to
       * shell), you must have the additional System privilege */
      if (!(s->session->writeperm & EVENT_FLAG_SYSTEM)
         && (
            strcasestr(app, "system") ||      /* System(rm -rf /)
                                                 TrySystem(rm -rf /)       */
            strcasestr(app, "exec") ||        /* Exec(System(rm -rf /))
                                                 TryExec(System(rm -rf /)) */
            strcasestr(app, "agi") ||         /* AGI(/bin/rm,-rf /)
                                                 EAGI(/bin/rm,-rf /)       */
            strstr(appdata, "SHELL") ||       /* NoOp(${SHELL(rm -rf /)})  */
            strstr(appdata, "EVAL")           /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
            )) {
         astman_send_error(s, m, "Originate with certain 'Application' arguments requires the additional System privilege, which you do not have.");
         return 0;
      }
   }
   /* Allocate requested channel variables */
   vars = astman_get_variables(m);

   if (ast_true(async)) {
      struct fast_originate_helper *fast = ast_calloc(1, sizeof(*fast));
      if (!fast || ast_string_field_init(fast, 252)) {
         if (fast) {
            ast_free(fast);
         }
         res = -1;
      } else {
         if (!ast_strlen_zero(id)) {
            ast_string_field_build(fast, idtext, "ActionID: %s", id);
         }
         ast_copy_string(fast->tech, tech, sizeof(fast->tech));
         ast_copy_string(fast->data, data, sizeof(fast->data));
         ast_string_field_set(fast, app, app);
         ast_string_field_set(fast, appdata, appdata);
         ast_string_field_set(fast, cid_num, l);
         ast_string_field_set(fast, cid_name, n);
         ast_string_field_set(fast, context, context);
         ast_string_field_set(fast, exten, exten);
         ast_string_field_set(fast, account, account);
         fast->vars = vars;
         fast->format = format;
         fast->timeout = to;
         fast->priority = pi;
         if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) {
            ast_string_field_free_memory(fast);
            ast_free(fast);
            res = -1;
         } else {
            res = 0;
         }
      }
   } else if (!ast_strlen_zero(app)) {
      res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
   } else {
      if (exten && context && pi) {
         res = ast_pbx_outgoing_exten(tech, format, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
      } else {
         astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
         if (vars) {
            ast_variables_destroy(vars);
         }
         return 0;
      }
   }
   if (!res) {
      astman_send_ack(s, m, "Originate successfully queued");
   } else {
      astman_send_error(s, m, "Originate failed");
   }
   return 0;
}
static int action_ping ( struct mansession s,
const struct message m 
) [static]

Definition at line 2445 of file manager.c.

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

Referenced by __init_manager().

{
   const char *actionid = astman_get_header(m, "ActionID");
   struct timeval now = ast_tvnow();

   astman_append(s, "Response: Success\r\n");
   if (!ast_strlen_zero(actionid)){
      astman_append(s, "ActionID: %s\r\n", actionid);
   }
   astman_append(
      s,
      "Ping: Pong\r\n"
      "Timestamp: %ld.%06lu\r\n"
      "\r\n",
      (long) now.tv_sec, (unsigned long) now.tv_usec);
   return 0;
}
static int action_redirect ( struct mansession s,
const struct message m 
) [static]

action_redirect: The redirect manager command

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

{
   const char *name = astman_get_header(m, "Channel");
   const char *name2 = astman_get_header(m, "ExtraChannel");
   const char *exten = astman_get_header(m, "Exten");
   const char *exten2 = astman_get_header(m, "ExtraExten");
   const char *context = astman_get_header(m, "Context");
   const char *context2 = astman_get_header(m, "ExtraContext");
   const char *priority = astman_get_header(m, "Priority");
   const char *priority2 = astman_get_header(m, "ExtraPriority");
   struct ast_channel *chan, *chan2 = NULL;
   int pi, pi2 = 0;
   int res;

   if (ast_strlen_zero(name)) {
      astman_send_error(s, m, "Channel not specified");
      return 0;
   }

   if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) {
      if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
         astman_send_error(s, m, "Invalid priority");
         return 0;
      }
   }

   if (!ast_strlen_zero(priority2) && (sscanf(priority2, "%30d", &pi2) != 1)) {
      if ((pi2 = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL)) < 1) {
         astman_send_error(s, m, "Invalid ExtraPriority");
         return 0;
      }
   }

   if (!(chan = ast_channel_get_by_name(name))) {
      char buf[256];
      snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
      astman_send_error(s, m, buf);
      return 0;
   }

   if (ast_check_hangup_locked(chan)) {
      astman_send_error(s, m, "Redirect failed, channel not up.");
      chan = ast_channel_unref(chan);
      return 0;
   }

   if (!ast_strlen_zero(name2)) {
      chan2 = ast_channel_get_by_name(name2);
   }

   if (chan2 && ast_check_hangup_locked(chan2)) {
      astman_send_error(s, m, "Redirect failed, extra channel not up.");
      chan = ast_channel_unref(chan);
      chan2 = ast_channel_unref(chan2);
      return 0;
   }

   if (chan->pbx) {
      ast_channel_lock(chan);
      ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
      ast_channel_unlock(chan);
   }

   res = ast_async_goto(chan, context, exten, pi);
   if (!res) {
      if (!ast_strlen_zero(name2)) {
         if (chan2) {
            if (chan2->pbx) {
               ast_channel_lock(chan2);
               ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
               ast_channel_unlock(chan2);
            }
            if (context2) {
               res = ast_async_goto(chan2, context2, exten2, pi2);
            } else {
               res = ast_async_goto(chan2, context, exten, pi);
            }
         } else {
            res = -1;
         }
         if (!res) {
            astman_send_ack(s, m, "Dual Redirect successful");
         } else {
            astman_send_error(s, m, "Secondary redirect failed");
         }
      } else {
         astman_send_ack(s, m, "Redirect successful");
      }
   } else {
      astman_send_error(s, m, "Redirect failed");
   }

   if (chan) {
      chan = ast_channel_unref(chan);
   }

   if (chan2) {
      chan2 = ast_channel_unref(chan2);
   }

   return 0;
}
static int action_reload ( struct mansession s,
const struct message m 
) [static]

Send a reload event.

Definition at line 4368 of file manager.c.

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

Referenced by __init_manager().

{
   const char *module = astman_get_header(m, "Module");
   int res = ast_module_reload(S_OR(module, NULL));

   if (res == 2) {
      astman_send_ack(s, m, "Module Reloaded");
   } else {
      astman_send_error(s, m, s == 0 ? "No such module" : "Module does not support reload");
   }
   return 0;
}
static int action_sendtext ( struct mansession s,
const struct message m 
) [static]

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

{
   struct ast_channel *c = NULL;
   const char *name = astman_get_header(m, "Channel");
   const char *textmsg = astman_get_header(m, "Message");
   int res = 0;

   if (ast_strlen_zero(name)) {
      astman_send_error(s, m, "No channel specified");
      return 0;
   }

   if (ast_strlen_zero(textmsg)) {
      astman_send_error(s, m, "No Message specified");
      return 0;
   }

   if (!(c = ast_channel_get_by_name(name))) {
      astman_send_error(s, m, "No such channel");
      return 0;
   }

   res = ast_sendtext(c, textmsg);
   c = ast_channel_unref(c);

   if (res >= 0) {
      astman_send_ack(s, m, "Success");
   } else {
      astman_send_error(s, m, "Failure");
   }

   return res;
}
static int action_setvar ( struct mansession s,
const struct message m 
) [static]

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

{
   struct ast_channel *c = NULL;
   const char *name = astman_get_header(m, "Channel");
   const char *varname = astman_get_header(m, "Variable");
   const char *varval = astman_get_header(m, "Value");
   int res = 0;
   
   if (ast_strlen_zero(varname)) {
      astman_send_error(s, m, "No variable specified");
      return 0;
   }

   if (!ast_strlen_zero(name)) {
      if (!(c = ast_channel_get_by_name(name))) {
         astman_send_error(s, m, "No such channel");
         return 0;
      }
   }

   res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));

   if (c) {
      c = ast_channel_unref(c);
   }
   if (res == 0) {
      astman_send_ack(s, m, "Variable Set"); 
   } else {
      astman_send_error(s, m, "Variable not set");
   }
   return 0;
}
static int action_status ( struct mansession s,
const struct message m 
) [static]

Manager "status" command to show channels.

Definition at line 3211 of file manager.c.

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

Referenced by __init_manager().

{
   const char *name = astman_get_header(m, "Channel");
   const char *cvariables = astman_get_header(m, "Variables");
   char *variables = ast_strdupa(S_OR(cvariables, ""));
   struct ast_channel *c;
   char bridge[256];
   struct timeval now = ast_tvnow();
   long elapsed_seconds = 0;
   int channels = 0;
   int all = ast_strlen_zero(name); /* set if we want all channels */
   const char *id = astman_get_header(m, "ActionID");
   char idText[256];
   AST_DECLARE_APP_ARGS(vars,
      AST_APP_ARG(name)[100];
   );
   struct ast_str *str = ast_str_create(1000);
   struct ast_channel_iterator *iter = NULL;

   if (!ast_strlen_zero(id)) {
      snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
   } else {
      idText[0] = '\0';
   }

   if (all) {
      if (!(iter = ast_channel_iterator_all_new())) {
         ast_free(str);
         astman_send_error(s, m, "Memory Allocation Failure");
         return 1;
      }
      c = ast_channel_iterator_next(iter);
   } else {
      if (!(c = ast_channel_get_by_name(name))) {
         astman_send_error(s, m, "No such channel");
         ast_free(str);
         return 0;
      }
   }

   astman_send_ack(s, m, "Channel status will follow");

   if (!ast_strlen_zero(cvariables)) {
      AST_STANDARD_APP_ARGS(vars, variables);
   }

   /* if we look by name, we break after the first iteration */
   for (; c; c = ast_channel_iterator_next(iter)) {
      ast_channel_lock(c);

      if (!ast_strlen_zero(cvariables)) {
         int i;
         ast_str_reset(str);
         for (i = 0; i < vars.argc; i++) {
            char valbuf[512], *ret = NULL;

            if (vars.name[i][strlen(vars.name[i]) - 1] == ')') {
               if (ast_func_read(c, vars.name[i], valbuf, sizeof(valbuf)) < 0) {
                  valbuf[0] = '\0';
               }
               ret = valbuf;
            } else {
               pbx_retrieve_variable(c, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL);
            }

            ast_str_append(&str, 0, "Variable: %s=%s\r\n", vars.name[i], ret);
         }
      }

      channels++;
      if (c->_bridge) {
         snprintf(bridge, sizeof(bridge), "BridgedChannel: %s\r\nBridgedUniqueid: %s\r\n", c->_bridge->name, c->_bridge->uniqueid);
      } else {
         bridge[0] = '\0';
      }
      if (c->pbx) {
         if (c->cdr) {
            elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
         }
         astman_append(s,
         "Event: Status\r\n"
         "Privilege: Call\r\n"
         "Channel: %s\r\n"
         "CallerIDNum: %s\r\n"
         "CallerIDName: %s\r\n"
         "ConnectedLineNum: %s\r\n"
         "ConnectedLineName: %s\r\n"
         "Accountcode: %s\r\n"
         "ChannelState: %d\r\n"
         "ChannelStateDesc: %s\r\n"
         "Context: %s\r\n"
         "Extension: %s\r\n"
         "Priority: %d\r\n"
         "Seconds: %ld\r\n"
         "%s"
         "Uniqueid: %s\r\n"
         "%s"
         "%s"
         "\r\n",
         c->name,
         S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"),
         S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"),
         S_COR(c->connected.id.number.valid, c->connected.id.number.str, "<unknown>"),
         S_COR(c->connected.id.name.valid, c->connected.id.name.str, "<unknown>"),
         c->accountcode,
         c->_state,
         ast_state2str(c->_state), c->context,
         c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, ast_str_buffer(str), idText);
      } else {
         astman_append(s,
            "Event: Status\r\n"
            "Privilege: Call\r\n"
            "Channel: %s\r\n"
            "CallerIDNum: %s\r\n"
            "CallerIDName: %s\r\n"
            "ConnectedLineNum: %s\r\n"
            "ConnectedLineName: %s\r\n"
            "Account: %s\r\n"
            "State: %s\r\n"
            "%s"
            "Uniqueid: %s\r\n"
            "%s"
            "%s"
            "\r\n",
            c->name,
            S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"),
            S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"),
            S_COR(c->connected.id.number.valid, c->connected.id.number.str, "<unknown>"),
            S_COR(c->connected.id.name.valid, c->connected.id.name.str, "<unknown>"),
            c->accountcode,
            ast_state2str(c->_state), bridge, c->uniqueid,
            ast_str_buffer(str), idText);
      }

      ast_channel_unlock(c);
      c = ast_channel_unref(c);

      if (!all) {
         break;
      }
   }

   if (iter) {
      ast_channel_iterator_destroy(iter);
   }

   astman_append(s,
      "Event: StatusComplete\r\n"
      "%s"
      "Items: %d\r\n"
      "\r\n", idText, channels);

   ast_free(str);

   return 0;
}
static int action_timeout ( struct mansession s,
const struct message m 
) [static]

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

{
   struct ast_channel *c;
   const char *name = astman_get_header(m, "Channel");
   double timeout = atof(astman_get_header(m, "Timeout"));
   struct timeval when = { timeout, 0 };

   if (ast_strlen_zero(name)) {
      astman_send_error(s, m, "No channel specified");
      return 0;
   }

   if (!timeout || timeout < 0) {
      astman_send_error(s, m, "No timeout specified");
      return 0;
   }

   if (!(c = ast_channel_get_by_name(name))) {
      astman_send_error(s, m, "No such channel");
      return 0;
   }

   when.tv_usec = (timeout - when.tv_sec) * 1000000.0;

   ast_channel_lock(c);
   ast_channel_setwhentohangup_tv(c, when);
   ast_channel_unlock(c);
   c = ast_channel_unref(c);

   astman_send_ack(s, m, "Timeout Set");

   return 0;
}
static int action_updateconfig ( struct mansession s,
const struct message m 
) [static]

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

{
   struct ast_config *cfg;
   const char *sfn = astman_get_header(m, "SrcFilename");
   const char *dfn = astman_get_header(m, "DstFilename");
   int res;
   const char *rld = astman_get_header(m, "Reload");
   struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
   enum error_type result;

   if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) {
      astman_send_error(s, m, "Filename not specified");
      return 0;
   }
   if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) {
      astman_send_error(s, m, "Config file not found");
      return 0;
   } else if (cfg == CONFIG_STATUS_FILEINVALID) {
      astman_send_error(s, m, "Config file has invalid format");
      return 0;
   }
   result = handle_updates(s, m, cfg, dfn);
   if (!result) {
      ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */
      res = ast_config_text_file_save(dfn, cfg, "Manager");
      ast_config_destroy(cfg);
      if (res) {
         astman_send_error(s, m, "Save of config failed");
         return 0;
      }
      astman_send_ack(s, m, NULL);
      if (!ast_strlen_zero(rld)) {
         if (ast_true(rld)) {
            rld = NULL;
         }
         ast_module_reload(rld);
      }
   } else {
      ast_config_destroy(cfg);
      switch(result) {
      case UNKNOWN_ACTION:
         astman_send_error(s, m, "Unknown action command");
         break;
      case UNKNOWN_CATEGORY:
         astman_send_error(s, m, "Given category does not exist");
         break;
      case UNSPECIFIED_CATEGORY:
         astman_send_error(s, m, "Category not specified");
         break;
      case UNSPECIFIED_ARGUMENT:
         astman_send_error(s, m, "Problem with category, value, or line (if required)");
         break;
      case FAILURE_ALLOCATION:
         astman_send_error(s, m, "Memory allocation failure, this should not happen");
         break;
      case FAILURE_NEWCAT:
         astman_send_error(s, m, "Create category did not complete successfully");
         break;
      case FAILURE_DELCAT:
         astman_send_error(s, m, "Delete category did not complete successfully");
         break;
      case FAILURE_EMPTYCAT:
         astman_send_error(s, m, "Empty category did not complete successfully");
         break;
      case FAILURE_UPDATE:
         astman_send_error(s, m, "Update did not complete successfully");
         break;
      case FAILURE_DELETE:
         astman_send_error(s, m, "Delete did not complete successfully");
         break;
      case FAILURE_APPEND:
         astman_send_error(s, m, "Append did not complete successfully");
         break;
      }
   }
   return 0;
}
static int action_userevent ( struct mansession s,
const struct message m 
) [static]

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

{
   const char *event = astman_get_header(m, "UserEvent");
   struct ast_str *body = ast_str_thread_get(&userevent_buf, 16);
   int x;

   ast_str_reset(body);

   for (x = 0; x < m->hdrcount; x++) {
      if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) {
         ast_str_append(&body, 0, "%s\r\n", m->headers[x]);
      }
   }

   astman_send_ack(s, m, "Event Sent");   
   manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, ast_str_buffer(body));
   return 0;
}
static int action_waitevent ( struct mansession s,
const struct message m 
) [static]

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

{
   const char *timeouts = astman_get_header(m, "Timeout");
   int timeout = -1;
   int x;
   int needexit = 0;
   const char *id = astman_get_header(m, "ActionID");
   char idText[256];

   if (!ast_strlen_zero(id)) {
      snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
   } else {
      idText[0] = '\0';
   }

   if (!ast_strlen_zero(timeouts)) {
      sscanf(timeouts, "%30i", &timeout);
      if (timeout < -1) {
         timeout = -1;
      }
      /* XXX maybe put an upper bound, or prevent the use of 0 ? */
   }

   ao2_lock(s->session);
   if (s->session->waiting_thread != AST_PTHREADT_NULL) {
      pthread_kill(s->session->waiting_thread, SIGURG);
   }

   if (s->session->managerid) { /* AMI-over-HTTP session */
      /*
       * Make sure the timeout is within the expire time of the session,
       * as the client will likely abort the request if it does not see
       * data coming after some amount of time.
       */
      time_t now = time(NULL);
      int max = s->session->sessiontimeout - now - 10;

      if (max < 0) { /* We are already late. Strange but possible. */
         max = 0;
      }
      if (timeout < 0 || timeout > max) {
         timeout = max;
      }
      if (!s->session->send_events) {  /* make sure we record events */
         s->session->send_events = -1;
      }
   }
   ao2_unlock(s->session);

   /* XXX should this go inside the lock ? */
   s->session->waiting_thread = pthread_self(); /* let new events wake up this thread */
   ast_debug(1, "Starting waiting for an event!\n");

   for (x = 0; x < timeout || timeout < 0; x++) {
      ao2_lock(s->session);
      if (AST_RWLIST_NEXT(s->session->last_ev, eq_next)) {
         needexit = 1;
      }
      /* We can have multiple HTTP session point to the same mansession entry.
       * The way we deal with it is not very nice: newcomers kick out the previous
       * HTTP session. XXX this needs to be improved.
       */
      if (s->session->waiting_thread != pthread_self()) {
         needexit = 1;
      }
      if (s->session->needdestroy) {
         needexit = 1;
      }
      ao2_unlock(s->session);
      if (needexit) {
         break;
      }
      if (s->session->managerid == 0) {   /* AMI session */
         if (ast_wait_for_input(s->session->fd, 1000)) {
            break;
         }
      } else { /* HTTP session */
         sleep(1);
      }
   }
   ast_debug(1, "Finished waiting for an event!\n");

   ao2_lock(s->session);
   if (s->session->waiting_thread == pthread_self()) {
      struct eventqent *eqe = s->session->last_ev;
      astman_send_response(s, m, "Success", "Waiting for Event completed.");
      while ((eqe = advance_event(eqe))) {
         if (((s->session->readperm & eqe->category) == eqe->category) &&
             ((s->session->send_events & eqe->category) == eqe->category)) {
            astman_append(s, "%s", eqe->eventdata);
         }
         s->session->last_ev = eqe;
      }
      astman_append(s,
         "Event: WaitEventComplete\r\n"
         "%s"
         "\r\n", idText);
      s->session->waiting_thread = AST_PTHREADT_NULL;
   } else {
      ast_debug(1, "Abandoning event request!\n");
   }
   ao2_unlock(s->session);

   return 0;
}
static struct eventqent* advance_event ( struct eventqent e) [static, read]
static int aocmessage_get_unit_entry ( const struct message m,
struct ast_aoc_unit_entry entry,
unsigned int  entry_num 
) [static]

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

{
   const char *unitamount;
   const char *unittype;
   struct ast_str *str = ast_str_alloca(32);

   memset(entry, 0, sizeof(*entry));

   ast_str_set(&str, 0, "UnitAmount(%u)", entry_num);
   unitamount = astman_get_header(m, ast_str_buffer(str));

   ast_str_set(&str, 0, "UnitType(%u)", entry_num);
   unittype = astman_get_header(m, ast_str_buffer(str));

   if (!ast_strlen_zero(unitamount) && (sscanf(unitamount, "%30u", &entry->amount) == 1)) {
      entry->valid_amount = 1;
   }

   if (!ast_strlen_zero(unittype) && sscanf(unittype, "%30u", &entry->type) == 1) {
      entry->valid_type = 1;
   }

   return 0;
}
static void append_channel_vars ( struct ast_str **  pbuf,
struct ast_channel chan 
) [static]

Definition at line 5003 of file manager.c.

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

Referenced by __ast_manager_event_multichan().

{
   struct manager_channel_variable *var;

   AST_RWLIST_RDLOCK(&channelvars);
   AST_LIST_TRAVERSE(&channelvars, var, entry) {
      const char *val;
      struct ast_str *res;

      if (var->isfunc) {
         res = ast_str_thread_get(&manager_event_funcbuf, 16);
         if (res && ast_func_read2(chan, var->name, &res, 0) == 0) {
            val = ast_str_buffer(res);
         } else {
            val = NULL;
         }
      } else {
         val = pbx_builtin_getvar_helper(chan, var->name);
      }
      ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", chan->name, var->name, val ? val : "");
   }
   AST_RWLIST_UNLOCK(&channelvars);
}
static int append_event ( const char *  str,
int  category 
) [static]

Definition at line 4977 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::seq, eventqent::tv, and eventqent::usecount.

Referenced by __ast_manager_event_multichan(), and __init_manager().

{
   struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str));
   static int seq;   /* sequence number */

   if (!tmp) {
      return -1;
   }

   /* need to init all fields, because ast_malloc() does not */
   tmp->usecount = 0;
   tmp->category = category;
   tmp->seq = ast_atomic_fetchadd_int(&seq, 1);
   tmp->tv = ast_tvnow();
   AST_RWLIST_NEXT(tmp, eq_next) = NULL;
   strcpy(tmp->eventdata, str);

   AST_RWLIST_WRLOCK(&all_events);
   AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next);
   AST_RWLIST_UNLOCK(&all_events);

   return 0;
}
int ast_hook_send_action ( struct manager_custom_hook hook,
const char *  msg 
)

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

Parameters:
hookthe file identifier specified in manager_custom_hook struct when registering a hook
msgami action mesage string e.g. "Action: SipPeers\r\n"
Return values:
0on Success
non-zeroon Failure

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

{
   const char *action;
   int ret = 0;
   struct manager_action *act_found;
   struct mansession s = {.session = NULL, };
   struct message m = { 0 };
   char *dup_str;
   char *src;
   int x = 0;
   int curlen;

   if (hook == NULL) {
      return -1;
   }

   /* Create our own copy of the AMI action msg string. */
   src = dup_str = ast_strdup(msg);
   if (!dup_str) {
      return -1;
   }

   /* convert msg string to message struct */
   curlen = strlen(src);
   for (x = 0; x < curlen; x++) {
      int cr;  /* set if we have \r */
      if (src[x] == '\r' && x+1 < curlen && src[x+1] == '\n')
         cr = 2;  /* Found. Update length to include \r\n */
      else if (src[x] == '\n')
         cr = 1;  /* also accept \n only */
      else
         continue;
      /* don't keep empty lines */
      if (x && m.hdrcount < ARRAY_LEN(m.headers)) {
         /* ... but trim \r\n and terminate the header string */
         src[x] = '\0';
         m.headers[m.hdrcount++] = src;
      }
      x += cr;
      curlen -= x;      /* remaining size */
      src += x;      /* update pointer */
      x = -1;        /* reset loop */
   }

   action = astman_get_header(&m, "Action");
   if (strcasecmp(action, "login")) {
      act_found = action_find(action);
      if (act_found) {
         /*
          * we have to simulate a session for this action request
          * to be able to pass it down for processing
          * This is necessary to meet the previous design of manager.c
          */
         s.hook = hook;
         s.f = (void*)1; /* set this to something so our request will make it through all functions that test it*/

         ao2_lock(act_found);
         if (act_found->registered && act_found->func) {
            ret = act_found->func(&s, &m);
         } else {
            ret = -1;
         }
         ao2_unlock(act_found);
         ao2_t_ref(act_found, -1, "done with found action object");
      }
   }
   ast_free(dup_str);
   return ret;
}
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 1207 of file manager.c.

Referenced by get_perm().

{
   const char *val = bigstr, *next;

   do {
      if ((next = strchr(val, delim))) {
         if (!strncmp(val, smallstr, (next - val))) {
            return 1;
         } else {
            continue;
         }
      } else {
         return !strcmp(smallstr, val);
      }
   } while (*(val = (next + 1)));

   return 0;
}
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 5213 of file manager.c.

References manager_action::action, action_destroy(), ao2_alloc, ao2_t_ref, ast_free, ast_manager_register_struct(), AST_STATIC_DOC, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), manager_action::authority, manager_action::docsrc, and manager_action::func.

Referenced by load_module().

{
   struct manager_action *cur;

   cur = ao2_alloc(sizeof(*cur), action_destroy);
   if (!cur) {
      return -1;
   }
   if (ast_string_field_init(cur, 128)) {
      ao2_t_ref(cur, -1, "action object creation failed");
      return -1;
   }

   cur->action = action;
   cur->authority = auth;
   cur->func = func;
#ifdef AST_XML_DOCS
   if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
      char *tmpxml;

      tmpxml = ast_xmldoc_build_synopsis("manager", action, NULL);
      ast_string_field_set(cur, synopsis, tmpxml);
      ast_free(tmpxml);

      tmpxml = ast_xmldoc_build_syntax("manager", action, NULL);
      ast_string_field_set(cur, syntax, tmpxml);
      ast_free(tmpxml);

      tmpxml = ast_xmldoc_build_description("manager", action, NULL);
      ast_string_field_set(cur, description, tmpxml);
      ast_free(tmpxml);

      tmpxml = ast_xmldoc_build_seealso("manager", action, NULL);
      ast_string_field_set(cur, seealso, tmpxml);
      ast_free(tmpxml);

      tmpxml = ast_xmldoc_build_arguments("manager", action, NULL);
      ast_string_field_set(cur, arguments, tmpxml);
      ast_free(tmpxml);

      cur->docsrc = AST_XML_DOC;
   } else
#endif
   {
      ast_string_field_set(cur, synopsis, synopsis);
      ast_string_field_set(cur, description, description);
#ifdef AST_XML_DOCS
      cur->docsrc = AST_STATIC_DOC;
#endif
   }
   if (ast_manager_register_struct(cur)) {
      ao2_t_ref(cur, -1, "action object registration failed");
      return -1;
   }

   ao2_t_ref(cur, -1, "action object registration successful");
   return 0;
}
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:
hookstruct manager_custom_hook object to add

Definition at line 1076 of file manager.c.

References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

static int ast_manager_register_struct ( struct manager_action act) [static]

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

{
   struct manager_action *cur, *prev = NULL;

   AST_RWLIST_WRLOCK(&actions);
   AST_RWLIST_TRAVERSE(&actions, cur, list) {
      int ret;

      ret = strcasecmp(cur->action, act->action);
      if (ret == 0) {
         ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action);
         AST_RWLIST_UNLOCK(&actions);
         return -1;
      }
      if (ret > 0) { /* Insert these alphabetically */
         prev = cur;
         break;
      }
   }

   ao2_t_ref(act, +1, "action object added to list");
   act->registered = 1;
   if (prev) {
      AST_RWLIST_INSERT_AFTER(&actions, prev, act, list);
   } else {
      AST_RWLIST_INSERT_HEAD(&actions, act, list);
   }

   ast_verb(2, "Manager registered action %s\n", act->action);

   AST_RWLIST_UNLOCK(&actions);

   return 0;
}
int ast_manager_unregister ( char *  action)

Unregister a registered manager command.

Parameters:
actionName of registered Action:

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

{
   struct manager_action *cur;

   AST_RWLIST_WRLOCK(&actions);
   AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) {
      if (!strcasecmp(action, cur->action)) {
         AST_RWLIST_REMOVE_CURRENT(list);
         break;
      }
   }
   AST_RWLIST_TRAVERSE_SAFE_END;
   AST_RWLIST_UNLOCK(&actions);

   if (cur) {
      /*
       * We have removed the action object from the container so we
       * are no longer in a hurry.
       */
      ao2_lock(cur);
      cur->registered = 0;
      ao2_unlock(cur);

      ao2_t_ref(cur, -1, "action object removed from list");
      ast_verb(2, "Manager unregistered action %s\n", action);
   }

   return 0;
}
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:
hookstruct manager_custom_hook object to delete

Definition at line 1084 of file manager.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

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

utility functions for creating AMI replies

Definition at line 1994 of file manager.c.

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

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

{
   va_list ap;
   struct ast_str *buf;

   if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
      return;
   }

   va_start(ap, fmt);
   ast_str_set_va(&buf, 0, fmt, ap);
   va_end(ap);

   if (s->f != NULL || s->session->f != NULL) {
      send_string(s, ast_str_buffer(buf));
   } else {
      ast_verbose("fd == -1 in astman_append, should not happen\n");
   }
}
static void astman_append_json ( struct mansession s,
const char *  str 
) [static]

Definition at line 2564 of file manager.c.

References astman_append(), and json_escape().

Referenced by action_getconfigjson().

{
   char *buf;

   buf = alloca(2 * strlen(str) + 1);
   json_escape(buf, str);
   astman_append(s, "%s", buf);
}
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 1800 of file manager.c.

References __astman_get_header(), and GET_HEADER_FIRST_MATCH.

Referenced by _sip_show_peer(), _sip_show_peers(), _skinny_show_devices(), _skinny_show_lines(), action_add_agi_cmd(), action_agent_logoff(), action_agents(), action_aocmessage(), action_atxfer(), action_bridge(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdishowchannels(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_originate(), action_ping(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), action_waitevent(), aocmessage_get_unit_entry(), ast_hook_send_action(), astman_send_response_full(), authenticate(), change_monitor_action(), do_pause_or_unpause(), handle_updates(), manager_add_queue_member(), manager_data_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_jabber_send(), manager_list_voicemail_users(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_optimize_away(), manager_park(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_queue_rule_show(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), manager_rpt_status(), manager_show_dialplan(), manager_show_registry(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), meetmemute(), process_message(), rpt_manager_do_stats(), rpt_manager_success(), start_monitor_action(), and stop_monitor_action().

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

Get a linked list of the Variable: headers.

Definition at line 1858 of file manager.c.

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

Referenced by action_originate(), and manager_sipnotify().

{
   int varlen;
   int x;
   struct ast_variable *head = NULL;

   static const char var_hdr[] = "Variable:";

   /* Process all "Variable:" headers. */
   varlen = strlen(var_hdr);
   for (x = 0; x < m->hdrcount; x++) {
      if (strncasecmp(var_hdr, m->headers[x], varlen)) {
         continue;
      }
      head = man_do_variable_value(head, m->headers[x] + varlen);
   }

   return head;
}
void astman_send_error ( struct mansession s,
const struct message m,
char *  error 
)

Send error in manager transaction.

Definition at line 2056 of file manager.c.

References astman_send_response_full().

Referenced by _sip_qualify_peer(), _sip_show_peer(), action_add_agi_cmd(), action_agent_logoff(), action_aocmessage(), action_atxfer(), action_bridge(), action_challenge(), action_command(), action_coreshowchannels(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_originate(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), change_monitor_action(), do_message(), do_pause_or_unpause(), manager_add_queue_member(), manager_data_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_jabber_send(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_optimize_away(), manager_park(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_remove_queue_member(), manager_rpt_status(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_line(), meetmemute(), process_message(), rpt_manager_do_stats(), start_monitor_action(), and stop_monitor_action().

{
   astman_send_response_full(s, m, "Error", error, NULL);
}
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 2051 of file manager.c.

References astman_send_response_full().

Referenced by action_logoff(), and action_waitevent().

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

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

{
   const char *id = astman_get_header(m, "ActionID");

   astman_append(s, "Response: %s\r\n", resp);
   if (!ast_strlen_zero(id)) {
      astman_append(s, "ActionID: %s\r\n", id);
   }
   if (listflag) {
      astman_append(s, "EventList: %s\r\n", listflag);   /* Start, complete, cancelled */
   }
   if (msg == MSG_MOREDATA) {
      return;
   } else if (msg) {
      astman_append(s, "Message: %s\r\n\r\n", msg);
   } else {
      astman_append(s, "\r\n");
   }
}
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 2348 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(), mansession_session::readperm, ast_manager_user::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, mansession_session::writeperm, ast_manager_user::writeperm, mansession_session::writetimeout, and ast_manager_user::writetimeout.

Referenced by action_login().

{
   const char *username = astman_get_header(m, "Username");
   const char *password = astman_get_header(m, "Secret");
   int error = -1;
   struct ast_manager_user *user = NULL;
   regex_t *regex_filter;
   struct ao2_iterator filter_iter;
   struct ast_sockaddr addr;

   if (ast_strlen_zero(username)) { /* missing username */
      return -1;
   }

   /* locate user in locked state */
   AST_RWLIST_WRLOCK(&users);

   ast_sockaddr_from_sin(&addr, &s->session->sin);

   if (!(user = get_manager_by_name_locked(username))) {
      report_invalid_user(s, username);
      ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
   } else if (user->ha && !ast_apply_ha(user->ha, &addr)) {
      report_failed_acl(s, username);
      ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
   } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) {
      const char *key = astman_get_header(m, "Key");
      if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) {
         int x;
         int len = 0;
         char md5key[256] = "";
         struct MD5Context md5;
         unsigned char digest[16];

         MD5Init(&md5);
         MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge));
         MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret));
         MD5Final(digest, &md5);
         for (x = 0; x < 16; x++)
            len += sprintf(md5key + len, "%2.2x", digest[x]);
         if (!strcmp(md5key, key)) {
            error = 0;
         } else {
            report_failed_challenge_response(s, key, md5key);
         }
      } else {
         ast_debug(1, "MD5 authentication is not possible.  challenge: '%s'\n",
            S_OR(s->session->challenge, ""));
      }
   } else if (user->secret) {
      if (!strcmp(password, user->secret)) {
         error = 0;
      } else {
         report_inval_password(s, username);
      }
   }

   if (error) {
      ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
      AST_RWLIST_UNLOCK(&users);
      return -1;
   }

   /* auth complete */

   /* All of the user parameters are copied to the session so that in the event
     * of a reload and a configuration change, the session parameters are not
     * changed. */
   ast_copy_string(s->session->username, username, sizeof(s->session->username));
   s->session->readperm = user->readperm;
   s->session->writeperm = user->writeperm;
   s->session->writetimeout = user->writetimeout;

   filter_iter = ao2_iterator_init(user->whitefilters, 0);
   while ((regex_filter = ao2_iterator_next(&filter_iter))) {
      ao2_t_link(s->session->whitefilters, regex_filter, "add white user filter to session");
      ao2_t_ref(regex_filter, -1, "remove iterator ref");
   }
   ao2_iterator_destroy(&filter_iter);

   filter_iter = ao2_iterator_init(user->blackfilters, 0);
   while ((regex_filter = ao2_iterator_next(&filter_iter))) {
      ao2_t_link(s->session->blackfilters, regex_filter, "add black user filter to session");
      ao2_t_ref(regex_filter, -1, "remove iterator ref");
   }
   ao2_iterator_destroy(&filter_iter);

   s->session->sessionstart = time(NULL);
   s->session->sessionstart_tv = ast_tvnow();
   set_eventmask(s, astman_get_header(m, "Events"));

   report_auth_success(s);

   AST_RWLIST_UNLOCK(&users);
   return 0;
}
static const char* authority_to_str ( int  authority,
struct ast_str **  res 
) [static]

Convert authority code to a list of options.

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

{
   int i;
   char *sep = "";

   ast_str_reset(*res);
   for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
      if (authority & perms[i].num) {
         ast_str_append(res, 0, "%s%s", sep, perms[i].label);
         sep = ",";
      }
   }

   if (ast_str_strlen(*res) == 0)   /* replace empty string with something sensible */
      ast_str_append(res, 0, "<none>");

   return ast_str_buffer(*res);
}
static int blackfilter_cmp_fn ( void *  obj,
void *  arg,
void *  data,
int  flags 
) [static]

Definition at line 4197 of file manager.c.

References CMP_MATCH, CMP_STOP, and ast_frame::data.

Referenced by match_filter().

{
   regex_t *regex_filter = obj;
   const char *eventdata = arg;
   int *result = data;

   if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
      *result = 0;
      return (CMP_MATCH | CMP_STOP);
   }

   *result = 1;
   return 0;
}
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 1324 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().

{
   struct mansession_session *newsession;

   if (!(newsession = ao2_alloc(sizeof(*newsession), session_destructor))) {
      return NULL;
   }

   if (!(newsession->whitefilters = ao2_container_alloc(1, NULL, NULL))) {
      ao2_ref(newsession, -1);
      return NULL;
   }

   if (!(newsession->blackfilters = ao2_container_alloc(1, NULL, NULL))) {
      ao2_ref(newsession, -1); /* session_destructor will cleanup the other filter */
      return NULL;
   }

   newsession->fd = -1;
   newsession->waiting_thread = AST_PTHREADT_NULL;
   newsession->writetimeout = 100;
   newsession->send_events = -1;
   newsession->sin = sin;

   ao2_link(sessions, newsession);

   return newsession;
}
static int check_blacklist ( const char *  cmd) [static]

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

{
   char *cmd_copy, *cur_cmd;
   char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, };
   int i;

   cmd_copy = ast_strdupa(cmd);
   for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) {
      cur_cmd = ast_strip(cur_cmd);
      if (ast_strlen_zero(cur_cmd)) {
         i--;
         continue;
      }

      cmd_words[i] = cur_cmd;
   }

   for (i = 0; i < ARRAY_LEN(command_blacklist); i++) {
      int j, match = 1;

      for (j = 0; command_blacklist[i].words[j]; j++) {
         if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) {
            match = 0;
            break;
         }
      }

      if (match) {
         return 1;
      }
   }

   return 0;
}
int check_manager_enabled ( void  )

Check if AMI is enabled.

Definition at line 1091 of file manager.c.

References manager_enabled.

Referenced by handle_show_settings().

{
   return manager_enabled;
}
static int check_manager_session_inuse ( const char *  name) [static]

Definition at line 1367 of file manager.c.

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

Referenced by process_message().

{
   struct mansession_session *session = ao2_find(sessions, (char *) name, 0);
   int inuse = 0;

   if (session) {
      inuse = 1;
      unref_mansession(session);
   }
   return inuse;
}
int check_webmanager_enabled ( void  )

Check if AMI/HTTP is enabled.

Definition at line 1096 of file manager.c.

Referenced by action_coresettings(), and handle_show_settings().

static int do_message ( struct mansession s) [static]

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

{
   struct message m = { 0 };
   char header_buf[sizeof(s->session->inbuf)] = { '\0' };
   int res;
   int idx;
   int hdr_loss;
   time_t now;

   hdr_loss = 0;
   for (;;) {
      /* Check if any events are pending and do them if needed */
      if (process_events(s)) {
         res = -1;
         break;
      }
      res = get_input(s, header_buf);
      if (res == 0) {
         /* No input line received. */
         if (!s->session->authenticated) {
            if (time(&now) == -1) {
               ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
               res = -1;
               break;
            }

            if (now - s->session->authstart > authtimeout) {
               if (displayconnects) {
                  ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout);
               }
               res = -1;
               break;
            }
         }
         continue;
      } else if (res > 0) {
         /* Input line received. */
         if (ast_strlen_zero(header_buf)) {
            if (hdr_loss) {
               mansession_lock(s);
               astman_send_error(s, &m, "Too many lines in message or allocation failure");
               mansession_unlock(s);
               res = 0;
            } else {
               res = process_message(s, &m) ? -1 : 0;
            }
            break;
         } else if (m.hdrcount < ARRAY_LEN(m.headers)) {
            m.headers[m.hdrcount] = ast_strdup(header_buf);
            if (!m.headers[m.hdrcount]) {
               /* Allocation failure. */
               hdr_loss = 1;
            } else {
               ++m.hdrcount;
            }
         } else {
            /* Too many lines in message. */
            hdr_loss = 1;
         }
      } else {
         /* Input error. */
         break;
      }
   }

   /* Free AMI request headers. */
   for (idx = 0; idx < m.hdrcount; ++idx) {
      ast_free((void *) m.headers[idx]);
   }
   return res;
}
static void event_filter_destructor ( void *  obj) [static]

Definition at line 1287 of file manager.c.

Referenced by __init_manager().

{
   regex_t *regex_filter = obj;
   regfree(regex_filter);
}
static void* fast_originate ( void *  data) [static]

Definition at line 3666 of file manager.c.

References fast_originate_helper::account, fast_originate_helper::app, fast_originate_helper::appdata, AST_CHANNEL_NAME, ast_channel_unlock, ast_free, ast_manager_event_multichan, ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_string_field_free_memory, ast_strlen_zero(), fast_originate_helper::cid_name, fast_originate_helper::cid_num, fast_originate_helper::context, ast_frame::data, fast_originate_helper::data, EVENT_FLAG_CALL, fast_originate_helper::exten, fast_originate_helper::format, fast_originate_helper::idtext, ast_channel::name, fast_originate_helper::priority, S_OR, fast_originate_helper::tech, fast_originate_helper::timeout, ast_channel::uniqueid, and fast_originate_helper::vars.

Referenced by action_originate().

{
   struct fast_originate_helper *in = data;
   int res;
   int reason = 0;
   struct ast_channel *chan = NULL, *chans[1];
   char requested_channel[AST_CHANNEL_NAME];

   if (!ast_strlen_zero(in->app)) {
      res = ast_pbx_outgoing_app(in->tech, in->format, in->data, in->timeout, in->app, in->appdata, &reason, 1,
         S_OR(in->cid_num, NULL),
         S_OR(in->cid_name, NULL),
         in->vars, in->account, &chan);
   } else {
      res = ast_pbx_outgoing_exten(in->tech, in->format, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1,
         S_OR(in->cid_num, NULL),
         S_OR(in->cid_name, NULL),
         in->vars, in->account, &chan);
   }

   if (!chan) {
      snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);
   }
   /* Tell the manager what happened with the channel */
   chans[0] = chan;
   ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans,
      "%s%s"
      "Response: %s\r\n"
      "Channel: %s\r\n"
      "Context: %s\r\n"
      "Exten: %s\r\n"
      "Reason: %d\r\n"
      "Uniqueid: %s\r\n"
      "CallerIDNum: %s\r\n"
      "CallerIDName: %s\r\n",
      in->idtext, ast_strlen_zero(in->idtext) ? "" : "\r\n", res ? "Failure" : "Success",
      chan ? chan->name : requested_channel, in->context, in->exten, reason,
      chan ? chan->uniqueid : "<null>",
      S_OR(in->cid_num, "<unknown>"),
      S_OR(in->cid_name, "<unknown>")
      );

   /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
   if (chan) {
      ast_channel_unlock(chan);
   }
   ast_string_field_free_memory(in);
   ast_free(in);
   return NULL;
}
static void free_channelvars ( void  ) [static]
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 4672 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.

Referenced by do_message().

{
   int res, x;
   int maxlen = sizeof(s->session->inbuf) - 1;
   char *src = s->session->inbuf;
   int timeout = -1;
   time_t now;

   /*
    * Look for \r\n within the buffer. If found, copy to the output
    * buffer and return, trimming the \r\n (not used afterwards).
    */
   for (x = 0; x < s->session->inlen; x++) {
      int cr;  /* set if we have \r */
      if (src[x] == '\r' && x+1 < s->session->inlen && src[x + 1] == '\n') {
         cr = 2;  /* Found. Update length to include \r\n */
      } else if (src[x] == '\n') {
         cr = 1;  /* also accept \n only */
      } else {
         continue;
      }
      memmove(output, src, x);   /*... but trim \r\n */
      output[x] = '\0';    /* terminate the string */
      x += cr;       /* number of bytes used */
      s->session->inlen -= x;       /* remaining size */
      memmove(src, src + x, s->session->inlen); /* remove used bytes */
      return 1;
   }
   if (s->session->inlen >= maxlen) {
      /* no crlf found, and buffer full - sorry, too long for us */
      ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", ast_inet_ntoa(s->session->sin.sin_addr), src);
      s->session->inlen = 0;
   }
   res = 0;
   while (res == 0) {
      /* calculate a timeout if we are not authenticated */
      if (!s->session->authenticated) {
         if(time(&now) == -1) {
            ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
            return -1;
         }

         timeout = (authtimeout - (now - s->session->authstart)) * 1000;
         if (timeout < 0) {
            /* we have timed out */
            return 0;
         }
      }

      ao2_lock(s->session);
      if (s->session->pending_event) {
         s->session->pending_event = 0;
         ao2_unlock(s->session);
         return 0;
      }
      s->session->waiting_thread = pthread_self();
      ao2_unlock(s->session);

      res = ast_wait_for_input(s->session->fd, timeout);

      ao2_lock(s->session);
      s->session->waiting_thread = AST_PTHREADT_NULL;
      ao2_unlock(s->session);
   }
   if (res < 0) {
      /* If we get a signal from some other thread (typically because
       * there are new events queued), return 0 to notify the caller.
       */
      if (errno == EINTR || errno == EAGAIN) {
         return 0;
      }
      ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno));
      return -1;
   }

   ao2_lock(s->session);
   res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f);
   if (res < 1) {
      res = -1;   /* error return */
   } else {
      s->session->inlen += res;
      src[s->session->inlen] = '\0';
      res = 0;
   }
   ao2_unlock(s->session);
   return res;
}
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 1384 of file manager.c.

References AST_RWLIST_TRAVERSE, user, and ast_manager_user::username.

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

{
   struct ast_manager_user *user = NULL;

   AST_RWLIST_TRAVERSE(&users, user, list) {
      if (!strcasecmp(user->username, name)) {
         break;
      }
   }

   return user;
}
static int get_perm ( const char *  instr) [static]

Definition at line 1226 of file manager.c.

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

Referenced by __init_manager(), and strings_to_mask().

{
   int x = 0, ret = 0;

   if (!instr) {
      return 0;
   }

   for (x = 0; x < ARRAY_LEN(perms); x++) {
      if (ast_instring(instr, perms[x].label, ',')) {
         ret |= perms[x].num;
      }
   }

   return ret;
}
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 1105 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().

{
   struct eventqent *ret;

   AST_RWLIST_WRLOCK(&all_events);
   ret = AST_RWLIST_LAST(&all_events);
   /* the list is never empty now, but may become so when
    * we optimize it in the future, so be prepared.
    */
   if (ret) {
      ast_atomic_fetchadd_int(&ret->usecount, 1);
   }
   AST_RWLIST_UNLOCK(&all_events);
   return ret;
}
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 1718 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.

{
   switch (cmd) {
   case CLI_INIT:
      e->command = "manager reload";
      e->usage =
         "Usage: manager reload\n"
         "       Reloads the manager configuration.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }
   if (a->argc > 2) {
      return CLI_SHOWUSAGE;
   }
   reload_manager();
   return CLI_SUCCESS;
}
static char* handle_mandebug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

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

{
   switch (cmd) {
   case CLI_INIT:
      e->command = "manager set debug [on|off]";
      e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }

   if (a->argc == 3) {
      ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off");
   } else if (a->argc == 4) {
      if (!strcasecmp(a->argv[3], "on")) {
         manager_debug = 1;
      } else if (!strcasecmp(a->argv[3], "off")) {
         manager_debug = 0;
      } else {
         return CLI_SHOWUSAGE;
      }
   }
   return CLI_SUCCESS;
}
static char* handle_showmanager ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

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

{
   struct ast_manager_user *user = NULL;
   int l, which;
   char *ret = NULL;
   struct ast_str *rauthority = ast_str_alloca(128);
   struct ast_str *wauthority = ast_str_alloca(128);

   switch (cmd) {
   case CLI_INIT:
      e->command = "manager show user";
      e->usage =
         " Usage: manager show user <user>\n"
         "        Display all information related to the manager user specified.\n";
      return NULL;
   case CLI_GENERATE:
      l = strlen(a->word);
      which = 0;
      if (a->pos != 3) {
         return NULL;
      }
      AST_RWLIST_RDLOCK(&users);
      AST_RWLIST_TRAVERSE(&users, user, list) {
         if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) {
            ret = ast_strdup(user->username);
            break;
         }
      }
      AST_RWLIST_UNLOCK(&users);
      return ret;
   }

   if (a->argc != 4) {
      return CLI_SHOWUSAGE;
   }

   AST_RWLIST_RDLOCK(&users);

   if (!(user = get_manager_by_name_locked(a->argv[3]))) {
      ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]);
      AST_RWLIST_UNLOCK(&users);
      return CLI_SUCCESS;
   }

   ast_cli(a->fd, "\n");
   ast_cli(a->fd,
      "       username: %s\n"
      "         secret: %s\n"
      "            acl: %s\n"
      "      read perm: %s\n"
      "     write perm: %s\n"
      "displayconnects: %s\n",
      (user->username ? user->username : "(N/A)"),
      (user->secret ? "<Set>" : "(N/A)"),
      (user->ha ? "yes" : "no"),
      authority_to_str(user->readperm, &rauthority),
      authority_to_str(user->writeperm, &wauthority),
      (user->displayconnects ? "yes" : "no"));

   AST_RWLIST_UNLOCK(&users);

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

Definition at line 1581 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_cli_entry::usage, and ast_manager_user::username.

{
   struct ast_manager_user *user = NULL;
   int count_amu = 0;
   switch (cmd) {
   case CLI_INIT:
      e->command = "manager show users";
      e->usage =
         "Usage: manager show users\n"
         "       Prints a listing of all managers that are currently configured on that\n"
         " system.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }
   if (a->argc != 3) {
      return CLI_SHOWUSAGE;
   }

   AST_RWLIST_RDLOCK(&users);

   /* If there are no users, print out something along those lines */
   if (AST_RWLIST_EMPTY(&users)) {
      ast_cli(a->fd, "There are no manager users.\n");
      AST_RWLIST_UNLOCK(&users);
      return CLI_SUCCESS;
   }

   ast_cli(a->fd, "\nusername\n--------\n");

   AST_RWLIST_TRAVERSE(&users, user, list) {
      ast_cli(a->fd, "%s\n", user->username);
      count_amu++;
   }

   AST_RWLIST_UNLOCK(&users);

   ast_cli(a->fd,"-------------------\n"
            "%d manager users configured.\n", count_amu);
   return CLI_SUCCESS;
}
static char* handle_showmancmd ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1415 of file manager.c.

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

{
   struct manager_action *cur;
   struct ast_str *authority;
   int num, l, which;
   char *ret = NULL;
#ifdef AST_XML_DOCS
   char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64];
#endif

   switch (cmd) {
   case CLI_INIT:
      e->command = "manager show command";
      e->usage =
         "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n"
         "  Shows the detailed description for a specific Asterisk manager interface command.\n";
      return NULL;
   case CLI_GENERATE:
      l = strlen(a->word);
      which = 0;
      AST_RWLIST_RDLOCK(&actions);
      AST_RWLIST_TRAVERSE(&actions, cur, list) {
         if (!strncasecmp(a->word, cur->action, l) && ++which > a->n) {
            ret = ast_strdup(cur->action);
            break;   /* make sure we exit even if ast_strdup() returns NULL */
         }
      }
      AST_RWLIST_UNLOCK(&actions);
      return ret;
   }
   authority = ast_str_alloca(80);
   if (a->argc < 4) {
      return CLI_SHOWUSAGE;
   }

#ifdef AST_XML_DOCS
   /* setup the titles */
   term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
   term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40);
   term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
   term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40);
   term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
#endif

   AST_RWLIST_RDLOCK(&actions);
   AST_RWLIST_TRAVERSE(&actions, cur, list) {
      for (num = 3; num < a->argc; num++) {
         if (!strcasecmp(cur->action, a->argv[num])) {
#ifdef AST_XML_DOCS
            if (cur->docsrc == AST_XML_DOC) {
               ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n",
                  syntax_title,
                  ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1),
                  synopsis_title,
                  ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1),
                  description_title,
                  ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1),
                  arguments_title,
                  ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1),
                  seealso_title,
                  ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1));
            } else
#endif
            {
               ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
                  cur->action, cur->synopsis,
                  authority_to_str(cur->authority, &authority),
                  S_OR(cur->description, ""));
            }
         }
      }
   }
   AST_RWLIST_UNLOCK(&actions);

   return CLI_SUCCESS;
}
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 1624 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, manager_action::synopsis, and ast_cli_entry::usage.

{
   struct manager_action *cur;
   struct ast_str *authority;
#define HSMC_FORMAT "  %-15.15s  %-15.15s  %-55.55s\n"
   switch (cmd) {
   case CLI_INIT:
      e->command = "manager show commands";
      e->usage =
         "Usage: manager show commands\n"
         "  Prints a listing of all the available Asterisk manager interface commands.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }
   authority = ast_str_alloca(80);
   ast_cli(a->fd, HSMC_FORMAT, "Action", "Privilege", "Synopsis");
   ast_cli(a->fd, HSMC_FORMAT, "------", "---------", "--------");

   AST_RWLIST_RDLOCK(&actions);
   AST_RWLIST_TRAVERSE(&actions, cur, list) {
      ast_cli(a->fd, HSMC_FORMAT, cur->action, authority_to_str(cur->authority, &authority), cur->synopsis);
   }
   AST_RWLIST_UNLOCK(&actions);

   return CLI_SUCCESS;
}
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 1653 of file manager.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_cli(), ast_inet_ntoa(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, mansession_session::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.

{
   struct mansession_session *session;
   time_t now = time(NULL);
#define HSMCONN_FORMAT1 "  %-15.15s  %-15.15s  %-10.10s  %-10.10s  %-8.8s  %-8.8s  %-5.5s  %-5.5s\n"
#define HSMCONN_FORMAT2 "  %-15.15s  %-15.15s  %-10d  %-10d  %-8d  %-8d  %-5.5d  %-5.5d\n"
   int count = 0;
   struct ao2_iterator i;

   switch (cmd) {
   case CLI_INIT:
      e->command = "manager show connected";
      e->usage =
         "Usage: manager show connected\n"
         "  Prints a listing of the users that are currently connected to the\n"
         "Asterisk manager interface.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }

   ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write");

   i = ao2_iterator_init(sessions, 0);
   while ((session = ao2_iterator_next(&i))) {
      ao2_lock(session);
      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);
      count++;
      ao2_unlock(session);
      unref_mansession(session);
   }
   ao2_iterator_destroy(&i);
   ast_cli(a->fd, "%d users connected.\n", count);

   return CLI_SUCCESS;
}
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 1692 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, ast_cli_args::fd, ast_cli_entry::usage, and eventqent::usecount.

{
   struct eventqent *s;
   switch (cmd) {
   case CLI_INIT:
      e->command = "manager show eventq";
      e->usage =
         "Usage: manager show eventq\n"
         "  Prints a listing of all events pending in the Asterisk manger\n"
         "event queue.\n";
      return NULL;
   case CLI_GENERATE:
      return NULL;
   }
   AST_RWLIST_RDLOCK(&all_events);
   AST_RWLIST_TRAVERSE(&all_events, s, eq_next) {
      ast_cli(a->fd, "Usecount: %d\n", s->usecount);
      ast_cli(a->fd, "Category: %d\n", s->category);
      ast_cli(a->fd, "Event:\n%s", s->eventdata);
   }
   AST_RWLIST_UNLOCK(&all_events);

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

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

{
   int x;
   char hdr[40];
   const char *action, *cat, *var, *value, *match, *line;
   struct ast_category *category;
   struct ast_variable *v;
   struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
   enum error_type result = 0;

   for (x = 0; x < 100000; x++) {   /* 100000 = the max number of allowed updates + 1 */
      unsigned int object = 0;

      snprintf(hdr, sizeof(hdr), "Action-%06d", x);
      action = astman_get_header(m, hdr);
      if (ast_strlen_zero(action))     /* breaks the for loop if no action header */
         break;                        /* this could cause problems if actions come in misnumbered */

      snprintf(hdr, sizeof(hdr), "Cat-%06d", x);
      cat = astman_get_header(m, hdr);
      if (ast_strlen_zero(cat)) {      /* every action needs a category */
         result =  UNSPECIFIED_CATEGORY;
         break;
      }

      snprintf(hdr, sizeof(hdr), "Var-%06d", x);
      var = astman_get_header(m, hdr);

      snprintf(hdr, sizeof(hdr), "Value-%06d", x);
      value = astman_get_header(m, hdr);

      if (!ast_strlen_zero(value) && *value == '>') {
         object = 1;
         value++;
      }

      snprintf(hdr, sizeof(hdr), "Match-%06d", x);
      match = astman_get_header(m, hdr);

      snprintf(hdr, sizeof(hdr), "Line-%06d", x);
      line = astman_get_header(m, hdr);

      if (!strcasecmp(action, "newcat")) {
         if (ast_category_get(cfg,cat)) { /* check to make sure the cat doesn't */
            result = FAILURE_NEWCAT;   /* already exist */
            break;
         }
         if (!(category = ast_category_new(cat, dfn, -1))) {
            result = FAILURE_ALLOCATION;
            break;
         }
         if (ast_strlen_zero(match)) {
            ast_category_append(cfg, category);
         } else {
            ast_category_insert(cfg, category, match);
         }
      } else if (!strcasecmp(action, "renamecat")) {
         if (ast_strlen_zero(value)) {
            result = UNSPECIFIED_ARGUMENT;
            break;
         }
         if (!(category = ast_category_get(cfg, cat))) {
            result = UNKNOWN_CATEGORY;
            break;
         }
         ast_category_rename(category, value);
      } else if (!strcasecmp(action, "delcat")) {
         if (ast_category_delete(cfg, cat)) {
            result = FAILURE_DELCAT;
            break;
         }
      } else if (!strcasecmp(action, "emptycat")) {
         if (ast_category_empty(cfg, cat)) {
            result = FAILURE_EMPTYCAT;
            break;
         }
      } else if (!strcasecmp(action, "update")) {
         if (ast_strlen_zero(var)) {
            result = UNSPECIFIED_ARGUMENT;
            break;
         }
         if (!(category = ast_category_get(cfg,cat))) {
            result = UNKNOWN_CATEGORY;
            break;
         }
         if (ast_variable_update(category, var, value, match, object)) {
            result = FAILURE_UPDATE;
            break;
         }
      } else if (!strcasecmp(action, "delete")) {
         if ((ast_strlen_zero(var) && ast_strlen_zero(line))) {
            result = UNSPECIFIED_ARGUMENT;
            break;
         }
         if (!(category = ast_category_get(cfg, cat))) {
            result = UNKNOWN_CATEGORY;
            break;
         }
         if (ast_variable_delete(category, var, match, line)) {
            result = FAILURE_DELETE;
            break;
         }
      } else if (!strcasecmp(action, "append")) {
         if (ast_strlen_zero(var)) {
            result = UNSPECIFIED_ARGUMENT;
            break;
         }
         if (!(category = ast_category_get(cfg, cat))) {
            result = UNKNOWN_CATEGORY;
            break;
         }
         if (!(v = ast_variable_new(var, value, dfn))) {
            result = FAILURE_ALLOCATION;
            break;
         }
         if (object || (match && !strcasecmp(match, "object"))) {
            v->object = 1;
         }
         ast_variable_append(category, v);
      } else if (!strcasecmp(action, "insert")) {
         if (ast_strlen_zero(var) || ast_strlen_zero(line)) {
            result = UNSPECIFIED_ARGUMENT;
            break;
         }
         if (!(category = ast_category_get(cfg, cat))) {
            result = UNKNOWN_CATEGORY;
            break;
         }
         if (!(v = ast_variable_new(var, value, dfn))) {
            result = FAILURE_ALLOCATION;
            break;
         }
         ast_variable_insert(category, v, line);
      }
      else {
         ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action);
         result = UNKNOWN_ACTION;
         break;
      }
   }
   ast_free(str1);
   ast_free(str2);
   return result;
}
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 2544 of file manager.c.

Referenced by astman_append_json().

{
   for (; *in; in++) {
      if (*in == '\\' || *in == '\"') {
         *out++ = '\\';
      }
      *out++ = *in;
   }
   *out = '\0';
}
static struct ast_variable* man_do_variable_value ( struct ast_variable head,
const char *  hdr_val 
) [static, read]

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

{
   char *parse;
   AST_DECLARE_APP_ARGS(args,
      AST_APP_ARG(vars)[64];
   );

   hdr_val = ast_skip_blanks(hdr_val); /* ignore leading spaces in the value */
   parse = ast_strdupa(hdr_val);

   /* Break the header value string into name=val pair items. */
   AST_STANDARD_APP_ARGS(args, parse);
   if (args.argc) {
      int y;

      /* Process each name=val pair item. */
      for (y = 0; y < args.argc; y++) {
         struct ast_variable *cur;
         char *var;
         char *val;

         if (!args.vars[y]) {
            continue;
         }
         var = val = args.vars[y];
         strsep(&val, "=");

         /* XXX We may wish to trim whitespace from the strings. */
         if (!val || ast_strlen_zero(var)) {
            continue;
         }

         /* Create new variable list node and prepend it to the list. */
         cur = ast_variable_new(var, val, "");
         if (cur) {
            cur->next = head;
            head = cur;
         }
      }
   }

   return head;
}
static int manager_displayconnects ( struct mansession_session session) [static]

Get displayconnects config option.

Parameters:
sessionmanager session to get parameter from.
Returns:
displayconnects config option value.

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

{
   struct ast_manager_user *user = NULL;
   int ret = 0;

   AST_RWLIST_RDLOCK(&users);
   if ((user = get_manager_by_name_locked (session->username))) {
      ret = user->displayconnects;
   }
   AST_RWLIST_UNLOCK(&users);

   return ret;
}
static int manager_modulecheck ( struct mansession s,
const struct message m 
) [static]

Definition at line 4466 of file manager.c.

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

Referenced by __init_manager().

{
   int res;
   const char *module = astman_get_header(m, "Module");
   const char *id = astman_get_header(m, "ActionID");
   char idText[256];
#if !defined(LOW_MEMORY)
   const char *version;
#endif
   char filename[PATH_MAX];
   char *cut;

   ast_copy_string(filename, module, sizeof(filename));
   if ((cut = strchr(filename, '.'))) {
      *cut = '\0';
   } else {
      cut = filename + strlen(filename);
   }
   snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".so");
   ast_log(LOG_DEBUG, "**** ModuleCheck .so file %s\n", filename);
   res = ast_module_check(filename);
   if (!res) {
      astman_send_error(s, m, "Module not loaded");
      return 0;
   }
   snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".c");
   ast_log(LOG_DEBUG, "**** ModuleCheck .c file %s\n", filename);
#if !defined(LOW_MEMORY)
   version = ast_file_version_find(filename);
#endif

   if (!ast_strlen_zero(id)) {
      snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
   } else {
      idText[0] = '\0';
   }
   astman_append(s, "Response: Success\r\n%s", idText);
#if !defined(LOW_MEMORY)
   astman_append(s, "Version: %s\r\n\r\n", version ? version : "");
#endif
   return 0;
}
static int manager_moduleload ( struct mansession s,
const struct message m 
) [static]

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

{
   int res;
   const char *module = astman_get_header(m, "Module");
   const char *loadtype = astman_get_header(m, "LoadType");

   if (!loadtype || strlen(loadtype) == 0) {
      astman_send_error(s, m, "Incomplete ModuleLoad action.");
   }
   if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0) {
      astman_send_error(s, m, "Need module name");
   }

   if (!strcasecmp(loadtype, "load")) {
      res = ast_load_resource(module);
      if (res) {
         astman_send_error(s, m, "Could not load module.");
      } else {
         astman_send_ack(s, m, "Module loaded.");
      }
   } else if (!strcasecmp(loadtype, "unload")) {
      res = ast_unload_resource(module, AST_FORCE_SOFT);
      if (res) {
         astman_send_error(s, m, "Could not unload module.");
      } else {
         astman_send_ack(s, m, "Module unloaded.");
      }
   } else if (!strcasecmp(loadtype, "reload")) {
      if (!ast_strlen_zero(module)) {
         res = ast_module_reload(module);
         if (res == 0) {
            astman_send_error(s, m, "No such module.");
         } else if (res == 1) {
            astman_send_error(s, m, "Module does not support reload action.");
         } else {
            astman_send_ack(s, m, "Module reloaded.");
         }
      } else {
         ast_module_reload(NULL);   /* Reload all modules */
         astman_send_ack(s, m, "All modules reloaded");
      }
   } else
      astman_send_error(s, m, "Incomplete ModuleLoad action.");
   return 0;
}
static int manager_state_cb ( char *  context,
char *  exten,
int  state,
void *  data 
) [static]

Definition at line 5148 of file manager.c.

References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.

Referenced by __init_manager().

{
   /* Notify managers of change */
   char hint[512];
   ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten);

   manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state);
   return 0;
}
static int mansession_cmp_fn ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 1353 of file manager.c.

References CMP_MATCH, str, and mansession_session::username.

Referenced by __init_manager().

{
   struct mansession_session *s = obj;
   char *str = arg;
   return !strcasecmp(s->username, str) ? CMP_MATCH : 0;
}
static struct sockaddr_in* mansession_encode_sin_local ( const struct mansession s,
struct sockaddr_in *  sin_local 
) [static, read]
static void mansession_lock ( struct mansession s) [static]

Lock the 'mansession' structure.

Definition at line 2077 of file manager.c.

References ast_mutex_lock, and mansession::lock.

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

{
   ast_mutex_lock(&s->lock);
}
static void mansession_unlock ( struct mansession s) [static]

Unlock the 'mansession' structure.

Definition at line 2083 of file manager.c.

References ast_mutex_unlock, and mansession::lock.

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

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

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

{
   int result = 0;

   ast_debug(3, "Examining event:\n%s\n", eventdata);
   if (!ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) {
      return 1; /* no filtering means match all */
   } else if (ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) {
      /* white filters only: implied black all filter processed first, then white filters */
      ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
   } else if (!ao2_container_count(s->session->whitefilters) && ao2_container_count(s->session->blackfilters)) {
      /* black filters only: implied white all filter processed first, then black filters */
      ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
   } else {
      /* white and black filters: implied black all filter processed first, then white filters, and lastly black filters */
      ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
      if (result) {
         result = 0;
         ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 
      }
   }

   return result;
}
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 4242 of file manager.c.

References advance_event(), ao2_lock, ao2_unlock, mansession_session::authenticated, eventqent::category, 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().

{
   int ret = 0;

   ao2_lock(s->session);
   if (s->session->f != NULL) {
      struct eventqent *eqe = s->session->last_ev;

      while ((eqe = advance_event(eqe))) {
         if (!ret && s->session->authenticated &&
             (s->session->readperm & eqe->category) == eqe->category &&
             (s->session->send_events & eqe->category) == eqe->category) {
               if (match_filter(s, eqe->eventdata)) {
                  if (send_string(s, eqe->eventdata) < 0)
                     ret = -1;   /* don't send more */
               }
         }
         s->session->last_ev = eqe;
      }
   }
   ao2_unlock(s->session);
   return ret;
}
static int process_message ( struct mansession s,
const struct message m 
) [static]

Definition at line 4568 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, user, and mansession_session::writeperm.

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

{
   int ret = 0;
   struct manager_action *act_found;
   const char *user;
   const char *action;

   action = __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY);
   if (ast_strlen_zero(action)) {
      report_req_bad_format(s, "NONE");
      mansession_lock(s);
      astman_send_error(s, m, "Missing action in request");
      mansession_unlock(s);
      return 0;
   }

   if (!s->session->authenticated
      && strcasecmp(action, "Login")
      && strcasecmp(action, "Logoff")
      && strcasecmp(action, "Challenge")) {
      if (!s->session->authenticated) {
         report_req_not_allowed(s, action);
      }
      mansession_lock(s);
      astman_send_error(s, m, "Permission denied");
      mansession_unlock(s);
      return 0;
   }

   if (!allowmultiplelogin
      && !s->session->authenticated
      && (!strcasecmp(action, "Login")
         || !strcasecmp(action, "Challenge"))) {
      user = astman_get_header(m, "Username");

      if (check_manager_session_inuse(user)) {
         report_session_limit(s);
         sleep(1);
         mansession_lock(s);
         astman_send_error(s, m, "Login Already In Use");
         mansession_unlock(s);
         return -1;
      }
   }

   act_found = action_find(action);
   if (act_found) {
      /* Found the requested AMI action. */
      int acted = 0;

      if ((s->session->writeperm & act_found->authority)
         || act_found->authority == 0) {
         /* We have the authority to execute the action. */
         ao2_lock(act_found);
         if (act_found->registered && act_found->func) {
            ast_debug(1, "Running action '%s'\n", act_found->action);
            ret = act_found->func(s, m);
            acted = 1;
         }
         ao2_unlock(act_found);
      }
      if (!acted) {
         /*
          * We did not execute the action because access was denied, it
          * was no longer registered, or no action was really registered.
          * Complain about it and leave.
          */
         report_req_not_allowed(s, action);
         mansession_lock(s);
         astman_send_error(s, m, "Permission denied");
         mansession_unlock(s);
      }
      ao2_t_ref(act_found, -1, "done with found action object");
   } else {
      char buf[512];

      report_req_bad_format(s, action);
      snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action);
      mansession_lock(s);
      astman_send_error(s, m, buf);
      mansession_unlock(s);
   }
   if (ret) {
      return ret;
   }
   /* Once done with our message, deliver any pending events unless the
      requester doesn't want them as part of this response.
   */
   if (ast_strlen_zero(astman_get_header(m, "SuppressEvents"))) {
      return process_events(s);
   } else {
      return ret;
   }
}
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 1125 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().

{
   struct eventqent *ev;
   struct timeval now = ast_tvnow();

   AST_RWLIST_WRLOCK(&all_events);
   while ( (ev = AST_RWLIST_FIRST(&all_events)) &&
       ev->usecount == 0 && AST_RWLIST_NEXT(ev, eq_next)) {
      AST_RWLIST_REMOVE_HEAD(&all_events, eq_next);
      ast_free(ev);
   }

   AST_RWLIST_TRAVERSE_SAFE_BEGIN(&all_events, ev, eq_next) {
      /* Never release the last event */
      if (!AST_RWLIST_NEXT(ev, eq_next)) {
         break;
      }

      /* 2.5 times whatever the HTTP timeout is (maximum 2.5 hours) is the maximum time that we will definitely cache an event */
      if (ev->usecount == 0 && ast_tvdiff_sec(now, ev->tv) > (httptimeout > 3600 ? 3600 : httptimeout) * 2.5) {
         AST_RWLIST_REMOVE_CURRENT(eq_next);
         ast_free(ev);
      }
   }
   AST_RWLIST_TRAVERSE_SAFE_END;
   AST_RWLIST_UNLOCK(&all_events);
}
static void purge_sessions ( int  n_max) [static]

remove at most n_max stale session from the list.

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

{
   struct mansession_session *session;
   time_t now = time(NULL);
   struct ao2_iterator i;

   i = ao2_iterator_init(sessions, 0);
   while ((session = ao2_iterator_next(&i)) && n_max > 0) {
      ao2_lock(session);
      if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) {
         if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) {
            ast_verb(2, "HTTP Manager '%s' timed out from %s\n",
               session->username, ast_inet_ntoa(session->sin.sin_addr));
         }
         ao2_unlock(session);
         session_destroy(session);
         n_max--;
      } else {
         ao2_unlock(session);
         unref_mansession(session);
      }
   }
   ao2_iterator_destroy(&i);
}
static void report_auth_success ( const struct mansession s) [static]

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

{
   struct sockaddr_in sin_local;
   char session_id[32];
   struct ast_security_event_successful_auth successful_auth = {
      .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH,
      .common.version    = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION,
      .common.service    = "AMI",
      .common.account_id = s->session->username,
      .common.session_tv = &s->session->sessionstart_tv,
      .common.local_addr = {
         .sin       = mansession_encode_sin_local(s, &sin_local),
         .transport = mansession_get_transport(s),
      },
      .common.remote_addr = {
         .sin       = &s->session->sin,
         .transport = mansession_get_transport(s),
      },
      .common.session_id = session_id,
   };

   snprintf(session_id, sizeof(session_id), "%p", s->session);

   ast_security_event_report(AST_SEC_EVT(&successful_auth));
}
static void report_failed_acl ( const struct mansession s,
const char *  username 
) [static]

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

{
   struct sockaddr_in sin_local;
   char session_id[32];
   struct ast_security_event_failed_acl failed_acl_event = {
      .common.event_type = AST_SECURITY_EVENT_FAILED_ACL,
      .common.version    = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
      .common.service    = "AMI",
      .common.account_id = username,
      .common.session_tv = &s->session->sessionstart_tv,
      .common.local_addr = {
         .sin       = mansession_encode_sin_local(s, &sin_local),
         .transport = mansession_get_transport(s),
      },
      .common.remote_addr = {
         .sin       = &s->session->sin,
         .transport = mansession_get_transport(s),
      },
      .common.session_id = session_id,
   };

   snprintf(session_id, sizeof(session_id), "%p", s->session);

   ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
}
static void report_failed_challenge_response ( const struct mansession s,
const char *  response,
const char *  expected_response 
) [static]

Definition at line 2284 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, ast_security_event_chal_resp_failed::expected_response, mansession_encode_sin_local(), mansession_get_transport(), ast_security_event_chal_resp_failed::response, mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.

Referenced by authenticate().

{
   struct sockaddr_in sin_local;
   char session_id[32];
   struct ast_security_event_chal_resp_failed chal_resp_failed = {
      .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED,
      .common.version    = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION,
      .common.service    = "AMI",
      .common.account_id = s->session->username,
      .common.session_tv = &s->session->sessionstart_tv,
      .common.local_addr = {
         .sin       = mansession_encode_sin_local(s, &sin_local),
         .transport = mansession_get_transport(s),
      },
      .common.remote_addr = {
         .sin       = &s->session->sin,
         .transport = mansession_get_transport(s),
      },
      .common.session_id = session_id,

      .challenge         = s->session->challenge,
      .response          = response,
      .expected_response = expected_response,
   };

   snprintf(session_id, sizeof(session_id), "%p", s->session);

   ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
}
static void report_inval_password ( const struct mansession s,
const char *  username 
) [static]

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

{
   struct sockaddr_in sin_local;
   char session_id[32];
   struct ast_security_event_inval_password inval_password = {
      .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD,
      .common.version    = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION,
      .common.service    = "AMI",
      .common.account_id = username,
      .common.session_tv = &s->session->sessionstart_tv,
      .common.local_addr = {
         .sin       = mansession_encode_sin_local(s, &sin_local),
         .transport = mansession_get_transport(s),
      },
      .common.remote_addr = {
         .sin       = &s->session->sin,
         .transport = mansession_get_transport(s),
      },
      .common.session_id = session_id,
   };

   snprintf(session_id, sizeof(session_id), "%p", s->session);

   ast_security_event_report(AST_SEC_EVT(&inval_password));
}
static void report_invalid_user ( const struct mansession s,
const char *  username 
) [static]

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

{
   struct sockaddr_in sin_local;
   char session_id[32];
   struct ast_security_event_inval_acct_id inval_acct_id = {
      .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID,
      .common.version    = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION,
      .common.service    = "AMI",
      .common.account_id = username,
      .common.session_tv = &s->session->sessionstart_tv,
      .common.local_addr = {
         .sin       = mansession_encode_sin_local(s, &sin_local),
         .transport = mansession_get_transport(s),
      },
      .common.remote_addr = {
         .sin       = &s->session->sin,
         .transport = mansession_get_transport(s),
      },
      .common.session_id = session_id,
   };

   snprintf(session_id, sizeof(session_id), "%p", s);

   ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
}
static void report_req_bad_format ( const struct mansession s,
const char *  action 
) [static]

Definition at line 2254 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(), ast_security_event_req_bad_format::request_type, mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.

Referenced by process_message().

{
   struct sockaddr_in sin_local;
   char session_id[32];
   char request_type[64];
   struct ast_security_event_req_bad_format req_bad_format = {
      .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT,
      .common.version    = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION,
      .common.service    = "AMI",
      .common.account_id = s->session->username,
      .common.session_tv = &s->session->sessionstart_tv,
      .common.local_addr = {
         .sin       = mansession_encode_sin_local(s, &sin_local),
         .transport = mansession_get_transport(s),
      },
      .common.remote_addr = {
         .sin       = &s->session->sin,
         .transport = mansession_get_transport(s),
      },
      .common.session_id = session_id,

      .request_type      = request_type,
   };

   snprintf(session_id, sizeof(session_id), "%p", s->session);
   snprintf(request_type, sizeof(request_type), "Action: %s", action);

   ast_security_event_report(AST_SEC_EVT(&req_bad_format));
}
static void report_req_not_allowed ( const struct mansession s,
const char *  action 
) [static]

Definition at line 2224 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(), ast_security_event_req_not_allowed::request_type, mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.

Referenced by process_message().

{
   struct sockaddr_in sin_local;
   char session_id[32];
   char request_type[64];
   struct ast_security_event_req_not_allowed req_not_allowed = {
      .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED,
      .common.version    = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION,
      .common.service    = "AMI",
      .common.account_id = s->session->username,
      .common.session_tv = &s->session->sessionstart_tv,
      .common.local_addr = {
         .sin       = mansession_encode_sin_local(s, &sin_local),
         .transport = mansession_get_transport(s),
      },
      .common.remote_addr = {
         .sin       = &s->session->sin,
         .transport = mansession_get_transport(s),
      },
      .common.session_id = session_id,

      .request_type      = request_type,
   };

   snprintf(session_id, sizeof(session_id), "%p", s->session);
   snprintf(request_type, sizeof(request_type), "Action: %s", action);

   ast_security_event_report(AST_SEC_EVT(&req_not_allowed));
}
static void report_session_limit ( const struct mansession s) [static]

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

{
   struct sockaddr_in sin_local;
   char session_id[32];
   struct ast_security_event_session_limit session_limit = {
      .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT,
      .common.version    = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION,
      .common.service    = "AMI",
      .common.account_id = s->session->username,
      .common.session_tv = &s->session->sessionstart_tv,
      .common.local_addr = {
         .sin       = mansession_encode_sin_local(s, &sin_local),
         .transport = mansession_get_transport(s),
      },
      .common.remote_addr = {
         .sin       = &s->session->sin,
         .transport = mansession_get_transport(s),
      },
      .common.session_id = session_id,
   };

   snprintf(session_id, sizeof(session_id), "%p", s->session);

   ast_security_event_report(AST_SEC_EVT(&session_limit));
}
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 1955 of file manager.c.

References ast_careful_fwrite(), EVENT_FLAG_HOOKRESPONSE, f, mansession_session::f, mansession::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().

{
   int res;
   FILE *f = s->f ? s->f : s->session->f;
   int fd = s->f ? s->fd : s->session->fd;

   /* It's a result from one of the hook's action invocation */
   if (s->hook) {
      /*
       * to send responses, we're using the same function
       * as for receiving events. We call the event "HookResponse"
       */
      s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string);
      return 0;
   }
       
   if ((res = ast_careful_fwrite(f, fd, string, strlen(string), s->session->writetimeout))) {
      s->write_error = 1;
   }

   return res;
}
static void session_destroy ( struct mansession_session s) [static]
static void session_destructor ( void *  obj) [static]

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

{
   struct mansession_session *session = obj;
   struct eventqent *eqe = session->last_ev;
   struct ast_datastore *datastore;

   /* Get rid of each of the data stores on the session */
   while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) {
      /* Free the data store */
      ast_datastore_free(datastore);
   }

   if (session->f != NULL) {
      fclose(session->f);
   }
   if (eqe) {
      ast_atomic_fetchadd_int(&eqe->usecount, -1);
   }

   if (session->whitefilters) {
      ao2_t_callback(session->whitefilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all white filters");
      ao2_t_ref(session->whitefilters, -1 , "decrement ref for white container, should be last one");
   }

   if (session->blackfilters) {
      ao2_t_callback(session->blackfilters, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL, "unlink all black filters");
      ao2_t_ref(session->blackfilters, -1 , "decrement ref for black container, should be last one");
   }
}
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 4849 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(), ast_frame::data, mansession_session::datastores, do_message(), errno, ast_tcptls_session_instance::f, mansession_session::f, mansession::f, ast_tcptls_session_instance::fd, mansession_session::fd, mansession::fd, ast_frame::flags, grab_last(), mansession_session::last_ev, mansession::lock, LOG_ERROR, LOG_WARNING, manager_displayconnects(), ast_tcptls_session_instance::remote_address, mansession::session, session_destroy(), mansession_session::sin, mansession::tcptls_session, unauth_sessions, mansession_session::username, and mansession::write_error.

{
   struct ast_tcptls_session_instance *ser = data;
   struct mansession_session *session;
   struct mansession s = {
      .tcptls_session = data,
   };
   int flags;
   int res;
   struct sockaddr_in ser_remote_address_tmp;
   struct protoent *p;

   if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
      fclose(ser->f);
      ast_atomic_fetchadd_int(&unauth_sessions, -1);
      goto done;
   }

   ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
   session = build_mansession(ser_remote_address_tmp);

   if (session == NULL) {
      fclose(ser->f);
      ast_atomic_fetchadd_int(&unauth_sessions, -1);
      goto done;
   }

   /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
    * This is necessary to prevent delays (caused by buffering) as we
    * write to the socket in bits and peices. */
   p = getprotobyname("tcp");
   if (p) {
      int arg = 1;
      if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
         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));
      }
   } else {
      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");
   }

   flags = fcntl(ser->fd, F_GETFL);
   if (!block_sockets) { /* make sure socket is non-blocking */
      flags |= O_NONBLOCK;
   } else {
      flags &= ~O_NONBLOCK;
   }
   fcntl(ser->fd, F_SETFL, flags);

   ao2_lock(session);
   /* Hook to the tail of the event queue */
   session->last_ev = grab_last();

   ast_mutex_init(&s.lock);

   /* these fields duplicate those in the 'ser' structure */
   session->fd = s.fd = ser->fd;
   session->f = s.f = ser->f;
   session->sin = ser_remote_address_tmp;
   s.session = session;

   AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);

   if(time(&session->authstart) == -1) {
      ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
      ast_atomic_fetchadd_int(&unauth_sessions, -1);
      ao2_unlock(session);
      session_destroy(session);
      goto done;
   }
   ao2_unlock(session);

   astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION);   /* welcome prompt */
   for (;;) {
      if ((res = do_message(&s)) < 0 || s.write_error) {
         break;
      }
   }
   /* session is over, explain why and terminate */
   if (session->authenticated) {
      if (manager_displayconnects(session)) {
         ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
      }
   } else {
      ast_atomic_fetchadd_int(&unauth_sessions, -1);
      if (displayconnects) {
         ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
      }
   }

   session_destroy(session);

   ast_mutex_destroy(&s.lock);
done:
   ao2_ref(ser, -1);
   ser = NULL;
   return NULL;
}
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 2092 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().

{
   int maskint = strings_to_mask(eventmask);

   ao2_lock(s->session);
   if (maskint >= 0) {
      s->session->send_events = maskint;
   }
   ao2_unlock(s->session);

   return maskint;
}
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 1247 of file manager.c.

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

Referenced by set_eventmask().

{
   const char *p;

   if (ast_strlen_zero(string)) {
      return -1;
   }

   for (p = string; *p; p++) {
      if (*p < '0' || *p > '9') {
         break;
      }
   }
   if (!*p) { /* all digits */
      return atoi(string);
   }
   if (ast_false(string)) {
      return 0;
   }
   if (ast_true(string)) { /* all permissions */
      int x, ret = 0;
      for (x = 0; x < ARRAY_LEN(perms); x++) {
         ret |= perms[x].num;
      }
      return ret;
   }
   return get_perm(string);
}
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 1278 of file manager.c.

References ao2_ref, ast_log(), and LOG_DEBUG.

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

{
   int refcount = ao2_ref(s, -1);
        if (manager_debug) {
      ast_log(LOG_DEBUG, "Mansession: %p refcount now %d\n", s, refcount - 1);
   }
   return s;
}
static int whitefilter_cmp_fn ( void *  obj,
void *  arg,
void *  data,
int  flags 
) [static]

Definition at line 4183 of file manager.c.

References CMP_MATCH, CMP_STOP, and ast_frame::data.

Referenced by match_filter().

{
   regex_t *regex_filter = obj;
   const char *eventdata = arg;
   int *result = data;

   if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
      *result = 1;
      return (CMP_MATCH | CMP_STOP);
   }

   return 0;
}

Variable Documentation

struct actions actions [static]
struct all_events all_events [static]
int allowmultiplelogin = 1 [static]

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

Referenced by astman_append().

int authlimit [static]

Definition at line 899 of file manager.c.

int authtimeout [static]

Definition at line 898 of file manager.c.

int block_sockets [static]

Definition at line 905 of file manager.c.

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

int broken_events_action [static]

Definition at line 894 of file manager.c.

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

Referenced by check_blacklist().

const int DEFAULT_AUTHLIMIT = 50 [static]

Default setting for authlimit

Definition at line 887 of file manager.c.

Referenced by __init_manager(), and reload_config().

const int DEFAULT_AUTHTIMEOUT = 30 [static]

Default setting for authtimeout

Definition at line 886 of file manager.c.

Referenced by __init_manager(), and reload_config().

const int DEFAULT_BLOCKSOCKETS = 0 [static]

Default setting for block-sockets

Definition at line 881 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_BROKENEVENTSACTION = 0 [static]

Default setting for brokeneventsaction

Definition at line 885 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_DISPLAYCONNECTS = 1 [static]

Default setting for displaying manager connections

Definition at line 882 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_ENABLED = 0 [static]

Default setting for manager to be enabled

Definition at line 879 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_HTTPTIMEOUT = 60 [static]

Default manager http timeout

Definition at line 884 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_MANAGERDEBUG = 0 [static]

Default setting for manager debug

Definition at line 888 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_TIMESTAMPEVENTS = 0 [static]

Default setting for timestampevents

Definition at line 883 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_WEBENABLED = 0 [static]

Default setting for the web interface to be enabled

Definition at line 880 of file manager.c.

Referenced by __init_manager().

int displayconnects [static]

Definition at line 890 of file manager.c.

Referenced by __init_manager().

char global_realm[MAXHOSTNAMELEN] [static]

Default realm

Definition at line 903 of file manager.c.

Referenced by __init_manager(), and auth_http_callback().

int httptimeout [static]

Definition at line 893 of file manager.c.

char* manager_channelvars [static]

Definition at line 900 of file manager.c.

int manager_debug = 0 [static]

enable some debugging code in the manager

Definition at line 897 of file manager.c.

int manager_enabled = 0 [static]

Definition at line 895 of file manager.c.

Referenced by check_manager_enabled().

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

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

Referenced by append_channel_vars().

struct manager_hooks manager_hooks [static]
struct ao2_container* sessions = NULL [static]

Definition at line 1009 of file manager.c.

int timestampevents [static]

Definition at line 892 of file manager.c.

int unauth_sessions = 0 [static]

Definition at line 906 of file manager.c.

Referenced by action_login(), and session_do().

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

Definition at line 1986 of file manager.c.

Referenced by action_userevent().

struct users users [static]
int webmanager_enabled = 0 [static]

Definition at line 896 of file manager.c.

const char* words[AST_MAX_CMD_LEN]

Definition at line 921 of file manager.c.