Sun Oct 16 2011 08:43:11

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)
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 int action_events (struct mansession *s, const struct message *m)
static int action_extensionstate (struct mansession *s, const struct message *m)
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,...)
const char * astman_get_header (const struct message *m, char *var)
 Get header from mananger transaction.
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 ()
 Check if AMI is enabled.
static int check_manager_session_inuse (const char *name)
int check_webmanager_enabled ()
 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 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_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
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 1897 of file manager.c.

Referenced by astman_append().

#define DEFAULT_REALM   "asterisk"

Definition at line 887 of file manager.c.

Referenced by reload_config(), and __init_manager().

#define GET_HEADER_FIRST_MATCH   0

Definition at line 1718 of file manager.c.

Referenced by astman_get_header().

#define GET_HEADER_LAST_MATCH   1

Definition at line 1719 of file manager.c.

Referenced by __astman_get_header().

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 1720 of file manager.c.

Referenced by __astman_get_header(), and process_message().

#define MANAGER_EVENT_BUF_INITSIZE   256

Definition at line 4884 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 905 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 1938 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 821 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 4886 of file manager.c.

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

{
   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]

Definition at line 1721 of file manager.c.

References message::hdrcount, message::headers, value, ast_skip_blanks(), GET_HEADER_SKIP_EMPTY, ast_strlen_zero(), and GET_HEADER_LAST_MATCH.

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

{
static void __init_manager_event_buf ( void  ) [static]

Definition at line 4883 of file manager.c.

{
static void __init_manager_event_funcbuf ( void  ) [static]

Definition at line 4860 of file manager.c.

{
static void __init_userevent_buf ( void  ) [static]

Definition at line 1894 of file manager.c.

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

Definition at line 3649 of file manager.c.

References astman_get_header(), AST_AOC_MULT_ONE, AST_AOC_TOTAL, AST_AOC_BILLING_NA, ast_strlen_zero(), astman_send_error(), ast_channel_get_by_name(), ast_channel_get_by_name_prefix(), AST_AOC_E, AST_AOC_D, AST_AOC_CHARGE_NA, AST_AOC_CHARGE_FREE, AST_AOC_CHARGE_CURRENCY, AST_AOC_CHARGE_UNIT, AST_AOC_MULT_ONETHOUSANDTH, AST_AOC_MULT_ONEHUNDREDTH, AST_AOC_MULT_ONETENTH, AST_AOC_MULT_TEN, AST_AOC_MULT_HUNDRED, AST_AOC_MULT_THOUSAND, ast_aoc_create(), AST_AOC_SUBTOTAL, AST_AOC_BILLING_NORMAL, AST_AOC_BILLING_REVERSE_CHARGE, AST_AOC_BILLING_CREDIT_CARD, AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL, AST_AOC_BILLING_CALL_FWD_BUSY, AST_AOC_BILLING_CALL_FWD_NO_REPLY, AST_AOC_BILLING_CALL_DEFLECTION, AST_AOC_BILLING_CALL_TRANSFER, ast_aoc_set_association_id(), ast_aoc_set_association_number(), ast_aoc_set_currency_info(), aocmessage_get_unit_entry(), ast_aoc_add_unit_entry(), ast_aoc_unit_entry::valid_amount, ast_aoc_unit_entry::amount, ast_aoc_unit_entry::valid_type, ast_aoc_unit_entry::type, ast_aoc_set_billing_id(), ast_aoc_set_total_type(), ast_aoc_encode(), ast_indicate_data(), AST_CONTROL_AOC, astman_send_ack(), ast_aoc_destroy_decoded(), ast_aoc_destroy_encoded(), and ast_channel_unref.

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

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

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

References astman_get_header(), ast_strlen_zero(), mansession::session, mansession_session::challenge, ast_random(), mansession_lock(), astman_start_ack(), astman_append(), mansession_unlock(), and astman_send_error().

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

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

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

References astman_get_header(), ast_strlen_zero(), astman_append(), 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(), check_cdr_enabled(), and check_webmanager_enabled().

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

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

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

References astman_get_header(), ast_strlen_zero(), ast_localtime(), ast_startuptime, ast_strftime(), ast_lastreloadtime, astman_append(), and ast_active_channels().

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

References astman_get_header(), ast_str_alloca, ast_str_set(), ast_config_AST_CONFIG_DIR, ast_str_append(), ast_str_buffer(), AST_FILE_MODE, 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 int action_events ( struct mansession s,
const struct message m 
) [static]

Definition at line 2898 of file manager.c.

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

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

References exten, astman_get_header(), context, status, ast_strlen_zero(), astman_send_error(), ast_extension_state(), ast_get_hint(), astman_start_ack(), and astman_append().

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 int action_getconfig ( struct mansession s,
const struct message m 
) [static]

Definition at line 2371 of file manager.c.

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

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

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

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;
   char *buf = NULL;
   unsigned int buf_len = 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;
   }

   buf_len = 512;
   buf = alloca(buf_len);

   astman_start_ack(s, m);
   astman_append(s, "JSON: {");
   while ((category = ast_category_browse(cfg, category))) {
      int comma2 = 0;
      if (buf_len < 2 * strlen(category) + 1) {
         buf_len *= 2;
         buf = alloca(buf_len);
      }
      json_escape(buf, category);
      astman_append(s, "%s\"%s\":[", comma1 ? "," : "", buf);
      if (!comma1) {
         comma1 = 1;
      }
      for (v = ast_variable_browse(cfg, category); v; v = v->next) {
         if (comma2) {
            astman_append(s, ",");
         }
         if (buf_len < 2 * strlen(v->name) + 1) {
            buf_len *= 2;
            buf = alloca(buf_len);
         }
         json_escape(buf, v->name);
         astman_append(s, "\"%s", buf);
         if (buf_len < 2 * strlen(v->value) + 1) {
            buf_len *= 2;
            buf = alloca(buf_len);
         }
         json_escape(buf, v->value);
         astman_append(s, "%s\"", buf);
         if (!comma2) {
            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 3073 of file manager.c.

References astman_get_header(), ast_strlen_zero(), astman_send_error(), ast_channel_get_by_name(), ast_dummy_channel_alloc(), ast_func_read(), ast_channel_release(), ast_log(), LOG_ERROR, pbx_retrieve_variable(), ast_channel_unref, astman_start_ack(), astman_append(), 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;
      }
   }

   if (varname[strlen(varname) - 1] == ')') {
      if (!c) {
         c = ast_dummy_channel_alloc();
         if (c) {
            ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
            c = ast_channel_release(c);
         } 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 2997 of file manager.c.

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

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

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

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]
Note:
The actionlock is read-locked by the caller of this function

Definition at line 2881 of file manager.c.

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

Referenced by __init_manager().

{
   struct manager_action *cur;
   struct ast_str *temp = ast_str_alloca(BUFSIZ); /* XXX very large ? */

   astman_start_ack(s, m);
   AST_RWLIST_TRAVERSE(&actions, cur, list) {
      if (s->session->writeperm & cur->authority || cur->authority == 0) {
         astman_append(s, "%s: %s (Priv: %s)\r\n",
            cur->action, cur->synopsis, authority_to_str(cur->authority, &temp));
      }
   }
   astman_append(s, "\r\n");

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

Definition at line 2948 of file manager.c.

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

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

References mailbox, astman_get_header(), ast_strlen_zero(), astman_send_error(), ast_app_inboxcount2(), astman_start_ack(), and astman_append().

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

References mailbox, astman_get_header(), ast_strlen_zero(), astman_send_error(), ast_app_has_voicemail(), astman_start_ack(), and astman_append().

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

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

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) {
         res = -1;
      } else {
         if (!ast_strlen_zero(id))
            snprintf(fast->idtext, sizeof(fast->idtext), "ActionID: %s", id);
         ast_copy_string(fast->tech, tech, sizeof(fast->tech));
         ast_copy_string(fast->data, data, sizeof(fast->data));
         ast_copy_string(fast->app, app, sizeof(fast->app));
         ast_copy_string(fast->appdata, appdata, sizeof(fast->appdata));
         if (l) {
            ast_copy_string(fast->cid_num, l, sizeof(fast->cid_num));
         }
         if (n) {
            ast_copy_string(fast->cid_name, n, sizeof(fast->cid_name));
         }
         fast->vars = vars;
         ast_copy_string(fast->context, context, sizeof(fast->context));
         ast_copy_string(fast->exten, exten, sizeof(fast->exten));
         ast_copy_string(fast->account, account, sizeof(fast->account));
         fast->format = format;
         fast->timeout = to;
         fast->priority = pi;
         if (ast_pthread_create_detached(&th, NULL, fast_originate, 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 2353 of file manager.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

References astman_get_header(), ast_str_thread_get(), userevent_buf, ast_str_reset(), message::hdrcount, message::headers, ast_str_append(), astman_send_ack(), manager_event, EVENT_FLAG_USER, and ast_str_buffer().

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

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

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

References str, ast_str_alloca, ast_str_set(), astman_get_header(), ast_str_buffer(), ast_strlen_zero(), ast_aoc_unit_entry::amount, ast_aoc_unit_entry::valid_amount, ast_aoc_unit_entry::type, 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]
static int append_event ( const char *  str,
int  category 
) [static]

Definition at line 4836 of file manager.c.

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

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

References mansession::session, message::headers, message::hdrcount, ast_strdupa, astman_get_header(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, manager_action::action, mansession::hook, mansession::f, manager_action::func, and AST_RWLIST_UNLOCK.

{
   const char *action;
   int ret = 0;
   struct manager_action *tmp;
   struct mansession s = {.session = NULL, };
   struct message m = { 0 };
   char header_buf[1025] = { '\0' };
   const char *src = msg;
   int x = 0;
   int curlen;

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

   /* convert msg string to message struct */
   curlen = strlen(msg);
   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 copy empty lines */
      if (x) {
         memmove(header_buf, src, x);  /*... but trim \r\n */
         header_buf[x] = '\0';      /* terminate the string */
         m.headers[m.hdrcount++] = ast_strdupa(header_buf);
      }
      x += cr;
      curlen -= x;      /* remaining size */
      src += x;      /* update pointer */
      x = -1;        /* reset loop */
   }

   action = astman_get_header(&m,"Action");
   if (action && strcasecmp(action,"login")) {

      AST_RWLIST_RDLOCK(&actions);
      AST_RWLIST_TRAVERSE(&actions, tmp, list) {
         if (strcasecmp(action, tmp->action))
            continue;
         /*
         * 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*/
         ret = tmp->func(&s, &m);
         break;
      }
      AST_RWLIST_UNLOCK(&actions);
   }
   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 1169 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 5044 of file manager.c.

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

Referenced by load_module().

{
   struct manager_action *cur = NULL;
#ifdef AST_XML_DOCS
   char *tmpxml;
#endif

   if (!(cur = ast_calloc_with_stringfields(1, struct manager_action, 128))) {
      return -1;
   }

   cur->action = action;
   cur->authority = auth;
   cur->func = func;
#ifdef AST_XML_DOCS
   if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
      tmpxml = ast_xmldoc_build_synopsis("manager", action);
      ast_string_field_set(cur, synopsis, tmpxml);
      ast_free(tmpxml);

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

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

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

      tmpxml = ast_xmldoc_build_arguments("manager", action);
      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)) {
      ast_free(cur);
      return -1;
   }

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

References AST_RWLIST_WRLOCK, AST_RWLIST_INSERT_TAIL, and AST_RWLIST_UNLOCK.

static int ast_manager_register_struct ( struct manager_action act) [static]

Definition at line 5007 of file manager.c.

References eventqent::tv, AST_RWLIST_TIMEDWRLOCK, ast_log(), LOG_ERROR, AST_RWLIST_TRAVERSE, manager_action::action, LOG_WARNING, AST_RWLIST_UNLOCK, AST_RWLIST_INSERT_AFTER, AST_RWLIST_INSERT_HEAD, and ast_verb.

Referenced by ast_manager_register2().

{
   struct manager_action *cur, *prev = NULL;
   struct timespec tv = { 5, };

   if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) {
      ast_log(LOG_ERROR, "Could not obtain lock on manager list\n");
      return -1;
   }
   AST_RWLIST_TRAVERSE(&actions, cur, list) {
      int 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;
      }
   }

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

References eventqent::tv, AST_RWLIST_TIMEDWRLOCK, ast_log(), LOG_ERROR, AST_RWLIST_TRAVERSE_SAFE_BEGIN, manager_action::action, AST_RWLIST_REMOVE_CURRENT, ast_string_field_free_memory, ast_free, ast_verb, AST_RWLIST_TRAVERSE_SAFE_END, and AST_RWLIST_UNLOCK.

Referenced by unload_module(), and __unload_module().

{
   struct manager_action *cur;
   struct timespec tv = { 5, };

   if (AST_RWLIST_TIMEDWRLOCK(&actions, &tv)) {
      ast_log(LOG_ERROR, "Could not obtain lock on manager list\n");
      return -1;
   }
   AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) {
      if (!strcasecmp(action, cur->action)) {
         AST_RWLIST_REMOVE_CURRENT(list);
         ast_string_field_free_memory(cur);
         ast_free(cur);
         ast_verb(2, "Manager unregistered action %s\n", action);
         break;
      }
   }
   AST_RWLIST_TRAVERSE_SAFE_END;
   AST_RWLIST_UNLOCK(&actions);

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

References AST_RWLIST_WRLOCK, AST_RWLIST_REMOVE, and AST_RWLIST_UNLOCK.

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

utility functions for creating AMI replies

Definition at line 1902 of file manager.c.

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

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

{
   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");
   }
}
const char* astman_get_header ( const struct message m,
char *  var 
)

Get header from mananger transaction.

Definition at line 1749 of file manager.c.

References __astman_get_header(), and GET_HEADER_FIRST_MATCH.

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

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

Get a linked list of the Variable: headers.

Definition at line 1755 of file manager.c.

References AST_DECLARE_APP_ARGS, args, AST_APP_ARG, message::hdrcount, parse(), var, message::headers, ast_strdupa, AST_STANDARD_APP_ARGS, strsep(), ast_strlen_zero(), and ast_variable_new().

Referenced by manager_sipnotify(), and action_originate().

{
   int varlen, x, y;
   struct ast_variable *head = NULL, *cur;

   AST_DECLARE_APP_ARGS(args,
      AST_APP_ARG(vars)[32];
   );

   varlen = strlen("Variable: ");

   for (x = 0; x < m->hdrcount; x++) {
      char *parse, *var, *val;

      if (strncasecmp("Variable: ", m->headers[x], varlen)) {
         continue;
      }
      parse = ast_strdupa(m->headers[x] + varlen);

      AST_STANDARD_APP_ARGS(args, parse);
      if (!args.argc) {
         continue;
      }
      for (y = 0; y < args.argc; y++) {
         if (!args.vars[y]) {
            continue;
         }
         var = val = ast_strdupa(args.vars[y]);
         strsep(&val, "=");
         if (!val || ast_strlen_zero(var)) {
            continue;
         }
         cur = ast_variable_new(var, val, "");
         cur->next = head;
         head = cur;
      }
   }

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

Send error in manager transaction.

Definition at line 1964 of file manager.c.

References astman_send_response_full().

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

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

References astman_send_response_full().

Referenced by action_waitevent(), and action_logoff().

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

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

Referenced by astman_send_response(), astman_send_error(), astman_send_ack(), astman_start_ack(), and astman_send_listack().

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

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

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

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

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

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

References ast_frame::data, CMP_MATCH, and CMP_STOP.

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

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

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

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

References MAX_BLACKLIST_CMD_LEN, ast_strdupa, strsep(), ast_strip(), ast_strlen_zero(), ARRAY_LEN, command_blacklist, match(), 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 1053 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 1329 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 1058 of file manager.c.

Referenced by handle_show_settings(), and action_coresettings().

static int do_message ( struct mansession s) [static]

Definition at line 4660 of file manager.c.

References mansession::session, mansession_session::inbuf, process_events(), get_input(), mansession_session::authenticated, ast_log(), LOG_ERROR, errno, mansession_session::authstart, ast_verb, ast_inet_ntoa(), mansession_session::sin, ast_strlen_zero(), process_message(), message::hdrcount, AST_MAX_MANHEADERS, message::headers, and ast_strdupa.

Referenced by session_do().

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

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

            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);
               }
               return -1;
            }
         }
         continue;
      } else if (res > 0) {
         if (ast_strlen_zero(header_buf)) {
            return process_message(s, &m) ? -1 : 0;
         } else if (m.hdrcount < (AST_MAX_MANHEADERS - 1)) {
            m.headers[m.hdrcount++] = ast_strdupa(header_buf);
         }
      } else {
         return res;
      }
   }
}
static void event_filter_destructor ( void *  obj) [static]

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

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

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

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

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

References AST_RWLIST_TRAVERSE, ast_manager_user::username, and user.

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

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

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

Referenced by strings_to_mask(), and __init_manager().

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

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

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

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

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

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

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

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

References ast_str_alloca, CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::word, ast_cli_args::pos, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, ast_manager_user::username, ast_cli_args::n, ast_strdup, AST_RWLIST_UNLOCK, ast_cli_args::argc, CLI_SHOWUSAGE, get_manager_by_name_locked(), ast_cli_args::argv, ast_cli(), ast_cli_args::fd, CLI_SUCCESS, ast_manager_user::secret, ast_manager_user::ha, authority_to_str(), ast_manager_user::readperm, ast_manager_user::writeperm, and ast_manager_user::displayconnects.

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

References CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_cli_args::argc, CLI_SHOWUSAGE, AST_RWLIST_RDLOCK, AST_RWLIST_EMPTY, ast_cli(), ast_cli_args::fd, AST_RWLIST_UNLOCK, CLI_SUCCESS, AST_RWLIST_TRAVERSE, 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 1377 of file manager.c.

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

{
   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, ""));
#ifdef AST_XML_DOCS
            }
#endif
         }
      }
   }
   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 1587 of file manager.c.

References CLI_INIT, ast_cli_entry::command, ast_cli_entry::usage, CLI_GENERATE, ast_str_alloca, ast_cli(), ast_cli_args::fd, HSMC_FORMAT, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, manager_action::action, authority_to_str(), manager_action::authority, manager_action::synopsis, AST_RWLIST_UNLOCK, and CLI_SUCCESS.

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

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

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

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

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

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

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

Referenced by action_getconfigjson().

{
   for (; *in; in++) {
      if (*in == '\\' || *in == '\"') {
         *out++ = '\\';
      }
      *out++ = *in;
   }
   *out = '\0';
}
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 1363 of file manager.c.

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

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

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

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

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

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

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

References ast_get_hint(), manager_event, and EVENT_FLAG_CALL.

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

References str, mansession_session::username, and CMP_MATCH.

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

References ast_mutex_lock, and mansession::lock.

Referenced by action_challenge(), and process_message().

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

Unlock the 'mansession' structure.

Definition at line 1991 of file manager.c.

References ast_mutex_unlock, and mansession::lock.

Referenced by action_challenge(), and process_message().

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

Definition at line 4118 of file manager.c.

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

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

References ao2_lock, mansession::session, mansession_session::f, mansession_session::last_ev, advance_event(), mansession_session::authenticated, mansession_session::readperm, eventqent::category, mansession_session::send_events, match_filter(), send_string(), and ao2_unlock.

Referenced by process_message(), and do_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 4474 of file manager.c.

References astman_get_header(), ast_copy_string(), __astman_get_header(), GET_HEADER_SKIP_EMPTY, ast_strlen_zero(), report_req_bad_format(), mansession_lock(), astman_send_error(), mansession_unlock(), mansession::session, mansession_session::authenticated, report_req_not_allowed(), check_manager_session_inuse(), report_session_limit(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, manager_action::action, mansession_session::writeperm, manager_action::authority, manager_action::func, AST_RWLIST_UNLOCK, ast_debug, and process_events().

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

{
   char action[80] = "";
   int ret = 0;
   struct manager_action *tmp;
   const char *user = astman_get_header(m, "Username");
   int (*call_func)(struct mansession *s, const struct message *m) = NULL;

   ast_copy_string(action, __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY), sizeof(action));

   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 && user &&
      (!strcasecmp(action, "Login") || !strcasecmp(action, "Challenge"))) {
      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;
      }
   }

   AST_RWLIST_RDLOCK(&actions);
   AST_RWLIST_TRAVERSE(&actions, tmp, list) {
      if (strcasecmp(action, tmp->action)) {
         continue;
      }
      if (s->session->writeperm & tmp->authority || tmp->authority == 0) {
         call_func = tmp->func;
      }
      break;
   }
   AST_RWLIST_UNLOCK(&actions);

   if (tmp) {
      if (call_func) {
         /* Call our AMI function after we unlock our actions lists */
         ast_debug(1, "Running action '%s'\n", tmp->action);
         ret = call_func(s, m);
      } else {
         /* If we found our action but don't have a function pointer, access
          * was denied, so bail out.
          */
         report_req_not_allowed(s, action);
         mansession_lock(s);
         astman_send_error(s, m, "Permission denied");
         mansession_unlock(s);
      }
   } else {
      char buf[512];
      if (!tmp) {
         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 1087 of file manager.c.

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

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

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

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

References ast_security_event_successful_auth::common, ast_security_event_common::event_type, AST_SECURITY_EVENT_SUCCESSFUL_AUTH, AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION, mansession::session, mansession_session::username, mansession_session::sessionstart_tv, mansession_encode_sin_local(), mansession_get_transport(), mansession_session::sin, ast_security_event_report(), and AST_SEC_EVT.

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

References ast_security_event_failed_acl::common, ast_security_event_common::event_type, AST_SECURITY_EVENT_FAILED_ACL, AST_SECURITY_EVENT_FAILED_ACL_VERSION, mansession::session, mansession_session::sessionstart_tv, mansession_encode_sin_local(), mansession_get_transport(), mansession_session::sin, ast_security_event_report(), and AST_SEC_EVT.

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

References ast_security_event_chal_resp_failed::common, ast_security_event_common::event_type, AST_SECURITY_EVENT_CHAL_RESP_FAILED, AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION, mansession::session, mansession_session::username, mansession_session::sessionstart_tv, mansession_encode_sin_local(), mansession_get_transport(), mansession_session::sin, mansession_session::challenge, ast_security_event_chal_resp_failed::response, ast_security_event_chal_resp_failed::expected_response, ast_security_event_report(), and AST_SEC_EVT.

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

References ast_security_event_inval_password::common, ast_security_event_common::event_type, AST_SECURITY_EVENT_INVAL_PASSWORD, AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION, mansession::session, mansession_session::sessionstart_tv, mansession_encode_sin_local(), mansession_get_transport(), mansession_session::sin, ast_security_event_report(), and AST_SEC_EVT.

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

References ast_security_event_inval_acct_id::common, ast_security_event_common::event_type, AST_SECURITY_EVENT_INVAL_ACCT_ID, AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION, mansession::session, mansession_session::sessionstart_tv, mansession_encode_sin_local(), mansession_get_transport(), mansession_session::sin, ast_security_event_report(), and AST_SEC_EVT.

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

References ast_security_event_req_bad_format::common, ast_security_event_common::event_type, AST_SECURITY_EVENT_REQ_BAD_FORMAT, AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION, mansession::session, mansession_session::username, mansession_session::sessionstart_tv, mansession_encode_sin_local(), mansession_get_transport(), mansession_session::sin, ast_security_event_req_bad_format::request_type, ast_security_event_report(), and AST_SEC_EVT.

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

References ast_security_event_req_not_allowed::common, ast_security_event_common::event_type, AST_SECURITY_EVENT_REQ_NOT_ALLOWED, AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION, mansession::session, mansession_session::username, mansession_session::sessionstart_tv, mansession_encode_sin_local(), mansession_get_transport(), mansession_session::sin, ast_security_event_req_not_allowed::request_type, ast_security_event_report(), and AST_SEC_EVT.

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

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

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

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

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

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

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

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

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

References strings_to_mask(), ao2_lock, mansession::session, mansession_session::send_events, and ao2_unlock.

Referenced by authenticate(), and action_events().

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

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

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

References ao2_ref, manager_debug, ast_log(), and LOG_DEBUG.

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

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

References ast_frame::data, CMP_MATCH, and CMP_STOP.

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

Referenced by astman_append().

int authlimit [static]

Definition at line 884 of file manager.c.

int authtimeout [static]

Definition at line 883 of file manager.c.

int block_sockets [static]

Definition at line 890 of file manager.c.

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

int broken_events_action [static]

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

Referenced by reload_config(), and __init_manager().

const int DEFAULT_AUTHTIMEOUT = 30 [static]

Default setting for authtimeout

Definition at line 873 of file manager.c.

Referenced by reload_config(), and __init_manager().

const int DEFAULT_BLOCKSOCKETS = 0 [static]

Default setting for block-sockets

Definition at line 868 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_BROKENEVENTSACTION = 0 [static]

Default setting for brokeneventsaction

Definition at line 872 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_DISPLAYCONNECTS = 1 [static]

Default setting for displaying manager connections

Definition at line 869 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_ENABLED = 0 [static]

Default setting for manager to be enabled

Definition at line 866 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_HTTPTIMEOUT = 60 [static]

Default manager http timeout

Definition at line 871 of file manager.c.

Referenced by __init_manager().

const int DEFAULT_TIMESTAMPEVENTS = 0 [static]

Default setting for timestampevents

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

Referenced by __init_manager().

int displayconnects [static]

Definition at line 876 of file manager.c.

Referenced by __init_manager().

char global_realm[MAXHOSTNAMELEN] [static]

Default realm

Definition at line 888 of file manager.c.

Referenced by auth_http_callback(), and __init_manager().

int httptimeout [static]

Definition at line 879 of file manager.c.

char* manager_channelvars [static]

Definition at line 885 of file manager.c.

int manager_debug [static]

enable some debugging code in the manager

Definition at line 893 of file manager.c.

Referenced by unref_mansession(), handle_mandebug(), __ast_manager_event_multichan(), handle_manager_show_settings(), and __init_manager().

int manager_enabled = 0 [static]

Definition at line 881 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 4883 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 4860 of file manager.c.

Referenced by append_channel_vars().

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

Definition at line 995 of file manager.c.

int timestampevents [static]

Definition at line 878 of file manager.c.

int unauth_sessions = 0 [static]

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

Referenced by action_userevent().

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

Definition at line 882 of file manager.c.

const char* words[AST_MAX_CMD_LEN]

Definition at line 907 of file manager.c.