Asterisk - The Open Source Telephony Project GIT-master-5467495
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | Functions | Variables
AMI functions

Data Structures

struct  actions
 list of actions registered More...
 
struct  ast_manager_user
 user descriptor, as read from the config file. More...
 
struct  event_filter_entry
 
struct  eventqent
 An AMI event message. More...
 
struct  fast_originate_helper
 helper function for originate More...
 
struct  manager_hooks
 list of hooks registered More...
 
struct  mansession
 In case you didn't read that giant block of text above the mansession_session struct, the mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data. More...
 
struct  mansession_session
 
struct  originate_permissions_entry
 
struct  permalias
 
struct  users
 list of users found in the config file More...
 

Macros

#define any_manager_listeners(sessions)    ((sessions && ao2_container_count(sessions)) || !AST_RWLIST_EMPTY(&manager_hooks))
 
#define ASTMAN_APPEND_BUF_INITSIZE   256
 initial allocated size for the astman_append_buf and astman_send_*_va
 
#define DEFAULT_REALM   "asterisk"
 
#define EVENT_FLAG_SHUTDOWN   -1
 Fake event class used to end sessions at shutdown.
 
#define GET_HEADER_FIRST_MATCH   0
 
#define GET_HEADER_LAST_MATCH   1
 
#define GET_HEADER_SKIP_EMPTY   2
 
#define MANAGER_EVENT_BUF_INITSIZE   256
 Initial size of the manager event message buffer.
 
#define manager_event_sessions(sessions, category, event, contents, ...)    __manager_event_sessions(sessions, category, event, 0, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, contents , ## __VA_ARGS__)
 
#define MAX_AUTH_PERM_STRING   150
 
#define MAX_BLACKLIST_CMD_LEN   2
 Descriptor for a manager session, either on the AMI socket or over HTTP.
 
#define MAX_VARS   128
 
#define MGR_SHOW_TERMINAL_WIDTH   80
 
#define MSG_MOREDATA   ((char *)astman_send_response)
 

Enumerations

enum  add_filter_result { FILTER_SUCCESS = 0 , FILTER_ALLOC_FAILED , FILTER_COMPILE_FAIL , FILTER_FORMAT_ERROR }
 
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 , FAILURE_TEMPLATE
}
 
enum  event_filter_match_type {
  FILTER_MATCH_REGEX = 0 , FILTER_MATCH_EXACT , FILTER_MATCH_STARTS_WITH , FILTER_MATCH_ENDS_WITH ,
  FILTER_MATCH_CONTAINS , FILTER_MATCH_NONE
}
 
enum  mansession_message_parsing { MESSAGE_OKAY , MESSAGE_LINE_TOO_LONG }
 

Functions

int __ast_manager_event_multichan (int category, const char *event, int chancount, struct ast_channel **chans, const char *file, int line, const char *func, const char *fmt,...)
 
static const char * __astman_get_header (const struct message *m, char *var, int mode)
 Return a matching header value.
 
static int __manager_event_sessions (struct ao2_container *sessions, int category, const char *event, int chancount, struct ast_channel **chans, const char *file, int line, const char *func, const char *fmt,...)
 
static int __manager_event_sessions_va (struct ao2_container *sessions, int category, const char *event_name, int chancount, struct ast_channel **chans, const char *file, int line, const char *func, const char *fmt, va_list ap)
 
static void acl_change_stasis_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void acl_change_stasis_subscribe (void)
 
static void acl_change_stasis_unsubscribe (void)
 
static struct ast_aoc_decodedaction_aoc_de_message (struct mansession *s, const struct message *m)
 
static struct ast_aoc_decodedaction_aoc_s_message (struct mansession *s, const struct message *m)
 
static int action_aoc_s_submessage (struct mansession *s, const struct message *m, struct ast_aoc_decoded *decoded)
 
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_blind_transfer (struct mansession *s, const struct message *m)
 
static int action_cancel_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_coreshowchannelmap (struct mansession *s, const struct message *m)
 Manager command "CoreShowChannelMap" - Lists all channels connected to the specified channel.
 
static int action_coreshowchannels (struct mansession *s, const struct message *m)
 Manager command "CoreShowChannels" - List currently defined channels and some information about them.
 
static int action_corestatus (struct mansession *s, const struct message *m)
 Show PBX core status information.
 
static int action_createconfig (struct mansession *s, const struct message *m)
 
static void action_destroy (void *obj)
 
static int action_events (struct mansession *s, const struct message *m)
 
static int action_extensionstate (struct mansession *s, const struct message *m)
 
static int action_filter (struct mansession *s, const struct message *m)
 Manager command to add an event filter to a manager session.
 
static struct manager_actionaction_find (const char *name)
 
static int action_getconfig (struct mansession *s, const struct message *m)
 
static int action_getconfigjson (struct mansession *s, const struct message *m)
 
static int action_getvar (struct mansession *s, const struct message *m)
 
static int action_hangup (struct mansession *s, const struct message *m)
 
static int action_listcategories (struct mansession *s, const struct message *m)
 
static int action_listcommands (struct mansession *s, const struct message *m)
 
static int action_loggerrotate (struct mansession *s, const struct message *m)
 Manager command "LoggerRotate" - reloads and rotates the logger in the same manner as the CLI command 'logger rotate'.
 
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_presencestate (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 int action_waitevent_http (struct mansession *s, const struct message *m, const char *id, int timeout)
 
static int action_waitevent_tcp (struct mansession *s, const struct message *m, const char *id, int timeout)
 
static AO2_GLOBAL_OBJ_STATIC (event_docs)
 A container of event documentation nodes.
 
static AO2_GLOBAL_OBJ_STATIC (mgr_sessions)
 
static int aocmessage_get_unit_entry (const struct message *m, struct ast_aoc_unit_entry *entry, unsigned int entry_num)
 
static int app_match (const char *app, const char *data, const char *search)
 
static int appdata_match (const char *app, const char *data, const char *search)
 
static void append_channel_vars (struct ast_str **pbuf, struct ast_channel *chan)
 
int ast_hook_send_action (struct manager_custom_hook *hook, const char *msg)
 access for hooks to send action messages to ami
 
static int ast_instring (const char *bigstr, const char *smallstr, const char delim)
 
int ast_manager_check_enabled (void)
 Check if AMI is enabled.
 
struct stasis_message_routerast_manager_get_message_router (void)
 Get the stasis_message_router for AMI.
 
struct stasis_topicast_manager_get_topic (void)
 Get the Stasis Message Bus API topic for AMI.
 
int ast_manager_hangup_helper (struct mansession *s, const struct message *m, manager_hangup_handler_t hangup_handler, manager_hangup_cause_validator_t cause_validator)
 A manager helper function that hangs up a channel using a supplied channel type specific hangup function and cause code validator.
 
void ast_manager_publish_event (const char *type, int class_type, struct ast_json *obj)
 Publish an event to AMI.
 
int ast_manager_register2 (const char *action, int auth, int(*func)(struct mansession *s, const struct message *m), struct ast_module *module, 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)
 
struct ast_strast_manager_str_from_json_object (struct ast_json *blob, key_exclusion_cb exclusion_cb)
 Convert a JSON object into an AMI compatible string.
 
int ast_manager_unregister (const char *action)
 support functions to register/unregister AMI action handlers,
 
void ast_manager_unregister_hook (struct manager_custom_hook *hook)
 Delete a custom hook to be called when an event is fired.
 
 AST_THREADSTORAGE_CUSTOM_SCOPE (astman_append_buf, NULL, ast_free_ptr, static)
 thread local buffer for astman_append
 
 AST_THREADSTORAGE_CUSTOM_SCOPE (userevent_buf, NULL, ast_free_ptr, static)
 
int ast_webmanager_check_enabled (void)
 Check if AMI/HTTP is enabled.
 
void astman_append (struct mansession *s, const char *fmt,...)
 
static void astman_append_headers (struct message *m, const struct ast_variable *params)
 Append additional headers into the message structure from params.
 
static void astman_append_json (struct mansession *s, const char *str)
 
static void astman_flush (struct mansession *s, struct ast_str *buf)
 
static void astman_free_headers (struct message *m)
 Free headers inside message structure, but not the message structure itself.
 
const char * astman_get_header (const struct message *m, char *var)
 Return the first matching variable from an array.
 
struct ast_variableastman_get_variables (const struct message *m)
 Get a linked list of the Variable: headers.
 
struct ast_variableastman_get_variables_order (const struct message *m, enum variable_orders order)
 Get a linked list of the Variable: headers with order specified.
 
void astman_live_dangerously (int new_live_dangerously)
 Enable/disable the inclusion of 'dangerous' configurations outside of the ast_config_AST_CONFIG_DIR.
 
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_error_va (struct mansession *s, const struct message *m, const char *fmt,...)
 Send error in manager transaction (with va_args support)
 
static void astman_send_list_complete (struct mansession *s, const struct message *m, const char *event_name, int count)
 
void astman_send_list_complete_end (struct mansession *s)
 End the list complete event.
 
void astman_send_list_complete_start (struct mansession *s, const struct message *m, const char *event_name, int count)
 Start the list complete event.
 
static struct ast_strastman_send_list_complete_start_common (struct mansession *s, const struct message *m, const char *event_name, int count)
 
void astman_send_listack (struct mansession *s, const struct message *m, char *msg, char *listflag)
 Send ack in manager transaction to begin a list.
 
void astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg)
 Send response in manager transaction.
 
static void astman_send_response_full (struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag)
 send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field.
 
static void astman_start_ack (struct mansession *s, const struct message *m)
 
static int async_goto_with_discard_bridge_after (struct ast_channel *chan, const char *context, const char *exten, int priority)
 
static int authenticate (struct mansession *s, const struct message *m)
 
static const char * authority_to_str (int authority, struct ast_str **res)
 Convert authority code to a list of options. Note that the EVENT_FLAG_ALL authority will always be returned.
 
static struct mansession_sessionbuild_mansession (const struct ast_sockaddr *addr, unsigned int needs_alert_pipe)
 Allocate manager session structure and add it to the list of sessions.
 
static int check_blacklist (const char *cmd)
 
static int check_manager_session_inuse (const char *name)
 
static int coreshowchannelmap_add_connected_channels (struct ao2_container *channel_map, struct ast_channel_snapshot *channel_snapshot, struct ast_bridge_snapshot *bridge_snapshot)
 Recursive function to get all channels in a bridge. Follow local channels as well.
 
static int coreshowchannelmap_add_to_map (struct ao2_container *c, const char *s)
 Helper function to add a channel name to the vector.
 
static void destroy_fast_originate_helper (struct fast_originate_helper *doomed)
 
static int do_message (struct mansession *s)
 
static void event_filter_destructor (void *obj)
 
static struct eventqenteventqent_alloc (const char *event_name, int category)
 Allocate a manager event.
 
static void eventqent_destructor (void *obj)
 Destructor for manager event message.
 
static void * fast_originate (void *data)
 
static int file_in_modules_dir (const char *filename)
 Check if the given file path is in the modules dir or not.
 
static int filter_cmp_fn (void *obj, void *arg, void *data, int flags)
 
static int function_capable_string_allowed_with_auths (const char *evaluating, int writepermlist)
 Checks to see if a string which can be used to evaluate functions should be rejected.
 
static void generate_status (struct mansession *s, struct ast_channel *chan, char **vars, int varc, int all_variables, char *id_text, int *count)
 
static int get_input (struct mansession *s, struct pollfd *pfds, char *output)
 
static struct ast_manager_userget_manager_by_name_locked (const char *name)
 
static int get_perm (const char *instr)
 
static char * handle_kickmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager kick session.
 
static char * handle_manager_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager reload.
 
static char * handle_mandebug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void handle_parse_error (struct mansession *s, struct message *m, char *error)
 
static char * handle_showmanager (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_showmanagers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_showmancmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_showmancmds (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list commands.
 
static char * handle_showmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list connected.
 
static enum error_type handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn)
 helper function for action_updateconfig
 
static int is_originate_app_permitted (const char *app, const char *data, int permission)
 
static int is_restricted_file (const char *filename)
 Check if a file is restricted or not.
 
static void json_escape (char *out, const char *in)
 
static void log_action (const struct message *m, const char *action)
 
static struct ast_variableman_do_variable_value (struct ast_variable *head, const char *hdr_val)
 
static enum add_filter_result manager_add_filter (const char *criteria, const char *filter_pattern, struct ao2_container *includefilters, struct ao2_container *excludefilters)
 Add an event filter to a manager session.
 
static void manager_default_msg_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static int manager_displayconnects (struct mansession_session *session)
 Get displayconnects config option.
 
static void manager_generic_msg_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static void manager_json_array_with_key (struct ast_json *obj, const char *key, size_t index, struct ast_str **res, key_exclusion_cb exclusion_cb)
 
static void manager_json_obj_with_key (struct ast_json *obj, const char *key, const char *parent_key, struct ast_str **res, key_exclusion_cb exclusion_cb)
 
static void manager_json_to_ast_str (struct ast_json *obj, const char *key, struct ast_str **res, key_exclusion_cb exclusion_cb)
 
static void manager_json_value_str_append (struct ast_json *value, const char *key, struct ast_str **res)
 
static int manager_modulecheck (struct mansession *s, const struct message *m)
 Manager function to check if module is loaded.
 
static int manager_moduleload (struct mansession *s, const struct message *m)
 
static int manager_state_cb (const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
 
static void manager_subscription_change_msg_cb (void *userdata, struct stasis_subscription *sub, struct stasis_message *message)
 Callback for subscription change messages.
 
static int mansession_cmp_fn (void *obj, void *arg, int flags)
 
static enum ast_transport 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_eventdata (struct event_filter_entry *entry, const char *eventdata)
 Test eventdata against a filter entry.
 
static void print_event_instance (struct ast_cli_args *a, struct ast_xml_doc_item *instance)
 
static int process_events (struct mansession *s)
 Send any pending events to the client listening on this socket.
 
static int process_message (struct mansession *s, const struct message *m)
 Process an AMI message, performing desired action. Return 0 on success, -1 on error that require the session to be destroyed.
 
static int purge_sessions (int n_max)
 remove at most n_max stale session from the list.
 
static int queue_match (const char *app, const char *data, const char *search)
 
static int queue_read_action_payload (struct ast_channel *chan, const unsigned char *payload, size_t payload_size, enum ast_frame_read_action action)
 Queue a given read action containing a payload onto a channel.
 
static int queue_sendtext (struct ast_channel *chan, const char *body)
 Queue a read action to send a text message.
 
static int queue_sendtext_data (struct ast_channel *chan, const char *body, const char *content_type)
 Queue a read action to send a text data message.
 
static int reload_module (void)
 
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 void session_notify (struct mansession_session *session)
 
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 should_send_event (struct ao2_container *includefilters, struct ao2_container *excludefilters, struct eventqent *eqe)
 
static int strings_to_mask (const char *string)
 
static struct mansession_sessionunref_mansession (struct mansession_session *s)
 Unreference manager session object. If no more references, then go ahead and delete it.
 
static const char * user_authority_to_str (int authority, struct ast_str **res)
 Convert authority code to a list of options for a user. This will only display those authority codes that have an explicit match on authority.
 

Variables

static struct stasis_subscriptionacl_change_sub
 
static struct actions actions = AST_RWLIST_HEAD_INIT_VALUE
 
static int allowmultiplelogin = 1
 
static int authlimit
 
static int authtimeout
 
static int broken_events_action = 0
 
struct { 
 
   const char *   words [AST_MAX_CMD_LEN
 
command_blacklist [] 
 
static int displayconnects = 1
 
static char global_realm [MAXHOSTNAMELEN]
 
static int httptimeout = 60
 
static int live_dangerously
 Set to true (non-zero) to globally allow all dangerous AMI actions to run.
 
static char * manager_channelvars
 
static int manager_debug = 0
 
static char * manager_disabledevents
 
static int manager_enabled = 0
 
static struct manager_hooks manager_hooks = AST_RWLIST_HEAD_INIT_VALUE
 
static struct stasis_topicmanager_topic
 A stasis_topic that all topics AMI cares about will be forwarded to.
 
static char * match_type_names []
 
static struct originate_permissions_entry originate_app_permissions []
 
static const struct permalias perms []
 
static struct stasis_forwardrtp_topic_forwarder
 The stasis_subscription for forwarding the RTP topic to the AMI topic.
 
static struct stasis_forwardsecurity_topic_forwarder
 The stasis_subscription for forwarding the Security topic to the AMI topic.
 
static struct stasis_message_routerstasis_router
 The stasis_message_router for all Stasis Message Bus API messages.
 
static int subscribed = 0
 
static int timestampevents
 
static int unauth_sessions = 0
 
static struct users users = AST_RWLIST_HEAD_INIT_VALUE
 
static int webmanager_enabled = 0
 
 STASIS_MESSAGE_TYPE_DEFN (ast_manager_get_generic_type)
 Define AMI message types.
 

Detailed Description

Macro Definition Documentation

◆ any_manager_listeners

#define any_manager_listeners (   sessions)     ((sessions && ao2_container_count(sessions)) || !AST_RWLIST_EMPTY(&manager_hooks))

Definition at line 556 of file manager.c.

◆ ASTMAN_APPEND_BUF_INITSIZE

#define ASTMAN_APPEND_BUF_INITSIZE   256

initial allocated size for the astman_append_buf and astman_send_*_va

Definition at line 1828 of file manager.c.

◆ DEFAULT_REALM

#define DEFAULT_REALM   "asterisk"

Definition at line 163 of file manager.c.

◆ EVENT_FLAG_SHUTDOWN

#define EVENT_FLAG_SHUTDOWN   -1

Fake event class used to end sessions at shutdown.

Definition at line 196 of file manager.c.

◆ GET_HEADER_FIRST_MATCH

#define GET_HEADER_FIRST_MATCH   0

Definition at line 1528 of file manager.c.

◆ GET_HEADER_LAST_MATCH

#define GET_HEADER_LAST_MATCH   1

Definition at line 1529 of file manager.c.

◆ GET_HEADER_SKIP_EMPTY

#define GET_HEADER_SKIP_EMPTY   2

Definition at line 1530 of file manager.c.

◆ MANAGER_EVENT_BUF_INITSIZE

#define MANAGER_EVENT_BUF_INITSIZE   256

Initial size of the manager event message buffer.

Definition at line 7569 of file manager.c.

◆ manager_event_sessions

#define manager_event_sessions (   sessions,
  category,
  event,
  contents,
  ... 
)     __manager_event_sessions(sessions, category, event, 0, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, contents , ## __VA_ARGS__)

Definition at line 553 of file manager.c.

◆ MAX_AUTH_PERM_STRING

#define MAX_AUTH_PERM_STRING   150

Maximum string length of the AMI authority permission string buildable from perms[].

Definition at line 725 of file manager.c.

◆ MAX_BLACKLIST_CMD_LEN

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

◆ MAX_VARS

#define MAX_VARS   128

Definition at line 193 of file manager.c.

◆ MGR_SHOW_TERMINAL_WIDTH

#define MGR_SHOW_TERMINAL_WIDTH   80

Definition at line 191 of file manager.c.

◆ MSG_MOREDATA

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

Definition at line 1876 of file manager.c.

Enumeration Type Documentation

◆ add_filter_result

Enumerator
FILTER_SUCCESS 
FILTER_ALLOC_FAILED 
FILTER_COMPILE_FAIL 
FILTER_FORMAT_ERROR 

Definition at line 123 of file manager.c.

123 {
124 FILTER_SUCCESS = 0,
128};
@ FILTER_SUCCESS
Definition manager.c:124
@ FILTER_FORMAT_ERROR
Definition manager.c:127
@ FILTER_COMPILE_FAIL
Definition manager.c:126
@ FILTER_ALLOC_FAILED
Definition manager.c:125

◆ error_type

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 
FAILURE_TEMPLATE 

Definition at line 108 of file manager.c.

108 {
109 UNKNOWN_ACTION = 1,
121};
@ FAILURE_EMPTYCAT
Definition manager.c:116
@ FAILURE_UPDATE
Definition manager.c:117
@ FAILURE_NEWCAT
Definition manager.c:114
@ FAILURE_DELETE
Definition manager.c:118
@ FAILURE_APPEND
Definition manager.c:119
@ UNKNOWN_CATEGORY
Definition manager.c:110
@ FAILURE_DELCAT
Definition manager.c:115
@ FAILURE_ALLOCATION
Definition manager.c:113
@ FAILURE_TEMPLATE
Definition manager.c:120
@ UNSPECIFIED_CATEGORY
Definition manager.c:111
@ UNSPECIFIED_ARGUMENT
Definition manager.c:112
@ UNKNOWN_ACTION
Definition manager.c:109

◆ event_filter_match_type

Enumerator
FILTER_MATCH_REGEX 
FILTER_MATCH_EXACT 
FILTER_MATCH_STARTS_WITH 
FILTER_MATCH_ENDS_WITH 
FILTER_MATCH_CONTAINS 
FILTER_MATCH_NONE 

Definition at line 376 of file manager.c.

376 {
383};
@ FILTER_MATCH_ENDS_WITH
Definition manager.c:380
@ FILTER_MATCH_CONTAINS
Definition manager.c:381
@ FILTER_MATCH_STARTS_WITH
Definition manager.c:379
@ FILTER_MATCH_REGEX
Definition manager.c:377
@ FILTER_MATCH_NONE
Definition manager.c:382
@ FILTER_MATCH_EXACT
Definition manager.c:378

◆ mansession_message_parsing

Enumerator
MESSAGE_OKAY 
MESSAGE_LINE_TOO_LONG 

Definition at line 304 of file manager.c.

304 {
307};
@ MESSAGE_OKAY
Definition manager.c:305
@ MESSAGE_LINE_TOO_LONG
Definition manager.c:306

Function Documentation

◆ __ast_manager_event_multichan()

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
file,line,func
contentsFormat string describing event
...
Since
1.8

Definition at line 7757 of file manager.c.

7760{
7761 struct ao2_container *sessions = ao2_global_obj_ref(mgr_sessions);
7762 va_list ap;
7763 int res;
7764
7766 /* Nobody is listening */
7768 return 0;
7769 }
7770
7771 va_start(ap, fmt);
7773 file, line, func, fmt, ap);
7774 va_end(ap);
7776 return res;
7777}
#define ao2_cleanup(obj)
Definition astobj2.h:1934
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition astobj2.h:918
static struct unistimsession * sessions
static int chancount
Definition channel.c:97
static int __manager_event_sessions_va(struct ao2_container *sessions, int category, const char *event_name, int chancount, struct ast_channel **chans, const char *file, int line, const char *func, const char *fmt, va_list ap)
Definition manager.c:7620
#define any_manager_listeners(sessions)
Definition manager.c:556
Generic container type.
Definition astman.c:88

References __manager_event_sessions_va(), any_manager_listeners, ao2_cleanup, ao2_global_obj_ref, chancount, ast_category::file, and sessions.

◆ __astman_get_header()

static const char * __astman_get_header ( const struct message m,
char *  var,
int  mode 
)
static

Return a matching header value.

Generic function to return either the first or the last matching header from a list of variables, possibly skipping empty strings.

Note
At the moment there is only one use of this function in this file, so we make it static.
Never returns NULL.

Definition at line 1545 of file manager.c.

1546{
1547 int x, l = strlen(var);
1548 const char *result = "";
1549
1550 if (!m) {
1551 return result;
1552 }
1553
1554 for (x = 0; x < m->hdrcount; x++) {
1555 const char *h = m->headers[x];
1556 if (!strncasecmp(var, h, l) && h[l] == ':') {
1557 const char *value = h + l + 1;
1558 value = ast_skip_blanks(value); /* ignore leading spaces in the value */
1559 /* found a potential candidate */
1560 if ((mode & GET_HEADER_SKIP_EMPTY) && ast_strlen_zero(value)) {
1561 continue; /* not interesting */
1562 }
1563 if (mode & GET_HEADER_LAST_MATCH) {
1564 result = value; /* record the last match so far */
1565 } else {
1566 return value;
1567 }
1568 }
1569 }
1570
1571 return result;
1572}
#define var
Definition ast_expr2f.c:605
static PGresult * result
Definition cel_pgsql.c:84
#define GET_HEADER_LAST_MATCH
Definition manager.c:1529
#define GET_HEADER_SKIP_EMPTY
Definition manager.c:1530
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
char *attribute_pure ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition strings.h:161
unsigned int hdrcount
Definition manager.h:150
const char * headers[AST_MAX_MANHEADERS]
Definition manager.h:151
int value
Definition syslog.c:37

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

Referenced by action_aoc_s_submessage(), astman_get_header(), and process_message().

◆ __manager_event_sessions()

static int __manager_event_sessions ( struct ao2_container sessions,
int  category,
const char *  event,
int  chancount,
struct ast_channel **  chans,
const char *  file,
int  line,
const char *  func,
const char *  fmt,
  ... 
)
static

Definition at line 7735 of file manager.c.

7746{
7747 va_list ap;
7748 int res;
7749
7750 va_start(ap, fmt);
7752 chancount, chans, file, line, func, fmt, ap);
7753 va_end(ap);
7754 return res;
7755}

References __manager_event_sessions_va(), chancount, ast_category::file, and sessions.

◆ __manager_event_sessions_va()

static int __manager_event_sessions_va ( struct ao2_container sessions,
int  category,
const char *  event_name,
int  chancount,
struct ast_channel **  chans,
const char *  file,
int  line,
const char *  func,
const char *  fmt,
va_list  ap 
)
static

Definition at line 7620 of file manager.c.

7631{
7632 struct eventqent *event;
7634 const char *cat_str;
7635 int i;
7636
7638 if (ast_in_delimited_string(event_name, manager_disabledevents, ',')) {
7639 ast_debug(3, "AMI Event '%s' is globally disabled, skipping\n", event_name);
7640 /* Event is globally disabled */
7641 return -1;
7642 }
7643 }
7644
7645 event = eventqent_alloc(event_name, category);
7646 if (!event) {
7647 return -1;
7648 }
7649
7650 cat_str = authority_to_str(category, &auth);
7651 ast_str_set(&event->message, 0,
7652 "Event: %s\r\n"
7653 "Privilege: %s\r\n",
7654 event_name, cat_str);
7655
7656 if (timestampevents) {
7657 struct timeval now;
7658
7659 now = ast_tvnow();
7660 ast_str_append(&event->message, 0,
7661 "Timestamp: %ld.%06lu\r\n",
7662 (long)now.tv_sec, (unsigned long) now.tv_usec);
7663 }
7664 if (manager_debug) {
7665 static int seq;
7666
7667 ast_str_append(&event->message, 0,
7668 "SequenceNumber: %d\r\n",
7670 ast_str_append(&event->message, 0,
7671 "File: %s\r\n"
7672 "Line: %d\r\n"
7673 "Func: %s\r\n",
7674 file, line, func);
7675 }
7677 ast_str_append(&event->message, 0,
7678 "SystemName: %s\r\n",
7680 }
7681
7682 ast_str_append_va(&event->message, 0, fmt, ap);
7683 for (i = 0; i < chancount; i++) {
7684 append_channel_vars(&event->message, chans[i]);
7685 }
7686
7687 ast_str_append(&event->message, 0, "\r\n");
7688
7689 /* Wake up any sleeping sessions */
7690 if (sessions) {
7691 struct ao2_iterator iter;
7693
7694 /*
7695 * This purposely does not hold the session lock while checking send_events, as it
7696 * could block for a long period of time. We also do a second check in the consumer
7697 * of the pending_events queue such that if an event is added to the queue which should no
7698 * longer be sent to the session it won't be.
7699 */
7700 iter = ao2_iterator_init(sessions, 0);
7701 while ((session = ao2_iterator_next(&iter))) {
7702 if (category == EVENT_FLAG_SHUTDOWN ||
7703 (session->send_events & category) == category) {
7704 ast_mutex_lock(&session->pending_events_lock);
7705 if (!AST_VECTOR_APPEND(&session->pending_events, ao2_bump(event))) {
7706 if (AST_VECTOR_SIZE(&session->pending_events) == 1) {
7707 /* If this is the first event, wake up the session */
7709 }
7710 } else {
7711 ao2_ref(event, -1);
7712 }
7713 ast_mutex_unlock(&session->pending_events_lock);
7714 }
7716 }
7717 ao2_iterator_destroy(&iter);
7718 }
7719
7720 if (category != EVENT_FLAG_SHUTDOWN && !AST_RWLIST_EMPTY(&manager_hooks)) {
7721 struct manager_custom_hook *hook;
7722
7725 hook->helper(category, event_name, ast_str_buffer(event->message));
7726 }
7728 }
7729
7730 ao2_ref(event, -1);
7731
7732 return 0;
7733}
static volatile unsigned int seq
Definition app_sms.c:126
static struct ast_mansession session
#define ao2_iterator_next(iter)
Definition astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition astobj2.h:480
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static void session_notify(struct mansession_session *session)
Definition manager.c:886
static int manager_debug
Definition manager.c:157
static void append_channel_vars(struct ast_str **pbuf, struct ast_channel *chan)
Definition manager.c:7604
static struct mansession_session * unref_mansession(struct mansession_session *s)
Unreference manager session object. If no more references, then go ahead and delete it.
Definition manager.c:865
static const char * authority_to_str(int authority, struct ast_str **res)
Convert authority code to a list of options. Note that the EVENT_FLAG_ALL authority will always be re...
Definition manager.c:766
#define MAX_AUTH_PERM_STRING
Definition manager.c:725
static int timestampevents
Definition manager.c:151
#define EVENT_FLAG_SHUTDOWN
Fake event class used to end sessions at shutdown.
Definition manager.c:196
static struct eventqent * eventqent_alloc(const char *event_name, int category)
Allocate a manager event.
Definition manager.c:7579
static char * manager_disabledevents
Definition manager.c:161
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_RWLIST_EMPTY
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition linkedlists.h:78
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_RWLIST_TRAVERSE
#define ast_mutex_unlock(a)
Definition lock.h:197
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition lock.h:764
#define ast_mutex_lock(a)
Definition lock.h:196
const char * ast_config_AST_SYSTEM_NAME
Definition options.c:171
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition strings.h:1139
#define ast_str_alloca(init_len)
Definition strings.h:848
int ast_in_delimited_string(const char *needle, const char *haystack, char delim)
Check if there is an exact match for 'needle' between delimiters in 'haystack'.
Definition strings.c:466
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition strings.h:1113
int ast_str_append_va(struct ast_str **buf, ssize_t max_len, const char *fmt, va_list ap)
Append to a dynamic string using a va_list.
Definition strings.h:1048
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition astobj2.h:1821
Support for dynamic strings.
Definition strings.h:623
An AMI event message.
Definition manager.c:140
struct manager_custom_hook::@250 list
manager_hook_t helper
Definition manager.h:117
list of hooks registered
Definition manager.c:357
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition time.h:159
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition vector.h:637
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition vector.h:267

References ao2_bump, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, append_channel_vars(), ast_atomic_fetchadd_int(), ast_config_AST_SYSTEM_NAME, ast_debug, ast_in_delimited_string(), ast_mutex_lock, ast_mutex_unlock, AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_str_append(), ast_str_append_va(), ast_str_buffer(), ast_str_set(), ast_strlen_zero(), ast_tvnow(), AST_VECTOR_APPEND, AST_VECTOR_SIZE, authority_to_str(), chancount, EVENT_FLAG_SHUTDOWN, eventqent_alloc(), ast_category::file, manager_custom_hook::helper, manager_debug, manager_disabledevents, MAX_AUTH_PERM_STRING, seq, session, session_notify(), sessions, timestampevents, and unref_mansession().

Referenced by __ast_manager_event_multichan(), and __manager_event_sessions().

◆ acl_change_stasis_cb()

static void acl_change_stasis_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 10155 of file manager.c.

10157{
10159 return;
10160 }
10161
10162 /* For now, this is going to be performed simply and just execute a forced reload. */
10163 ast_log(LOG_NOTICE, "Reloading manager in response to ACL change event.\n");
10164 __init_manager(1, 1);
10165}
struct stasis_message_type * ast_named_acl_change_type(void)
a stasis_message_type for changes against a named ACL or the set of all named ACLs
#define ast_log
Definition astobj2.c:42
#define LOG_NOTICE
static int __init_manager(int reload, int by_external_config)
Definition manager.c:9758

References __init_manager(), ast_log, ast_named_acl_change_type(), and LOG_NOTICE.

Referenced by acl_change_stasis_subscribe().

◆ acl_change_stasis_subscribe()

static void acl_change_stasis_subscribe ( void  )
static

Definition at line 221 of file manager.c.

222{
223 if (!acl_change_sub) {
228 }
229}
static struct stasis_subscription * acl_change_sub
Definition manager.c:167
static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition manager.c:10155
#define NULL
Definition resample.c:96
struct stasis_topic * ast_security_topic(void)
A stasis_topic which publishes messages for security related issues.
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
Definition stasis.h:297
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition stasis.c:1101
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition stasis.c:1155
#define stasis_subscribe(topic, callback, data)
Definition stasis.h:649

References acl_change_stasis_cb(), acl_change_sub, ast_named_acl_change_type(), ast_security_topic(), NULL, stasis_subscribe, stasis_subscription_accept_message_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, and stasis_subscription_set_filter().

Referenced by __init_manager().

◆ acl_change_stasis_unsubscribe()

static void acl_change_stasis_unsubscribe ( void  )
static

Definition at line 231 of file manager.c.

232{
234}
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition stasis.c:1212

References acl_change_sub, and stasis_unsubscribe_and_join().

Referenced by __init_manager(), and manager_shutdown().

◆ action_aoc_de_message()

static struct ast_aoc_decoded * action_aoc_de_message ( struct mansession s,
const struct message m 
)
static

Definition at line 4544 of file manager.c.

4545{
4546 const char *msgtype = astman_get_header(m, "MsgType");
4547 const char *chargetype = astman_get_header(m, "ChargeType");
4548 const char *currencyname = astman_get_header(m, "CurrencyName");
4549 const char *currencyamount = astman_get_header(m, "CurrencyAmount");
4550 const char *mult = astman_get_header(m, "CurrencyMultiplier");
4551 const char *totaltype = astman_get_header(m, "TotalType");
4552 const char *aocbillingid = astman_get_header(m, "AOCBillingId");
4553 const char *association_id= astman_get_header(m, "ChargingAssociationId");
4554 const char *association_num = astman_get_header(m, "ChargingAssociationNumber");
4555 const char *association_plan = astman_get_header(m, "ChargingAssociationPlan");
4556
4557 enum ast_aoc_type _msgtype;
4558 enum ast_aoc_charge_type _chargetype;
4560 enum ast_aoc_total_type _totaltype = AST_AOC_TOTAL;
4561 enum ast_aoc_billing_id _billingid = AST_AOC_BILLING_NA;
4562 unsigned int _currencyamount = 0;
4563 int _association_id = 0;
4564 unsigned int _association_plan = 0;
4565
4566 struct ast_aoc_decoded *decoded = NULL;
4567
4568 if (ast_strlen_zero(chargetype)) {
4569 astman_send_error(s, m, "ChargeType not specified");
4570 goto aocmessage_cleanup;
4571 }
4572
4573 _msgtype = strcasecmp(msgtype, "d") ? AST_AOC_E : AST_AOC_D;
4574
4575 if (!strcasecmp(chargetype, "NA")) {
4576 _chargetype = AST_AOC_CHARGE_NA;
4577 } else if (!strcasecmp(chargetype, "Free")) {
4578 _chargetype = AST_AOC_CHARGE_FREE;
4579 } else if (!strcasecmp(chargetype, "Currency")) {
4580 _chargetype = AST_AOC_CHARGE_CURRENCY;
4581 } else if (!strcasecmp(chargetype, "Unit")) {
4582 _chargetype = AST_AOC_CHARGE_UNIT;
4583 } else {
4584 astman_send_error(s, m, "Invalid ChargeType");
4585 goto aocmessage_cleanup;
4586 }
4587
4588 if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
4589
4590 if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u", &_currencyamount) != 1)) {
4591 astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency");
4592 goto aocmessage_cleanup;
4593 }
4594
4595 if (ast_strlen_zero(mult)) {
4596 astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency.");
4597 goto aocmessage_cleanup;
4598 } else if (!strcasecmp(mult, "onethousandth")) {
4600 } else if (!strcasecmp(mult, "onehundredth")) {
4602 } else if (!strcasecmp(mult, "onetenth")) {
4603 _mult = AST_AOC_MULT_ONETENTH;
4604 } else if (!strcasecmp(mult, "one")) {
4605 _mult = AST_AOC_MULT_ONE;
4606 } else if (!strcasecmp(mult, "ten")) {
4607 _mult = AST_AOC_MULT_TEN;
4608 } else if (!strcasecmp(mult, "hundred")) {
4609 _mult = AST_AOC_MULT_HUNDRED;
4610 } else if (!strcasecmp(mult, "thousand")) {
4611 _mult = AST_AOC_MULT_THOUSAND;
4612 } else {
4613 astman_send_error(s, m, "Invalid ChargeMultiplier");
4614 goto aocmessage_cleanup;
4615 }
4616 }
4617
4618 /* create decoded object and start setting values */
4619 if (!(decoded = ast_aoc_create(_msgtype, _chargetype, 0))) {
4620 astman_send_error(s, m, "Message Creation Failed");
4621 goto aocmessage_cleanup;
4622 }
4623
4624 if (_msgtype == AST_AOC_D) {
4625 if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype, "subtotal")) {
4626 _totaltype = AST_AOC_SUBTOTAL;
4627 }
4628
4629 if (ast_strlen_zero(aocbillingid)) {
4630 /* ignore this is optional */
4631 } else if (!strcasecmp(aocbillingid, "Normal")) {
4632 _billingid = AST_AOC_BILLING_NORMAL;
4633 } else if (!strcasecmp(aocbillingid, "ReverseCharge")) {
4634 _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
4635 } else if (!strcasecmp(aocbillingid, "CreditCard")) {
4636 _billingid = AST_AOC_BILLING_CREDIT_CARD;
4637 } else {
4638 astman_send_error(s, m, "Invalid AOC-D AOCBillingId");
4639 goto aocmessage_cleanup;
4640 }
4641 } else {
4642 if (ast_strlen_zero(aocbillingid)) {
4643 /* ignore this is optional */
4644 } else if (!strcasecmp(aocbillingid, "Normal")) {
4645 _billingid = AST_AOC_BILLING_NORMAL;
4646 } else if (!strcasecmp(aocbillingid, "ReverseCharge")) {
4647 _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
4648 } else if (!strcasecmp(aocbillingid, "CreditCard")) {
4649 _billingid = AST_AOC_BILLING_CREDIT_CARD;
4650 } else if (!strcasecmp(aocbillingid, "CallFwdUnconditional")) {
4652 } else if (!strcasecmp(aocbillingid, "CallFwdBusy")) {
4653 _billingid = AST_AOC_BILLING_CALL_FWD_BUSY;
4654 } else if (!strcasecmp(aocbillingid, "CallFwdNoReply")) {
4656 } else if (!strcasecmp(aocbillingid, "CallDeflection")) {
4658 } else if (!strcasecmp(aocbillingid, "CallTransfer")) {
4659 _billingid = AST_AOC_BILLING_CALL_TRANSFER;
4660 } else {
4661 astman_send_error(s, m, "Invalid AOC-E AOCBillingId");
4662 goto aocmessage_cleanup;
4663 }
4664
4665 if (!ast_strlen_zero(association_id) && (sscanf(association_id, "%30d", &_association_id) != 1)) {
4666 astman_send_error(s, m, "Invalid ChargingAssociationId");
4667 goto aocmessage_cleanup;
4668 }
4669 if (!ast_strlen_zero(association_plan) && (sscanf(association_plan, "%30u", &_association_plan) != 1)) {
4670 astman_send_error(s, m, "Invalid ChargingAssociationPlan");
4671 goto aocmessage_cleanup;
4672 }
4673
4674 if (_association_id) {
4675 ast_aoc_set_association_id(decoded, _association_id);
4676 } else if (!ast_strlen_zero(association_num)) {
4677 ast_aoc_set_association_number(decoded, association_num, _association_plan);
4678 }
4679 }
4680
4681 if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
4682 ast_aoc_set_currency_info(decoded, _currencyamount, _mult, ast_strlen_zero(currencyname) ? NULL : currencyname);
4683 } else if (_chargetype == AST_AOC_CHARGE_UNIT) {
4684 struct ast_aoc_unit_entry entry;
4685 int i;
4686
4687 /* multiple unit entries are possible, lets get them all */
4688 for (i = 0; i < 32; i++) {
4689 if (aocmessage_get_unit_entry(m, &entry, i)) {
4690 break; /* that's the end then */
4691 }
4692
4693 ast_aoc_add_unit_entry(decoded, entry.valid_amount, entry.amount, entry.valid_type, entry.type);
4694 }
4695
4696 /* at least one unit entry is required */
4697 if (!i) {
4698 astman_send_error(s, m, "Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit");
4699 goto aocmessage_cleanup;
4700 }
4701
4702 }
4703
4704 ast_aoc_set_billing_id(decoded, _billingid);
4705 ast_aoc_set_total_type(decoded, _totaltype);
4706
4707 return decoded;
4708
4709aocmessage_cleanup:
4710
4711 ast_aoc_destroy_decoded(decoded);
4712 return NULL;
4713}
ast_aoc_charge_type
Definition aoc.h:69
@ AST_AOC_CHARGE_CURRENCY
Definition aoc.h:72
@ AST_AOC_CHARGE_FREE
Definition aoc.h:71
@ AST_AOC_CHARGE_UNIT
Definition aoc.h:73
@ AST_AOC_CHARGE_NA
Definition aoc.h:70
ast_aoc_currency_multiplier
Defines the currency multiplier for an aoc message.
Definition aoc.h:34
@ AST_AOC_MULT_TEN
Definition aoc.h:39
@ AST_AOC_MULT_ONEHUNDREDTH
Definition aoc.h:36
@ AST_AOC_MULT_HUNDRED
Definition aoc.h:40
@ AST_AOC_MULT_ONETENTH
Definition aoc.h:37
@ AST_AOC_MULT_ONETHOUSANDTH
Definition aoc.h:35
@ AST_AOC_MULT_THOUSAND
Definition aoc.h:41
@ AST_AOC_MULT_ONE
Definition aoc.h:38
struct ast_aoc_decoded * ast_aoc_create(const enum ast_aoc_type msg_type, const enum ast_aoc_charge_type charge_type, const enum ast_aoc_request requests)
creates a ast_aoc_decode object of a specific message type
Definition aoc.c:285
void * ast_aoc_destroy_decoded(struct ast_aoc_decoded *decoded)
free an ast_aoc_decoded object
Definition aoc.c:316
int ast_aoc_set_association_number(struct ast_aoc_decoded *decoded, const char *num, uint8_t plan)
set the charging association number for an AOC-E message
Definition aoc.c:1065
int ast_aoc_add_unit_entry(struct ast_aoc_decoded *decoded, const unsigned int amount_is_present, const unsigned int amount, const unsigned int type_is_present, const unsigned int type)
Adds a unit entry into the list of units.
Definition aoc.c:986
ast_aoc_billing_id
Defines the billing id options for an aoc message.
Definition aoc.h:49
@ AST_AOC_BILLING_CALL_FWD_BUSY
Definition aoc.h:55
@ AST_AOC_BILLING_CALL_FWD_NO_REPLY
Definition aoc.h:56
@ AST_AOC_BILLING_NORMAL
Definition aoc.h:51
@ AST_AOC_BILLING_CALL_DEFLECTION
Definition aoc.h:57
@ AST_AOC_BILLING_CREDIT_CARD
Definition aoc.h:53
@ AST_AOC_BILLING_CALL_TRANSFER
Definition aoc.h:58
@ AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL
Definition aoc.h:54
@ AST_AOC_BILLING_REVERSE_CHARGE
Definition aoc.h:52
@ AST_AOC_BILLING_NA
Definition aoc.h:50
int ast_aoc_set_billing_id(struct ast_aoc_decoded *decoded, const enum ast_aoc_billing_id id)
set the billing id for a AOC-D or AST_AOC_E message
Definition aoc.c:1033
int ast_aoc_set_currency_info(struct ast_aoc_decoded *decoded, const unsigned int amount, const enum ast_aoc_currency_multiplier multiplier, const char *name)
Sets the currency values for a AOC-D or AOC-E message.
Definition aoc.c:928
int ast_aoc_set_association_id(struct ast_aoc_decoded *decoded, const int id)
set the charging association id for an AST_AOC_E message
Definition aoc.c:1049
int ast_aoc_set_total_type(struct ast_aoc_decoded *decoded, const enum ast_aoc_total_type type)
Sets the type of total for a AOC-D message.
Definition aoc.c:916
ast_aoc_type
Definition aoc.h:62
@ AST_AOC_D
Definition aoc.h:65
@ AST_AOC_E
Definition aoc.h:66
ast_aoc_total_type
Definition aoc.h:82
@ AST_AOC_TOTAL
Definition aoc.h:83
@ AST_AOC_SUBTOTAL
Definition aoc.h:84
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition manager.c:1921
const char * astman_get_header(const struct message *m, char *var)
Return the first matching variable from an array.
Definition manager.c:1582
static int aocmessage_get_unit_entry(const struct message *m, struct ast_aoc_unit_entry *entry, unsigned int entry_num)
Definition manager.c:4519
Definition aoc.h:178

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

Referenced by action_aocmessage().

◆ action_aoc_s_message()

static struct ast_aoc_decoded * action_aoc_s_message ( struct mansession s,
const struct message m 
)
static

Definition at line 4939 of file manager.c.

4941{
4942 struct ast_aoc_decoded *decoded = NULL;
4943 int hdrlen;
4944 int x;
4945 static const char hdr[] = "ChargedItem:";
4946 struct message sm = { 0 };
4947 int rates = 0;
4948
4949 if (!(decoded = ast_aoc_create(AST_AOC_S, 0, 0))) {
4950 astman_send_error(s, m, "Message Creation Failed");
4951 goto aocmessage_cleanup;
4952 }
4953
4954 hdrlen = strlen(hdr);
4955 for (x = 0; x < m->hdrcount; x++) {
4956 if (strncasecmp(hdr, m->headers[x], hdrlen) == 0) {
4957 if (rates > ast_aoc_s_get_count(decoded)) {
4958 if (action_aoc_s_submessage(s, &sm, decoded) == -1) {
4959 goto aocmessage_cleanup;
4960 }
4961 }
4962 ++rates;
4963 }
4964
4965 sm.headers[sm.hdrcount] = m->headers[x];
4966 ++sm.hdrcount;
4967 }
4968 if (rates > ast_aoc_s_get_count(decoded)) {
4969 if (action_aoc_s_submessage(s, &sm, decoded) == -1) {
4970 goto aocmessage_cleanup;
4971 }
4972 }
4973
4974 return decoded;
4975
4976aocmessage_cleanup:
4977
4978 ast_aoc_destroy_decoded(decoded);
4979 return NULL;
4980}
@ AST_AOC_S
Definition aoc.h:64
unsigned int ast_aoc_s_get_count(struct ast_aoc_decoded *decoded)
get the number rates associated with an AOC-S message
Definition aoc.c:765
static int action_aoc_s_submessage(struct mansession *s, const struct message *m, struct ast_aoc_decoded *decoded)
Definition manager.c:4715

References action_aoc_s_submessage(), ast_aoc_create(), ast_aoc_destroy_decoded(), AST_AOC_S, ast_aoc_s_get_count(), astman_send_error(), message::hdrcount, message::headers, and NULL.

Referenced by action_aocmessage().

◆ action_aoc_s_submessage()

static int action_aoc_s_submessage ( struct mansession s,
const struct message m,
struct ast_aoc_decoded decoded 
)
static

Definition at line 4715 of file manager.c.

4717{
4718 const char *chargeditem = __astman_get_header(m, "ChargedItem", GET_HEADER_LAST_MATCH);
4719 const char *ratetype = __astman_get_header(m, "RateType", GET_HEADER_LAST_MATCH);
4720 const char *currencyname = __astman_get_header(m, "CurrencyName", GET_HEADER_LAST_MATCH);
4721 const char *currencyamount = __astman_get_header(m, "CurrencyAmount", GET_HEADER_LAST_MATCH);
4722 const char *mult = __astman_get_header(m, "CurrencyMultiplier", GET_HEADER_LAST_MATCH);
4723 const char *time = __astman_get_header(m, "Time", GET_HEADER_LAST_MATCH);
4724 const char *timescale = __astman_get_header(m, "TimeScale", GET_HEADER_LAST_MATCH);
4725 const char *granularity = __astman_get_header(m, "Granularity", GET_HEADER_LAST_MATCH);
4726 const char *granularitytimescale = __astman_get_header(m, "GranularityTimeScale", GET_HEADER_LAST_MATCH);
4727 const char *chargingtype = __astman_get_header(m, "ChargingType", GET_HEADER_LAST_MATCH);
4728 const char *volumeunit = __astman_get_header(m, "VolumeUnit", GET_HEADER_LAST_MATCH);
4729 const char *code = __astman_get_header(m, "Code", GET_HEADER_LAST_MATCH);
4730
4731 enum ast_aoc_s_charged_item _chargeditem;
4732 enum ast_aoc_s_rate_type _ratetype;
4734 unsigned int _currencyamount = 0;
4735 unsigned int _code;
4736 unsigned int _time = 0;
4737 enum ast_aoc_time_scale _scale = 0;
4738 unsigned int _granularity = 0;
4739 enum ast_aoc_time_scale _granularity_time_scale = AST_AOC_TIME_SCALE_MINUTE;
4740 int _step = 0;
4741 enum ast_aoc_volume_unit _volumeunit = 0;
4742
4743 if (ast_strlen_zero(chargeditem)) {
4744 astman_send_error(s, m, "ChargedItem not specified");
4745 goto aocmessage_cleanup;
4746 }
4747
4748 if (ast_strlen_zero(ratetype)) {
4749 astman_send_error(s, m, "RateType not specified");
4750 goto aocmessage_cleanup;
4751 }
4752
4753 if (!strcasecmp(chargeditem, "NA")) {
4754 _chargeditem = AST_AOC_CHARGED_ITEM_NA;
4755 } else if (!strcasecmp(chargeditem, "SpecialArrangement")) {
4757 } else if (!strcasecmp(chargeditem, "BasicCommunication")) {
4759 } else if (!strcasecmp(chargeditem, "CallAttempt")) {
4760 _chargeditem = AST_AOC_CHARGED_ITEM_CALL_ATTEMPT;
4761 } else if (!strcasecmp(chargeditem, "CallSetup")) {
4762 _chargeditem = AST_AOC_CHARGED_ITEM_CALL_SETUP;
4763 } else if (!strcasecmp(chargeditem, "UserUserInfo")) {
4765 } else if (!strcasecmp(chargeditem, "SupplementaryService")) {
4767 } else {
4768 astman_send_error(s, m, "Invalid ChargedItem");
4769 goto aocmessage_cleanup;
4770 }
4771
4772 if (!strcasecmp(ratetype, "NA")) {
4773 _ratetype = AST_AOC_RATE_TYPE_NA;
4774 } else if (!strcasecmp(ratetype, "Free")) {
4775 _ratetype = AST_AOC_RATE_TYPE_FREE;
4776 } else if (!strcasecmp(ratetype, "FreeFromBeginning")) {
4778 } else if (!strcasecmp(ratetype, "Duration")) {
4779 _ratetype = AST_AOC_RATE_TYPE_DURATION;
4780 } else if (!strcasecmp(ratetype, "Flat")) {
4781 _ratetype = AST_AOC_RATE_TYPE_FLAT;
4782 } else if (!strcasecmp(ratetype, "Volume")) {
4783 _ratetype = AST_AOC_RATE_TYPE_VOLUME;
4784 } else if (!strcasecmp(ratetype, "SpecialCode")) {
4786 } else {
4787 astman_send_error(s, m, "Invalid RateType");
4788 goto aocmessage_cleanup;
4789 }
4790
4791 if (_ratetype > AST_AOC_RATE_TYPE_FREE_FROM_BEGINNING) {
4792 if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u",
4793 &_currencyamount) != 1)) {
4794 astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when RateType is non-free");
4795 goto aocmessage_cleanup;
4796 }
4797
4798 if (ast_strlen_zero(mult)) {
4799 astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency.");
4800 goto aocmessage_cleanup;
4801 } else if (!strcasecmp(mult, "onethousandth")) {
4803 } else if (!strcasecmp(mult, "onehundredth")) {
4805 } else if (!strcasecmp(mult, "onetenth")) {
4806 _mult = AST_AOC_MULT_ONETENTH;
4807 } else if (!strcasecmp(mult, "one")) {
4808 _mult = AST_AOC_MULT_ONE;
4809 } else if (!strcasecmp(mult, "ten")) {
4810 _mult = AST_AOC_MULT_TEN;
4811 } else if (!strcasecmp(mult, "hundred")) {
4812 _mult = AST_AOC_MULT_HUNDRED;
4813 } else if (!strcasecmp(mult, "thousand")) {
4814 _mult = AST_AOC_MULT_THOUSAND;
4815 } else {
4816 astman_send_error(s, m, "Invalid ChargeMultiplier");
4817 goto aocmessage_cleanup;
4818 }
4819 }
4820
4821 if (_ratetype == AST_AOC_RATE_TYPE_DURATION) {
4822 if (ast_strlen_zero(timescale)) {
4823 astman_send_error(s, m, "TimeScale unspecified, TimeScale is required when RateType is Duration.");
4824 goto aocmessage_cleanup;
4825 } else if (!strcasecmp(timescale, "onehundredthsecond")) {
4827 } else if (!strcasecmp(timescale, "onetenthsecond")) {
4829 } else if (!strcasecmp(timescale, "second")) {
4831 } else if (!strcasecmp(timescale, "tenseconds")) {
4833 } else if (!strcasecmp(timescale, "minute")) {
4835 } else if (!strcasecmp(timescale, "hour")) {
4836 _scale = AST_AOC_TIME_SCALE_HOUR;
4837 } else if (!strcasecmp(timescale, "day")) {
4838 _scale = AST_AOC_TIME_SCALE_DAY;
4839 } else {
4840 astman_send_error(s, m, "Invalid TimeScale");
4841 goto aocmessage_cleanup;
4842 }
4843
4844 if (ast_strlen_zero(time) || (sscanf(time, "%30u", &_time) != 1)) {
4845 astman_send_error(s, m, "Invalid Time, Time is a required when RateType is Duration");
4846 goto aocmessage_cleanup;
4847 }
4848
4849 if (!ast_strlen_zero(granularity)) {
4850 if ((sscanf(time, "%30u", &_granularity) != 1)) {
4851 astman_send_error(s, m, "Invalid Granularity");
4852 goto aocmessage_cleanup;
4853 }
4854
4855 if (ast_strlen_zero(granularitytimescale)) {
4856 astman_send_error(s, m, "Invalid GranularityTimeScale, GranularityTimeScale is a required when Granularity is specified");
4857 } else if (!strcasecmp(granularitytimescale, "onehundredthsecond")) {
4858 _granularity_time_scale = AST_AOC_TIME_SCALE_HUNDREDTH_SECOND;
4859 } else if (!strcasecmp(granularitytimescale, "onetenthsecond")) {
4860 _granularity_time_scale = AST_AOC_TIME_SCALE_TENTH_SECOND;
4861 } else if (!strcasecmp(granularitytimescale, "second")) {
4862 _granularity_time_scale = AST_AOC_TIME_SCALE_SECOND;
4863 } else if (!strcasecmp(granularitytimescale, "tenseconds")) {
4864 _granularity_time_scale = AST_AOC_TIME_SCALE_TEN_SECOND;
4865 } else if (!strcasecmp(granularitytimescale, "minute")) {
4866 _granularity_time_scale = AST_AOC_TIME_SCALE_MINUTE;
4867 } else if (!strcasecmp(granularitytimescale, "hour")) {
4868 _granularity_time_scale = AST_AOC_TIME_SCALE_HOUR;
4869 } else if (!strcasecmp(granularitytimescale, "day")) {
4870 _granularity_time_scale = AST_AOC_TIME_SCALE_DAY;
4871 } else {
4872 astman_send_error(s, m, "Invalid GranularityTimeScale");
4873 goto aocmessage_cleanup;
4874 }
4875 }
4876
4877 if (ast_strlen_zero(chargingtype) || strcasecmp(chargingtype, "continuouscharging") == 0) {
4878 _step = 0;
4879 } else if (strcasecmp(chargingtype, "stepfunction") == 0 ) {
4880 _step = 1;
4881 } else {
4882 astman_send_error(s, m, "Invalid ChargingType");
4883 goto aocmessage_cleanup;
4884 }
4885 }
4886
4887 if (_ratetype == AST_AOC_RATE_TYPE_VOLUME) {
4888 if (ast_strlen_zero(volumeunit)) {
4889 astman_send_error(s, m, "VolumeUnit unspecified, VolumeUnit is required when RateType is Volume.");
4890 goto aocmessage_cleanup;
4891 } else if (!strcasecmp(timescale, "octet")) {
4892 _volumeunit = AST_AOC_VOLUME_UNIT_OCTET;
4893 } else if (!strcasecmp(timescale, "segment")) {
4894 _volumeunit = AST_AOC_VOLUME_UNIT_SEGMENT;
4895 } else if (!strcasecmp(timescale, "message")) {
4896 _volumeunit = AST_AOC_VOLUME_UNIT_MESSAGE;
4897 }else {
4898 astman_send_error(s, m, "Invalid VolumeUnit");
4899 goto aocmessage_cleanup;
4900 }
4901 }
4902
4904 || _ratetype == AST_AOC_RATE_TYPE_SPECIAL_CODE) {
4905 if (ast_strlen_zero(code) || (sscanf(code, "%30u", &_code) != 1)) {
4906 astman_send_error(s, m, "Invalid Code, Code is a required when ChargedItem is SpecialArrangement and when RateType is SpecialCode");
4907 goto aocmessage_cleanup;
4908 }
4909 }
4910
4911 if (_chargeditem == AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT) {
4912 ast_aoc_s_add_special_arrangement(decoded, _code);
4913 } else if (_ratetype == AST_AOC_RATE_TYPE_DURATION) {
4914 ast_aoc_s_add_rate_duration(decoded, _chargeditem, _currencyamount, _mult,
4915 currencyname, _time, _scale, _granularity, _granularity_time_scale, _step);
4916 } else if (_ratetype == AST_AOC_RATE_TYPE_FLAT) {
4917 ast_aoc_s_add_rate_flat(decoded, _chargeditem, _currencyamount, _mult,
4918 currencyname);
4919 } else if (_ratetype == AST_AOC_RATE_TYPE_VOLUME) {
4920 ast_aoc_s_add_rate_volume(decoded, _chargeditem, _volumeunit, _currencyamount,
4921 _mult, currencyname);
4922 } else if (_ratetype == AST_AOC_RATE_TYPE_SPECIAL_CODE) {
4923 ast_aoc_s_add_rate_special_charge_code(decoded, _chargeditem, _code);
4924 } else if (_ratetype == AST_AOC_RATE_TYPE_FREE) {
4925 ast_aoc_s_add_rate_free(decoded, _chargeditem, 0);
4926 } else if (_ratetype == AST_AOC_RATE_TYPE_FREE_FROM_BEGINNING) {
4927 ast_aoc_s_add_rate_free(decoded, _chargeditem, 1);
4928 } else if (_ratetype == AST_AOC_RATE_TYPE_NA) {
4929 ast_aoc_s_add_rate_na(decoded, _chargeditem);
4930 }
4931
4932 return 0;
4933
4934aocmessage_cleanup:
4935
4936 return -1;
4937}
int ast_aoc_s_add_rate_duration(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, unsigned int amount, enum ast_aoc_currency_multiplier multiplier, const char *currency_name, unsigned long time, enum ast_aoc_time_scale time_scale, unsigned long granularity_time, enum ast_aoc_time_scale granularity_time_scale, int step_function)
Add AOC-S duration rate entry.
Definition aoc.c:779
ast_aoc_s_charged_item
Definition aoc.h:145
@ AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION
Definition aoc.h:148
@ AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT
Definition aoc.h:147
@ AST_AOC_CHARGED_ITEM_NA
Definition aoc.h:146
@ AST_AOC_CHARGED_ITEM_USER_USER_INFO
Definition aoc.h:151
@ AST_AOC_CHARGED_ITEM_CALL_SETUP
Definition aoc.h:150
@ AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE
Definition aoc.h:152
@ AST_AOC_CHARGED_ITEM_CALL_ATTEMPT
Definition aoc.h:149
ast_aoc_time_scale
Definition aoc.h:87
@ AST_AOC_TIME_SCALE_TEN_SECOND
Definition aoc.h:91
@ AST_AOC_TIME_SCALE_DAY
Definition aoc.h:94
@ AST_AOC_TIME_SCALE_TENTH_SECOND
Definition aoc.h:89
@ AST_AOC_TIME_SCALE_MINUTE
Definition aoc.h:92
@ AST_AOC_TIME_SCALE_SECOND
Definition aoc.h:90
@ AST_AOC_TIME_SCALE_HOUR
Definition aoc.h:93
@ AST_AOC_TIME_SCALE_HUNDREDTH_SECOND
Definition aoc.h:88
ast_aoc_volume_unit
Definition aoc.h:125
@ AST_AOC_VOLUME_UNIT_OCTET
Definition aoc.h:126
@ AST_AOC_VOLUME_UNIT_SEGMENT
Definition aoc.h:127
@ AST_AOC_VOLUME_UNIT_MESSAGE
Definition aoc.h:128
int ast_aoc_s_add_rate_special_charge_code(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, unsigned int code)
Add AOC-S special rate entry.
Definition aoc.c:853
int ast_aoc_s_add_rate_free(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, int from_beginning)
Add AOC-S indicating charge item is free.
Definition aoc.c:866
int ast_aoc_s_add_special_arrangement(struct ast_aoc_decoded *decoded, unsigned int code)
Add AOC-S special arrangement entry.
Definition aoc.c:889
int ast_aoc_s_add_rate_flat(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, unsigned int amount, enum ast_aoc_currency_multiplier multiplier, const char *currency_name)
Add AOC-S flat rate entry.
Definition aoc.c:810
int ast_aoc_s_add_rate_volume(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, enum ast_aoc_volume_unit volume_unit, unsigned int amount, enum ast_aoc_currency_multiplier multiplier, const char *currency_name)
Add AOC-S volume rate entry.
Definition aoc.c:831
int ast_aoc_s_add_rate_na(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item)
Add AOC-S entry indicating charge item is not available.
Definition aoc.c:878
ast_aoc_s_rate_type
Definition aoc.h:155
@ AST_AOC_RATE_TYPE_VOLUME
Definition aoc.h:161
@ AST_AOC_RATE_TYPE_FREE_FROM_BEGINNING
Definition aoc.h:158
@ AST_AOC_RATE_TYPE_SPECIAL_CODE
Definition aoc.h:162
@ AST_AOC_RATE_TYPE_NA
Definition aoc.h:156
@ AST_AOC_RATE_TYPE_DURATION
Definition aoc.h:159
@ AST_AOC_RATE_TYPE_FLAT
Definition aoc.h:160
@ AST_AOC_RATE_TYPE_FREE
Definition aoc.h:157
static const char * __astman_get_header(const struct message *m, char *var, int mode)
Return a matching header value.
Definition manager.c:1545

References __astman_get_header(), AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION, AST_AOC_CHARGED_ITEM_CALL_ATTEMPT, AST_AOC_CHARGED_ITEM_CALL_SETUP, AST_AOC_CHARGED_ITEM_NA, AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT, AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE, AST_AOC_CHARGED_ITEM_USER_USER_INFO, AST_AOC_MULT_HUNDRED, AST_AOC_MULT_ONE, AST_AOC_MULT_ONEHUNDREDTH, AST_AOC_MULT_ONETENTH, AST_AOC_MULT_ONETHOUSANDTH, AST_AOC_MULT_TEN, AST_AOC_MULT_THOUSAND, AST_AOC_RATE_TYPE_DURATION, AST_AOC_RATE_TYPE_FLAT, AST_AOC_RATE_TYPE_FREE, AST_AOC_RATE_TYPE_FREE_FROM_BEGINNING, AST_AOC_RATE_TYPE_NA, AST_AOC_RATE_TYPE_SPECIAL_CODE, AST_AOC_RATE_TYPE_VOLUME, ast_aoc_s_add_rate_duration(), ast_aoc_s_add_rate_flat(), ast_aoc_s_add_rate_free(), ast_aoc_s_add_rate_na(), ast_aoc_s_add_rate_special_charge_code(), ast_aoc_s_add_rate_volume(), ast_aoc_s_add_special_arrangement(), AST_AOC_TIME_SCALE_DAY, AST_AOC_TIME_SCALE_HOUR, AST_AOC_TIME_SCALE_HUNDREDTH_SECOND, AST_AOC_TIME_SCALE_MINUTE, AST_AOC_TIME_SCALE_SECOND, AST_AOC_TIME_SCALE_TEN_SECOND, AST_AOC_TIME_SCALE_TENTH_SECOND, AST_AOC_VOLUME_UNIT_MESSAGE, AST_AOC_VOLUME_UNIT_OCTET, AST_AOC_VOLUME_UNIT_SEGMENT, ast_strlen_zero(), astman_send_error(), and GET_HEADER_LAST_MATCH.

Referenced by action_aoc_s_message().

◆ action_aocmessage()

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

Definition at line 4982 of file manager.c.

4983{
4984 const char *msgtype = astman_get_header(m, "MsgType");
4985 const char *channel = astman_get_header(m, "Channel");
4986 const char *pchannel = astman_get_header(m, "ChannelPrefix");
4987
4988 struct ast_channel *chan = NULL;
4989
4990 struct ast_aoc_decoded *decoded = NULL;
4991 struct ast_aoc_encoded *encoded = NULL;
4992 size_t encoded_size = 0;
4993
4994 if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) {
4995 astman_send_error(s, m, "Channel and PartialChannel are not specified. Specify at least one of these.");
4996 goto aocmessage_cleanup;
4997 }
4998
4999 if (!(chan = ast_channel_get_by_name(channel)) && !ast_strlen_zero(pchannel)) {
5000 chan = ast_channel_get_by_name_prefix(pchannel, strlen(pchannel));
5001 }
5002
5003 if (!chan) {
5004 astman_send_error(s, m, "No such channel");
5005 goto aocmessage_cleanup;
5006 }
5007
5008 if (strcasecmp(msgtype, "d") == 0 || strcasecmp(msgtype, "e") == 0) {
5009 decoded = action_aoc_de_message(s, m);
5010 }
5011 else if (strcasecmp(msgtype, "s") == 0) {
5012 decoded = action_aoc_s_message(s, m);
5013 }
5014 else {
5015 astman_send_error(s, m, "Invalid MsgType");
5016 goto aocmessage_cleanup;
5017 }
5018
5019 if (!decoded) {
5020 goto aocmessage_cleanup;
5021 }
5022
5023 if ((encoded = ast_aoc_encode(decoded, &encoded_size, chan))
5024 && !ast_indicate_data(chan, AST_CONTROL_AOC, encoded, encoded_size)) {
5025 astman_send_ack(s, m, "AOC Message successfully queued on channel");
5026 } else {
5027 astman_send_error(s, m, "Error encoding AOC message, could not queue onto channel");
5028 }
5029
5030aocmessage_cleanup:
5031
5032 ast_aoc_destroy_decoded(decoded);
5033 ast_aoc_destroy_encoded(encoded);
5034
5035 if (chan) {
5036 chan = ast_channel_unref(chan);
5037 }
5038 return 0;
5039}
void * ast_aoc_destroy_encoded(struct ast_aoc_encoded *encoded)
free an ast_aoc_encoded object
Definition aoc.c:322
struct ast_aoc_encoded * ast_aoc_encode(struct ast_aoc_decoded *decoded, size_t *out_size, struct ast_channel *chan)
encodes a decoded aoc structure so it can be passed on the wire
Definition aoc.c:659
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
Definition channel.c:1400
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition channel.c:1417
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition channel.c:4676
#define ast_channel_unref(c)
Decrease channel reference count.
Definition channel.h:3019
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition manager.c:1953
static struct ast_aoc_decoded * action_aoc_s_message(struct mansession *s, const struct message *m)
Definition manager.c:4939
static struct ast_aoc_decoded * action_aoc_de_message(struct mansession *s, const struct message *m)
Definition manager.c:4544
Main Channel structure associated with a channel.

References action_aoc_de_message(), action_aoc_s_message(), ast_aoc_destroy_decoded(), ast_aoc_destroy_encoded(), ast_aoc_encode(), ast_channel_get_by_name(), ast_channel_get_by_name_prefix(), ast_channel_unref, AST_CONTROL_AOC, ast_indicate_data(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and NULL.

Referenced by __init_manager().

◆ action_atxfer()

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

Definition at line 4192 of file manager.c.

4193{
4194 const char *name = astman_get_header(m, "Channel");
4195 const char *exten = astman_get_header(m, "Exten");
4196 const char *context = astman_get_header(m, "Context");
4197 struct ast_channel *chan = NULL;
4198 char feature_code[AST_FEATURE_MAX_LEN];
4199 const char *digit;
4200
4201 if (ast_strlen_zero(name)) {
4202 astman_send_error(s, m, "No channel specified");
4203 return 0;
4204 }
4205 if (ast_strlen_zero(exten)) {
4206 astman_send_error(s, m, "No extension specified");
4207 return 0;
4208 }
4209
4210 if (!(chan = ast_channel_get_by_name(name))) {
4211 astman_send_error(s, m, "Channel specified does not exist");
4212 return 0;
4213 }
4214
4215 ast_channel_lock(chan);
4216 if (ast_get_builtin_feature(chan, "atxfer", feature_code, sizeof(feature_code)) ||
4217 ast_strlen_zero(feature_code)) {
4218 ast_channel_unlock(chan);
4219 astman_send_error(s, m, "No attended transfer feature code found");
4220 ast_channel_unref(chan);
4221 return 0;
4222 }
4223 ast_channel_unlock(chan);
4224
4225 if (!ast_strlen_zero(context)) {
4226 pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context);
4227 }
4228
4229 for (digit = feature_code; *digit; ++digit) {
4230 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *digit };
4231 ast_queue_frame(chan, &f);
4232 }
4233
4234 for (digit = exten; *digit; ++digit) {
4235 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *digit };
4236 ast_queue_frame(chan, &f);
4237 }
4238
4239 chan = ast_channel_unref(chan);
4240
4241 astman_send_ack(s, m, "Atxfer successfully queued");
4242
4243 return 0;
4244}
char digit
#define ast_channel_lock(chan)
Definition channel.h:2983
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition channel.c:1171
#define ast_channel_unlock(chan)
Definition channel.h:2984
static const char name[]
Definition format_mp3.c:68
#define AST_FEATURE_MAX_LEN
int ast_get_builtin_feature(struct ast_channel *chan, const char *feature, char *buf, size_t len)
Get the DTMF code for a builtin feature.
#define AST_FRAME_DTMF
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
char exten[AST_MAX_EXTENSION]
char context[AST_MAX_CONTEXT]
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass

References ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, AST_FEATURE_MAX_LEN, AST_FRAME_DTMF, ast_get_builtin_feature(), ast_queue_frame(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), digit, ast_frame_subclass::integer, name, NULL, pbx_builtin_setvar_helper(), and ast_frame::subclass.

Referenced by __init_manager().

◆ action_blind_transfer()

static int action_blind_transfer ( struct mansession s,
const struct message m 
)
static

Definition at line 4146 of file manager.c.

4147{
4148 const char *name = astman_get_header(m, "Channel");
4149 const char *exten = astman_get_header(m, "Exten");
4150 const char *context = astman_get_header(m, "Context");
4151 struct ast_channel *chan;
4152
4153 if (ast_strlen_zero(name)) {
4154 astman_send_error(s, m, "No channel specified");
4155 return 0;
4156 }
4157
4158 if (ast_strlen_zero(exten)) {
4159 astman_send_error(s, m, "No extension specified");
4160 return 0;
4161 }
4162
4164 if (!chan) {
4165 astman_send_error(s, m, "Channel specified does not exist");
4166 return 0;
4167 }
4168
4169 if (ast_strlen_zero(context)) {
4171 }
4172
4173 switch (ast_bridge_transfer_blind(1, chan, exten, context, NULL, NULL)) {
4175 astman_send_error(s, m, "Transfer not permitted");
4176 break;
4178 astman_send_error(s, m, "Transfer invalid");
4179 break;
4181 astman_send_error(s, m, "Transfer failed");
4182 break;
4184 astman_send_ack(s, m, "Transfer succeeded");
4185 break;
4186 }
4187
4188 ast_channel_unref(chan);
4189 return 0;
4190}
enum ast_transfer_result ast_bridge_transfer_blind(int is_external, struct ast_channel *transferer, const char *exten, const char *context, transfer_channel_cb new_channel_cb, void *user_data)
Blind transfer target to the extension and context provided.
Definition bridge.c:4634
@ AST_BRIDGE_TRANSFER_NOT_PERMITTED
Definition bridge.h:1163
@ AST_BRIDGE_TRANSFER_SUCCESS
Definition bridge.h:1161
@ AST_BRIDGE_TRANSFER_INVALID
Definition bridge.h:1165
@ AST_BRIDGE_TRANSFER_FAIL
Definition bridge.h:1167
const char * ast_channel_context(const struct ast_channel *chan)

References ast_bridge_transfer_blind(), AST_BRIDGE_TRANSFER_FAIL, AST_BRIDGE_TRANSFER_INVALID, AST_BRIDGE_TRANSFER_NOT_PERMITTED, AST_BRIDGE_TRANSFER_SUCCESS, ast_channel_context(), ast_channel_get_by_name(), ast_channel_unref, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), name, and NULL.

Referenced by __init_manager().

◆ action_cancel_atxfer()

static int action_cancel_atxfer ( struct mansession s,
const struct message m 
)
static

Definition at line 4246 of file manager.c.

4247{
4248 const char *name = astman_get_header(m, "Channel");
4249 struct ast_channel *chan = NULL;
4250 char *feature_code;
4251 const char *digit;
4252
4253 if (ast_strlen_zero(name)) {
4254 astman_send_error(s, m, "No channel specified");
4255 return 0;
4256 }
4257
4258 if (!(chan = ast_channel_get_by_name(name))) {
4259 astman_send_error(s, m, "Channel specified does not exist");
4260 return 0;
4261 }
4262
4263 ast_channel_lock(chan);
4264 feature_code = ast_get_chan_features_atxferabort(chan);
4265 ast_channel_unlock(chan);
4266
4267 if (!feature_code) {
4268 astman_send_error(s, m, "No disconnect feature code found");
4269 ast_channel_unref(chan);
4270 return 0;
4271 }
4272
4273 for (digit = feature_code; *digit; ++digit) {
4274 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *digit };
4275 ast_queue_frame(chan, &f);
4276 }
4277 ast_free(feature_code);
4278
4279 chan = ast_channel_unref(chan);
4280
4281 astman_send_ack(s, m, "CancelAtxfer successfully queued");
4282
4283 return 0;
4284}
#define ast_free(a)
Definition astmm.h:180
char * ast_get_chan_features_atxferabort(struct ast_channel *chan)
Get the transfer configuration option atxferabort.

References ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, AST_FRAME_DTMF, ast_free, ast_get_chan_features_atxferabort(), ast_queue_frame(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), digit, ast_frame_subclass::integer, name, NULL, and ast_frame::subclass.

Referenced by __init_manager().

◆ action_challenge()

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

Definition at line 3451 of file manager.c.

3452{
3453 const char *authtype = astman_get_header(m, "AuthType");
3454
3455 if (!strcasecmp(authtype, "MD5")) {
3457 snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
3458 }
3459 mansession_lock(s);
3460 astman_start_ack(s, m);
3461 astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
3463 } else {
3464 astman_send_error(s, m, "Must specify AuthType");
3465 }
3466 return 0;
3467}
static void mansession_unlock(struct mansession *s)
Unlock the 'mansession' structure.
Definition manager.c:2019
static void mansession_lock(struct mansession *s)
Lock the 'mansession' structure.
Definition manager.c:2013
static void astman_start_ack(struct mansession *s, const struct message *m)
Definition manager.c:1958
void astman_append(struct mansession *s, const char *fmt,...)
Definition manager.c:1842
char challenge[10]
Definition manager.c:281
struct mansession_session * session
Definition manager.c:315
long int ast_random(void)
Definition utils.c:2346

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

Referenced by __init_manager().

◆ action_command()

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

Manager command "command" - execute CLI command.

Definition at line 4323 of file manager.c.

4324{
4325 const char *cmd = astman_get_header(m, "Command");
4326 char *buf = NULL, *final_buf = NULL, *delim, *output;
4327 char template[] = "/tmp/ast-ami-XXXXXX"; /* template for temporary file */
4328 int fd, ret;
4329 off_t len;
4330
4331 if (ast_strlen_zero(cmd)) {
4332 astman_send_error(s, m, "No command provided");
4333 return 0;
4334 }
4335
4336 if (check_blacklist(cmd)) {
4337 astman_send_error(s, m, "Command blacklisted");
4338 return 0;
4339 }
4340
4341 if ((fd = mkstemp(template)) < 0) {
4342 astman_send_error_va(s, m, "Failed to create temporary file: %s", strerror(errno));
4343 return 0;
4344 }
4345
4346 ret = ast_cli_command(fd, cmd);
4347 astman_send_response_full(s, m, ret == RESULT_SUCCESS ? "Success" : "Error", MSG_MOREDATA, NULL);
4348
4349 /* Determine number of characters available */
4350 if ((len = lseek(fd, 0, SEEK_END)) < 0) {
4351 astman_append(s, "Message: Failed to determine number of characters: %s\r\n", strerror(errno));
4352 goto action_command_cleanup;
4353 }
4354
4355 /* This has a potential to overflow the stack. Hence, use the heap. */
4356 buf = ast_malloc(len + 1);
4357 final_buf = ast_malloc(len + 1);
4358
4359 if (!buf || !final_buf) {
4360 astman_append(s, "Message: Memory allocation failure\r\n");
4361 goto action_command_cleanup;
4362 }
4363
4364 if (lseek(fd, 0, SEEK_SET) < 0) {
4365 astman_append(s, "Message: Failed to set position on temporary file: %s\r\n", strerror(errno));
4366 goto action_command_cleanup;
4367 }
4368
4369 if (read(fd, buf, len) < 0) {
4370 astman_append(s, "Message: Failed to read from temporary file: %s\r\n", strerror(errno));
4371 goto action_command_cleanup;
4372 }
4373
4374 buf[len] = '\0';
4375 term_strip(final_buf, buf, len);
4376 final_buf[len] = '\0';
4377
4378 /* Trim trailing newline */
4379 if (len && final_buf[len - 1] == '\n') {
4380 final_buf[len - 1] = '\0';
4381 }
4382
4383 astman_append(s, "Message: Command output follows\r\n");
4384
4385 delim = final_buf;
4386 while ((output = strsep(&delim, "\n"))) {
4387 astman_append(s, "Output: %s\r\n", output);
4388 }
4389
4390action_command_cleanup:
4391 astman_append(s, "\r\n");
4392
4393 close(fd);
4394 unlink(template);
4395
4396 ast_free(buf);
4397 ast_free(final_buf);
4398
4399 return 0;
4400}
char * strsep(char **str, const char *delims)
#define ast_malloc(len)
A wrapper for malloc()
Definition astmm.h:191
#define RESULT_SUCCESS
Definition cli.h:40
#define ast_cli_command(fd, s)
Definition cli.h:232
char buf[BUFSIZE]
Definition eagi_proxy.c:66
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void astman_send_error_va(struct mansession *s, const struct message *m, const char *fmt,...)
Send error in manager transaction (with va_args support)
Definition manager.c:1926
static void astman_send_response_full(struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag)
send a response with an optional message, and terminate it with an empty line. m is used only to grab...
Definition manager.c:1885
static int check_blacklist(const char *cmd)
Definition manager.c:4287
#define MSG_MOREDATA
Definition manager.c:1876
int errno
char * term_strip(char *outbuf, const char *inbuf, int maxout)
Remove colorings from a specified string.
Definition term.c:362

References ast_cli_command, ast_free, ast_malloc, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_send_error_va(), astman_send_response_full(), buf, check_blacklist(), errno, len(), MSG_MOREDATA, NULL, RESULT_SUCCESS, strsep(), and term_strip().

Referenced by __init_manager().

◆ action_coresettings()

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

Show PBX core settings information.

Definition at line 6525 of file manager.c.

6526{
6527 const char *actionid = astman_get_header(m, "ActionID");
6528 char idText[150];
6529
6530 if (!ast_strlen_zero(actionid)) {
6531 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
6532 } else {
6533 idText[0] = '\0';
6534 }
6535
6536 astman_append(s, "Response: Success\r\n"
6537 "%s"
6538 "AMIversion: %s\r\n"
6539 "AsteriskVersion: %s\r\n"
6540 "SystemName: %s\r\n"
6541 "CoreMaxCalls: %d\r\n"
6542 "CoreMaxLoadAvg: %f\r\n"
6543 "CoreRunUser: %s\r\n"
6544 "CoreRunGroup: %s\r\n"
6545 "CoreMaxFilehandles: %d\r\n"
6546 "CoreRealTimeEnabled: %s\r\n"
6547 "CoreCDRenabled: %s\r\n"
6548 "CoreHTTPenabled: %s\r\n"
6549 "SoundsSearchCustomDir: %s\r\n"
6550 "\r\n",
6551 idText,
6564 );
6565 return 0;
6566}
const char * ast_get_version(void)
Retrieve the Asterisk version string.
int ast_cdr_is_enabled(void)
Return TRUE if CDR subsystem is enabled.
Definition cdr.c:2994
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
Definition cli.h:71
int ast_webmanager_check_enabled(void)
Check if AMI/HTTP is enabled.
Definition manager.c:688
int ast_option_maxfiles
Definition options.c:82
int ast_option_maxcalls
Definition options.c:80
double ast_option_maxload
Definition options.c:78
int ast_realtime_enabled(void)
Check if there's any realtime engines loaded.
#define AMI_VERSION
Definition manager.h:57
#define ast_opt_sounds_search_custom
Definition options.h:148
const char * ast_config_AST_RUN_GROUP
Definition options.c:170
const char * ast_config_AST_RUN_USER
Definition options.c:169

References AMI_VERSION, ast_cdr_is_enabled(), AST_CLI_YESNO, ast_config_AST_RUN_GROUP, ast_config_AST_RUN_USER, ast_config_AST_SYSTEM_NAME, ast_get_version(), ast_opt_sounds_search_custom, ast_option_maxcalls, ast_option_maxfiles, ast_option_maxload, ast_realtime_enabled(), ast_strlen_zero(), ast_webmanager_check_enabled(), astman_append(), and astman_get_header().

Referenced by __init_manager().

◆ action_coreshowchannelmap()

static int action_coreshowchannelmap ( struct mansession s,
const struct message m 
)
static

Manager command "CoreShowChannelMap" - Lists all channels connected to the specified channel.

Definition at line 6811 of file manager.c.

6812{
6813 const char *actionid = astman_get_header(m, "ActionID");
6814 const char *channel_name = astman_get_header(m, "Channel");
6815 char *current_channel_name;
6816 char id_text[256];
6817 int total = 0;
6818 struct ao2_container *channel_map;
6819 struct ao2_iterator i;
6820 RAII_VAR(struct ast_bridge_snapshot *, bridge_snapshot, NULL, ao2_cleanup);
6821 RAII_VAR(struct ast_channel_snapshot *, channel_snapshot, NULL, ao2_cleanup);
6822
6823 if (!ast_strlen_zero(actionid)) {
6824 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
6825 } else {
6826 id_text[0] = '\0';
6827 }
6828
6829 if (ast_strlen_zero(channel_name)) {
6830 astman_send_error(s, m, "CoreShowChannelMap requires a channel.\n");
6831 return 0;
6832 }
6833
6834 channel_snapshot = ast_channel_snapshot_get_latest_by_name(channel_name);
6835 if (!channel_snapshot) {
6836 astman_send_error(s, m, "Could not get channel snapshot\n");
6837 return 0;
6838 }
6839
6840 if (ast_strlen_zero(channel_snapshot->bridge->id)) {
6841 astman_send_listack(s, m, "Channel map will follow", "start");
6842 astman_send_list_complete_start(s, m, "CoreShowChannelMapComplete", 0);
6844 return 0;
6845 }
6846
6847 bridge_snapshot = ast_bridge_get_snapshot_by_uniqueid(channel_snapshot->bridge->id);
6848 if (!bridge_snapshot) {
6849 astman_send_listack(s, m, "Channel map will follow", "start");
6850 astman_send_list_complete_start(s, m, "CoreShowChannelMapComplete", 0);
6852 return 0;
6853 }
6854
6856 if (!channel_map) {
6857 astman_send_error(s, m, "Could not create channel map\n");
6858 return 0;
6859 }
6860
6861 astman_send_listack(s, m, "Channel map will follow", "start");
6862
6863 if (coreshowchannelmap_add_connected_channels(channel_map, channel_snapshot, bridge_snapshot)) {
6864 astman_send_error(s, m, "Could not complete channel map\n");
6865 ao2_ref(channel_map, -1);
6866 return 0;
6867 }
6868
6869 i = ao2_iterator_init(channel_map, 0);
6870 while ((current_channel_name = ao2_iterator_next(&i))) {
6871 astman_append(s,
6872 "Event: CoreShowChannelMap\r\n"
6873 "%s"
6874 "Channel: %s\r\n"
6875 "ConnectedChannel: %s\r\n\r\n",
6876 id_text,
6877 channel_name,
6878 current_channel_name);
6879 total++;
6880 }
6882
6883 ao2_ref(channel_map, -1);
6884 astman_send_list_complete_start(s, m, "CoreShowChannelMapComplete", total);
6886
6887 return 0;
6888}
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition astobj2.h:367
@ AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT
Reject duplicate objects in container.
Definition astobj2.h:1201
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition manager.c:1963
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition manager.c:1999
static int coreshowchannelmap_add_connected_channels(struct ao2_container *channel_map, struct ast_channel_snapshot *channel_snapshot, struct ast_bridge_snapshot *bridge_snapshot)
Recursive function to get all channels in a bridge. Follow local channels as well.
Definition manager.c:6727
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition manager.c:2007
struct ast_channel_snapshot * ast_channel_snapshot_get_latest_by_name(const char *name)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object,...
static int total
Definition res_adsi.c:970
struct ast_bridge_snapshot * ast_bridge_get_snapshot_by_uniqueid(const char *bridge_id)
Returns the current snapshot for the bridge.
struct ao2_container * ast_str_container_alloc_options(enum ao2_alloc_opts opts, int buckets)
Allocates a hash container for bare strings.
Definition strings.c:200
Structure that contains a snapshot of information about a bridge.
Definition bridge.h:318
Structure representing a snapshot of channel state.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_cleanup, AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_bridge_get_snapshot_by_uniqueid(), ast_channel_snapshot_get_latest_by_name(), ast_str_container_alloc_options(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), coreshowchannelmap_add_connected_channels(), NULL, RAII_VAR, and total.

Referenced by __init_manager().

◆ action_coreshowchannels()

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

6644{
6645 const char *actionid = astman_get_header(m, "ActionID");
6646 char idText[256];
6647 int numchans = 0;
6648 struct ao2_container *channels;
6649 struct ao2_iterator it_chans;
6650 struct ast_channel_snapshot *cs;
6651
6652 if (!ast_strlen_zero(actionid)) {
6653 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
6654 } else {
6655 idText[0] = '\0';
6656 }
6657
6659
6660 astman_send_listack(s, m, "Channels will follow", "start");
6661
6662 it_chans = ao2_iterator_init(channels, 0);
6663 for (; (cs = ao2_iterator_next(&it_chans)); ao2_ref(cs, -1)) {
6665 char durbuf[16] = "";
6666
6667 if (!built) {
6668 continue;
6669 }
6670
6671 if (!ast_tvzero(cs->base->creationtime)) {
6672 int duration, durh, durm, durs;
6673
6674 duration = (int)(ast_tvdiff_ms(ast_tvnow(), cs->base->creationtime) / 1000);
6675 durh = duration / 3600;
6676 durm = (duration % 3600) / 60;
6677 durs = duration % 60;
6678 snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
6679 }
6680
6681 astman_append(s,
6682 "Event: CoreShowChannel\r\n"
6683 "%s"
6684 "%s"
6685 "Application: %s\r\n"
6686 "ApplicationData: %s\r\n"
6687 "Duration: %s\r\n"
6688 "BridgeId: %s\r\n"
6689 "\r\n",
6690 idText,
6691 ast_str_buffer(built),
6692 cs->dialplan->appl,
6693 cs->dialplan->data,
6694 durbuf,
6695 cs->bridge->id);
6696
6697 numchans++;
6698
6699 ast_free(built);
6700 }
6701 ao2_iterator_destroy(&it_chans);
6702
6703 astman_send_list_complete(s, m, "CoreShowChannelsComplete", numchans);
6704
6705 ao2_ref(channels, -1);
6706 return 0;
6707}
static struct channel_usage channels
static void astman_send_list_complete(struct mansession *s, const struct message *m, const char *event_name, int count)
Definition manager.c:1990
struct ao2_container * ast_channel_cache_by_name(void)
Secondary channel cache, indexed by name.
struct ast_str * ast_manager_build_channel_state_string_prefix(const struct ast_channel_snapshot *snapshot, const char *prefix)
Generate the AMI message body from a channel snapshot.
const ast_string_field data
const ast_string_field appl
struct ast_channel_snapshot_dialplan * dialplan
struct ast_channel_snapshot_bridge * bridge
struct ast_channel_snapshot_base * base
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition time.h:117
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition time.h:107

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_channel_snapshot_dialplan::appl, ast_channel_cache_by_name(), ast_free, ast_manager_build_channel_state_string_prefix(), ast_str_buffer(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), astman_append(), astman_get_header(), astman_send_list_complete(), astman_send_listack(), ast_channel_snapshot::base, ast_channel_snapshot::bridge, channels, ast_channel_snapshot_base::creationtime, ast_channel_snapshot_dialplan::data, ast_channel_snapshot::dialplan, and ast_channel_snapshot_bridge::id.

Referenced by __init_manager().

◆ action_corestatus()

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

Show PBX core status information.

Definition at line 6569 of file manager.c.

6570{
6571 const char *actionid = astman_get_header(m, "ActionID");
6572 char idText[150];
6573 char startuptime[150], startupdate[150];
6574 char reloadtime[150], reloaddate[150];
6575 struct ast_tm tm;
6576
6577 if (!ast_strlen_zero(actionid)) {
6578 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid);
6579 } else {
6580 idText[0] = '\0';
6581 }
6582
6584 ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm);
6585 ast_strftime(startupdate, sizeof(startupdate), "%Y-%m-%d", &tm);
6587 ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm);
6588 ast_strftime(reloaddate, sizeof(reloaddate), "%Y-%m-%d", &tm);
6589
6590 astman_append(s, "Response: Success\r\n"
6591 "%s"
6592 "CoreStartupDate: %s\r\n"
6593 "CoreStartupTime: %s\r\n"
6594 "CoreReloadDate: %s\r\n"
6595 "CoreReloadTime: %s\r\n"
6596 "CoreCurrentCalls: %d\r\n"
6597 "CoreProcessedCalls: %d\r\n"
6598 "\r\n",
6599 idText,
6600 startupdate,
6601 startuptime,
6602 reloaddate,
6603 reloadtime,
6606 );
6607 return 0;
6608}
int ast_active_channels(void)
returns number of active/allocated channels
Definition channel.c:500
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition localtime.c:1739
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition localtime.c:2524
struct timeval ast_lastreloadtime
Definition asterisk.c:345
struct timeval ast_startuptime
Definition asterisk.c:344
int ast_processed_calls(void)
Retrieve the total number of calls processed through the PBX since last restart.
Definition pbx.c:3325

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

Referenced by __init_manager().

◆ action_createconfig()

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

Definition at line 3044 of file manager.c.

3045{
3046 int fd;
3047 const char *fn = astman_get_header(m, "Filename");
3048 char *stripped_filename;
3049 RAII_VAR(char *, filepath, NULL, ast_free);
3050 RAII_VAR(char *, real_dir, NULL, ast_std_free);
3051 RAII_VAR(char *, real_path, NULL, ast_free);
3052 char *filename;
3053
3054 if (ast_strlen_zero(fn)) {
3055 astman_send_error(s, m, "Filename not specified");
3056 return 0;
3057 }
3058
3059 stripped_filename = ast_strip(ast_strdupa(fn));
3060
3061 /* If the file name is relative, prepend ast_config_AST_CONFIG_DIR */
3062 if (stripped_filename[0] != '/') {
3063 if (ast_asprintf(&filepath, "%s/%s", ast_config_AST_CONFIG_DIR, stripped_filename) == -1) {
3064 return -1;
3065 }
3066 } else {
3067 filepath = ast_strdup(stripped_filename);
3068 }
3069
3070 /*
3071 * We can't call is_restricted_file() here because it uses realpath() and...
3072 *
3073 * realpath() and other functions that canonicalize paths won't work with
3074 * a filename that doesn't exist, so we need to separate the directory
3075 * from the filename and canonicalize the directory first. We have to do
3076 * the separation manually because dirname() and basename() aren't all
3077 * that friendly to multi-threaded programs and there are different
3078 * versions of basename for glibc and POSIX.
3079 */
3080
3081 filename = strrchr(filepath, '/');
3082 if (!filename) {
3083 astman_send_error(s, m, "Filename is invalid");
3084 return 0;
3085 }
3086 *filename = '\0';
3087 filename++;
3088
3089 /* filepath just has the directory now so canonicalize it. */
3090 real_dir = realpath(filepath, NULL);
3091 if (ast_strlen_zero(real_dir)) {
3092 astman_send_error(s, m, strerror(errno));
3093 return 0;
3094 }
3095
3096 /* Check if the directory is restricted. */
3098 astman_send_error(s, m, "File requires escalated privileges");
3099 return 0;
3100 }
3101
3102 /* Create the final file path. */
3103 if (ast_asprintf(&real_path, "%s/%s", real_dir, filename) == -1) {
3104 astman_send_error(s, m, strerror(errno));
3105 return -1;
3106 }
3107
3108 if ((fd = open(real_path, O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
3109 close(fd);
3110 astman_send_ack(s, m, "New configuration file created successfully");
3111 } else {
3112 astman_send_error(s, m, strerror(errno));
3113 }
3114
3115 return 0;
3116}
#define AST_FILE_MODE
Definition asterisk.h:32
void ast_std_free(void *ptr)
Definition astmm.c:1734
#define ast_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition astmm.h:267
static int live_dangerously
Set to true (non-zero) to globally allow all dangerous AMI actions to run.
Definition manager.c:184
const char * ast_config_AST_CONFIG_DIR
Definition options.c:152
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
Definition strings.h:97
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition strings.h:223

References ast_asprintf, ast_begins_with(), ast_config_AST_CONFIG_DIR, AST_FILE_MODE, ast_free, ast_std_free(), ast_strdup, ast_strdupa, ast_strip(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), errno, live_dangerously, NULL, and RAII_VAR.

Referenced by __init_manager().

◆ action_destroy()

static void action_destroy ( void *  obj)
static

Definition at line 7894 of file manager.c.

7895{
7896 struct manager_action *doomed = obj;
7897
7898 if (doomed->synopsis) {
7899 /* The string fields were initialized. */
7901 }
7902 ao2_cleanup(doomed->final_response);
7903 ao2_cleanup(doomed->list_responses);
7904}
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
struct ast_xml_doc_item * final_response
Definition manager.h:167
const ast_string_field synopsis
Definition manager.h:163
struct ast_xml_doc_item * list_responses
Definition manager.h:165

References ao2_cleanup, ast_string_field_free_memory, manager_action::final_response, manager_action::list_responses, and manager_action::synopsis.

Referenced by ast_manager_register2().

◆ action_events()

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

Definition at line 3353 of file manager.c.

3354{
3355 const char *mask = astman_get_header(m, "EventMask");
3356 int res, x;
3357 const char *id = astman_get_header(m, "ActionID");
3358 char id_text[256];
3359
3360 if (!ast_strlen_zero(id)) {
3361 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
3362 } else {
3363 id_text[0] = '\0';
3364 }
3365
3366 res = set_eventmask(s, mask);
3368 /* if this option is set we should not return a response on
3369 * error, or when all events are set */
3370
3371 if (res > 0) {
3372 for (x = 0; x < ARRAY_LEN(perms); x++) {
3373 if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) {
3374 return 0;
3375 }
3376 }
3377 astman_append(s, "Response: Success\r\n%s"
3378 "Events: On\r\n\r\n", id_text);
3379 } else if (res == 0)
3380 astman_append(s, "Response: Success\r\n%s"
3381 "Events: Off\r\n\r\n", id_text);
3382 return 0;
3383 }
3384
3385 if (res > 0)
3386 astman_append(s, "Response: Success\r\n%s"
3387 "Events: On\r\n\r\n", id_text);
3388 else if (res == 0)
3389 astman_append(s, "Response: Success\r\n%s"
3390 "Events: Off\r\n\r\n", id_text);
3391 else
3392 astman_send_error(s, m, "Invalid event mask");
3393
3394 return 0;
3395}
static int broken_events_action
Definition manager.c:153
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 ',...
Definition manager.c:2028
static const struct permalias perms[]
int num
Definition manager.c:698
#define ARRAY_LEN(a)
Definition utils.h:706

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

Referenced by __init_manager().

◆ action_extensionstate()

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

Definition at line 5508 of file manager.c.

5509{
5510 const char *exten = astman_get_header(m, "Exten");
5511 const char *context = astman_get_header(m, "Context");
5512 char hint[256];
5513 int status;
5514
5515 if (ast_strlen_zero(exten)) {
5516 astman_send_error(s, m, "Extension not specified");
5517 return 0;
5518 }
5519 if (ast_strlen_zero(context)) {
5520 context = "default";
5521 }
5522 status = ast_extension_state(NULL, context, exten);
5523 hint[0] = '\0';
5524 ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten);
5525 astman_start_ack(s, m);
5526 astman_append(s, "Message: Extension Status\r\n"
5527 "Exten: %s\r\n"
5528 "Context: %s\r\n"
5529 "Hint: %s\r\n"
5530 "Status: %d\r\n"
5531 "StatusText: %s\r\n"
5532 "\r\n",
5533 exten, context, hint, status,
5535 return 0;
5536}
jack_status_t status
Definition app_jack.c:149
const char * ast_extension_state2str(int extension_state)
Return string representation of the state of an extension.
int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
If an extension hint exists, return non-zero.
Definition pbx.c:2697
int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
Uses hint and devicestate callback to get the state of an extension.

References ast_extension_state(), ast_extension_state2str(), ast_get_hint(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), NULL, and status.

Referenced by __init_manager().

◆ action_filter()

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

Manager command to add an event filter to a manager session.

See also
For more details look at manager_add_filter

Definition at line 5733 of file manager.c.

5734{
5735 const char *match_criteria = astman_get_header(m, "MatchCriteria");
5736 const char *filter = astman_get_header(m, "Filter");
5737 const char *operation = astman_get_header(m, "Operation");
5738 int res;
5739
5740 if (!strcasecmp(operation, "Add")) {
5741 char *criteria;
5742 int have_match = !ast_strlen_zero(match_criteria);
5743
5744 /* Create an eventfilter expression.
5745 * eventfilter[(match_criteria)]
5746 */
5747 res = ast_asprintf(&criteria, "eventfilter%s%s%s",
5748 S_COR(have_match, "(", ""), S_OR(match_criteria, ""),
5749 S_COR(have_match, ")", ""));
5750 if (res <= 0) {
5751 astman_send_error(s, m, "Internal Error. Failed to allocate storage for filter type");
5752 return 0;
5753 }
5754
5756 ast_free(criteria);
5757 if (res != FILTER_SUCCESS) {
5758 if (res == FILTER_ALLOC_FAILED) {
5759 astman_send_error(s, m, "Internal Error. Failed to allocate regex for filter");
5760 return 0;
5761 } else if (res == FILTER_COMPILE_FAIL) {
5762 astman_send_error(s, m,
5763 "Filter did not compile. Check the syntax of the filter given.");
5764 return 0;
5765 } else if (res == FILTER_FORMAT_ERROR) {
5766 astman_send_error(s, m,
5767 "Filter was formatted incorrectly. Check the syntax of the filter given.");
5768 return 0;
5769 } else {
5770 astman_send_error(s, m, "Internal Error. Failed adding filter.");
5771 return 0;
5772 }
5773 }
5774
5775 astman_send_ack(s, m, "Success");
5776 return 0;
5777 }
5778
5779 astman_send_error(s, m, "Unknown operation");
5780 return 0;
5781}
static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
static enum add_filter_result manager_add_filter(const char *criteria, const char *filter_pattern, struct ao2_container *includefilters, struct ao2_container *excludefilters)
Add an event filter to a manager session.
Definition manager.c:5800
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition strings.h:80
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition strings.h:87
struct ao2_container * excludefilters
Definition manager.c:288
struct ao2_container * includefilters
Definition manager.c:287

References ast_asprintf, ast_free, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), mansession_session::excludefilters, filter(), FILTER_ALLOC_FAILED, FILTER_COMPILE_FAIL, FILTER_FORMAT_ERROR, FILTER_SUCCESS, mansession_session::includefilters, manager_add_filter(), S_COR, S_OR, and mansession::session.

Referenced by __init_manager().

◆ action_find()

static struct manager_action * action_find ( const char *  name)
static

Definition at line 425 of file manager.c.

426{
427 struct manager_action *act;
428
431 if (!strcasecmp(name, act->action)) {
432 ao2_t_ref(act, +1, "found action object");
433 break;
434 }
435 }
437
438 return act;
439}
#define ao2_t_ref(o, delta, tag)
Definition astobj2.h:460
list of actions registered
Definition manager.c:354
struct manager_action::@251 list
const char * action
Definition manager.h:156

References manager_action::action, ao2_t_ref, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, manager_action::list, and name.

Referenced by ast_hook_send_action(), and process_message().

◆ action_getconfig()

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

Definition at line 2448 of file manager.c.

2449{
2450 struct ast_config *cfg;
2451 const char *fn = astman_get_header(m, "Filename");
2452 const char *category = astman_get_header(m, "Category");
2453 const char *filter = astman_get_header(m, "Filter");
2454 const char *category_name;
2455 int catcount = 0;
2456 int lineno = 0;
2457 int ret = 0;
2458 struct ast_category *cur_category = NULL;
2459 struct ast_variable *v;
2460 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
2461
2462 if (ast_strlen_zero(fn)) {
2463 astman_send_error(s, m, "Filename not specified");
2464 return 0;
2465 }
2466
2467 ret = is_restricted_file(fn);
2468 if (ret == 1) {
2469 astman_send_error(s, m, "File requires escalated privileges");
2470 return 0;
2471 } else if (ret == -1) {
2472 astman_send_error(s, m, "Config file not found");
2473 return 0;
2474 }
2475
2476 cfg = ast_config_load2(fn, "manager", config_flags);
2477 if (cfg == CONFIG_STATUS_FILEMISSING) {
2478 astman_send_error(s, m, "Config file not found");
2479 return 0;
2480 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2481 astman_send_error(s, m, "Config file has invalid format");
2482 return 0;
2483 }
2484
2485 astman_start_ack(s, m);
2486 while ((cur_category = ast_category_browse_filtered(cfg, category, cur_category, filter))) {
2487 struct ast_str *templates;
2488
2489 category_name = ast_category_get_name(cur_category);
2490 lineno = 0;
2491 astman_append(s, "Category-%06d: %s\r\n", catcount, category_name);
2492
2493 if (ast_category_is_template(cur_category)) {
2494 astman_append(s, "IsTemplate-%06d: %d\r\n", catcount, 1);
2495 }
2496
2497 if ((templates = ast_category_get_templates(cur_category))
2498 && ast_str_strlen(templates) > 0) {
2499 astman_append(s, "Templates-%06d: %s\r\n", catcount, ast_str_buffer(templates));
2501 }
2502
2503 for (v = ast_category_first(cur_category); v; v = v->next) {
2504 astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value);
2505 }
2506
2507 catcount++;
2508 }
2509
2510 if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
2511 astman_append(s, "No categories found\r\n");
2512 }
2513
2514 ast_config_destroy(cfg);
2515 astman_append(s, "\r\n");
2516
2517 return 0;
2518}
static int is_restricted_file(const char *filename)
Check if a file is restricted or not.
Definition manager.c:2415
@ CONFIG_FLAG_NOCACHE
@ CONFIG_FLAG_WITHCOMMENTS
const char * ast_category_get_name(const struct ast_category *category)
Return the name of the category.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
#define CONFIG_STATUS_FILEMISSING
struct ast_str * ast_category_get_templates(const struct ast_category *category)
Return the template names this category inherits from.
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
int ast_category_is_template(const struct ast_category *category)
Check if category is a template.
struct ast_variable * ast_category_first(struct ast_category *cat)
given a pointer to a category, return the root variable.
struct ast_category * ast_category_browse_filtered(struct ast_config *config, const char *category_name, struct ast_category *prev, const char *filter)
Browse categories with filters.
size_t attribute_pure ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition strings.h:730
Structure used to handle boolean flags.
Definition utils.h:220
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next

References ast_category_browse_filtered(), ast_category_first(), ast_category_get_name(), ast_category_get_templates(), ast_category_is_template(), ast_config_destroy(), ast_config_load2(), ast_free, ast_str_buffer(), ast_str_strlen(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, filter(), is_restricted_file(), ast_variable::name, ast_variable::next, NULL, and ast_variable::value.

Referenced by __init_manager().

◆ action_getconfigjson()

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

Definition at line 2596 of file manager.c.

2597{
2598 struct ast_config *cfg;
2599 const char *fn = astman_get_header(m, "Filename");
2600 const char *filter = astman_get_header(m, "Filter");
2601 const char *category = astman_get_header(m, "Category");
2602 struct ast_category *cur_category = NULL;
2603 const char *category_name;
2604 struct ast_variable *v;
2605 int comma1 = 0;
2606 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
2607
2608 if (ast_strlen_zero(fn)) {
2609 astman_send_error(s, m, "Filename not specified");
2610 return 0;
2611 }
2612
2613 if (is_restricted_file(fn)) {
2614 astman_send_error(s, m, "File requires escalated privileges");
2615 return 0;
2616 }
2617
2618 if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
2619 astman_send_error(s, m, "Config file not found");
2620 return 0;
2621 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2622 astman_send_error(s, m, "Config file has invalid format");
2623 return 0;
2624 }
2625
2626 astman_start_ack(s, m);
2627 astman_append(s, "JSON: {");
2628 while ((cur_category = ast_category_browse_filtered(cfg, category, cur_category, filter))) {
2629 int comma2 = 0;
2630 struct ast_str *templates;
2631
2632 category_name = ast_category_get_name(cur_category);
2633 astman_append(s, "%s\"", comma1 ? "," : "");
2634 astman_append_json(s, category_name);
2635 astman_append(s, "\":{");
2636 comma1 = 1;
2637
2638 if (ast_category_is_template(cur_category)) {
2639 astman_append(s, "\"istemplate\":1");
2640 comma2 = 1;
2641 }
2642
2643 if ((templates = ast_category_get_templates(cur_category))
2644 && ast_str_strlen(templates) > 0) {
2645 astman_append(s, "%s", comma2 ? "," : "");
2646 astman_append(s, "\"templates\":\"%s\"", ast_str_buffer(templates));
2648 comma2 = 1;
2649 }
2650
2651 for (v = ast_category_first(cur_category); v; v = v->next) {
2652 astman_append(s, "%s\"", comma2 ? "," : "");
2653 astman_append_json(s, v->name);
2654 astman_append(s, "\":\"");
2656 astman_append(s, "\"");
2657 comma2 = 1;
2658 }
2659
2660 astman_append(s, "}");
2661 }
2662 astman_append(s, "}\r\n\r\n");
2663
2664 ast_config_destroy(cfg);
2665
2666 return 0;
2667}
static void astman_append_json(struct mansession *s, const char *str)
Definition manager.c:2587

References ast_category_browse_filtered(), ast_category_first(), ast_category_get_name(), ast_category_get_templates(), ast_category_is_template(), ast_config_destroy(), ast_config_load2(), ast_free, ast_str_buffer(), ast_str_strlen(), ast_strlen_zero(), astman_append(), astman_append_json(), astman_get_header(), astman_send_error(), astman_start_ack(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEINVALID, filter(), is_restricted_file(), ast_variable::name, ast_variable::next, NULL, and ast_variable::value.

Referenced by __init_manager().

◆ action_getvar()

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

Definition at line 3629 of file manager.c.

3630{
3631 struct ast_channel *c = NULL;
3632 const char *name = astman_get_header(m, "Channel");
3633 const char *varname = astman_get_header(m, "Variable");
3634 char *varval;
3635 char workspace[1024];
3636
3637 if (ast_strlen_zero(varname)) {
3638 astman_send_error(s, m, "No variable specified");
3639 return 0;
3640 }
3641
3642 /* We don't want users with insufficient permissions using certain functions. */
3644 astman_send_error(s, m, "GetVar Access Forbidden: Variable");
3645 return 0;
3646 }
3647
3648 if (!ast_strlen_zero(name)) {
3649 if (!(c = ast_channel_get_by_name(name))) {
3650 astman_send_error(s, m, "No such channel");
3651 return 0;
3652 }
3653 }
3654
3655 workspace[0] = '\0';
3656 if (varname[strlen(varname) - 1] == ')') {
3657 if (!c) {
3659 if (c) {
3660 ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
3661 } else
3662 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n");
3663 } else {
3664 ast_func_read(c, (char *) varname, workspace, sizeof(workspace));
3665 }
3666 varval = workspace;
3667 } else {
3668 pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL);
3669 }
3670
3671 if (c) {
3673 }
3674
3675 astman_start_ack(s, m);
3676 astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, S_OR(varval, ""));
3677
3678 return 0;
3679}
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition channel.h:1328
static int function_capable_string_allowed_with_auths(const char *evaluating, int writepermlist)
Checks to see if a string which can be used to evaluate functions should be rejected.
Definition manager.c:728
#define LOG_ERROR
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
Retrieve the value of a builtin variable or variable from the channel variable stack.
static struct test_val c

References ast_channel_get_by_name(), ast_channel_unref, ast_dummy_channel_alloc, ast_func_read(), ast_log, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), c, function_capable_string_allowed_with_auths(), LOG_ERROR, name, NULL, pbx_retrieve_variable(), S_OR, mansession::session, and mansession_session::writeperm.

Referenced by __init_manager().

◆ action_hangup()

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

Definition at line 3590 of file manager.c.

3591{
3592 return ast_manager_hangup_helper(s, m,
3594}
void ast_channel_softhangup_withcause_locked(struct ast_channel *chan, int causecode)
Lock the given channel, then request softhangup on the channel with the given causecode.
Definition channel.c:469
int ast_manager_hangup_helper(struct mansession *s, const struct message *m, manager_hangup_handler_t hangup_handler, manager_hangup_cause_validator_t cause_validator)
A manager helper function that hangs up a channel using a supplied channel type specific hangup funct...
Definition manager.c:3469

References ast_channel_softhangup_withcause_locked(), ast_manager_hangup_helper(), and NULL.

Referenced by __init_manager().

◆ action_listcategories()

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

Definition at line 2520 of file manager.c.

2521{
2522 struct ast_config *cfg;
2523 const char *fn = astman_get_header(m, "Filename");
2524 const char *match = astman_get_header(m, "Match");
2525 struct ast_category *category = NULL;
2526 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
2527 int catcount = 0;
2528 int ret = 0;
2529
2530 if (ast_strlen_zero(fn)) {
2531 astman_send_error(s, m, "Filename not specified");
2532 return 0;
2533 }
2534
2535 ret = is_restricted_file(fn);
2536 if (ret == 1) {
2537 astman_send_error(s, m, "File requires escalated privileges");
2538 return 0;
2539 } else if (ret == -1) {
2540 astman_send_error(s, m, "Config file not found");
2541 return 0;
2542 }
2543
2544 if (!(cfg = ast_config_load2(fn, "manager", config_flags))) {
2545 astman_send_error(s, m, "Config file not found");
2546 return 0;
2547 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2548 astman_send_error(s, m, "Config file has invalid format");
2549 return 0;
2550 }
2551
2552 astman_start_ack(s, m);
2553 while ((category = ast_category_browse_filtered(cfg, NULL, category, match))) {
2554 astman_append(s, "Category-%06d: %s\r\n", catcount, ast_category_get_name(category));
2555 catcount++;
2556 }
2557
2558 if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */
2559 astman_append(s, "Error: no categories found\r\n");
2560 }
2561
2562 ast_config_destroy(cfg);
2563 astman_append(s, "\r\n");
2564
2565 return 0;
2566}
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition chan_iax2.c:2401

References ast_category_browse_filtered(), ast_category_get_name(), ast_config_destroy(), ast_config_load2(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEINVALID, is_restricted_file(), match(), and NULL.

Referenced by __init_manager().

◆ action_listcommands()

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

Definition at line 3334 of file manager.c.

3335{
3336 struct manager_action *cur;
3338
3339 astman_start_ack(s, m);
3341 AST_RWLIST_TRAVERSE(&actions, cur, list) {
3342 if ((s->session->writeperm & cur->authority) || cur->authority == 0) {
3343 astman_append(s, "%s: %s (Priv: %s)\r\n",
3344 cur->action, cur->synopsis, authority_to_str(cur->authority, &temp));
3345 }
3346 }
3348 astman_append(s, "\r\n");
3349
3350 return 0;
3351}

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

Referenced by __init_manager().

◆ action_loggerrotate()

static int action_loggerrotate ( struct mansession s,
const struct message m 
)
static

Manager command "LoggerRotate" - reloads and rotates the logger in the same manner as the CLI command 'logger rotate'.

Definition at line 6892 of file manager.c.

6893{
6894 if (ast_logger_rotate()) {
6895 astman_send_error(s, m, "Failed to reload the logger and rotate log files");
6896 return 0;
6897 }
6898
6899 astman_send_ack(s, m, "Reloaded the logger and rotated log files");
6900 return 0;
6901}
int ast_logger_rotate(void)
Reload logger while rotating log files.
Definition logger.c:1307

References ast_logger_rotate(), astman_send_ack(), and astman_send_error().

Referenced by __init_manager().

◆ action_login()

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

Definition at line 3403 of file manager.c.

3404{
3405
3406 /* still authenticated - don't process again */
3407 if (s->session->authenticated) {
3408 astman_send_ack(s, m, "Already authenticated");
3409 return 0;
3410 }
3411
3412 if (authenticate(s, m)) {
3413 sleep(1);
3414 astman_send_error(s, m, "Authentication failed");
3415 return -1;
3416 }
3417 s->session->authenticated = 1;
3420 ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_sockaddr_stringify_addr(&s->session->addr));
3421 }
3422 astman_send_ack(s, m, "Authentication accepted");
3424 && ast_fully_booted) {
3426 const char *cat_str = authority_to_str(EVENT_FLAG_SYSTEM, &auth);
3427 long uptime = 0;
3428 long lastreloaded = 0;
3429 struct timeval tmp;
3430 struct timeval curtime = ast_tvnow();
3431
3432 if (ast_startuptime.tv_sec) {
3433 tmp = ast_tvsub(curtime, ast_startuptime);
3434 uptime = tmp.tv_sec;
3435 }
3436
3437 if (ast_lastreloadtime.tv_sec) {
3438 tmp = ast_tvsub(curtime, ast_lastreloadtime);
3439 lastreloaded = tmp.tv_sec;
3440 }
3441
3442 astman_append(s, "Event: FullyBooted\r\n"
3443 "Privilege: %s\r\n"
3444 "Uptime: %ld\r\n"
3445 "LastReload: %ld\r\n"
3446 "Status: Fully Booted\r\n\r\n", cat_str, uptime, lastreloaded);
3447 }
3448 return 0;
3449}
static int manager_displayconnects(struct mansession_session *session)
Get displayconnects config option.
Definition manager.c:1036
static int unauth_sessions
Definition manager.c:166
static int authenticate(struct mansession *s, const struct message *m)
Definition manager.c:2268
#define ast_verb(level,...)
#define EVENT_FLAG_SYSTEM
Definition manager.h:75
static char * ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
Definition netsock2.h:286
#define ast_fully_booted
Definition options.h:127
uint32_t managerid
Definition manager.c:276
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition extconf.c:2295

References mansession_session::addr, ast_atomic_fetchadd_int(), ast_fully_booted, ast_lastreloadtime, ast_sockaddr_stringify_addr(), ast_startuptime, ast_str_alloca, ast_tvnow(), ast_tvsub(), ast_verb, astman_append(), astman_send_ack(), astman_send_error(), authenticate(), mansession_session::authenticated, authority_to_str(), EVENT_FLAG_SYSTEM, manager_displayconnects(), mansession_session::managerid, MAX_AUTH_PERM_STRING, mansession_session::send_events, mansession::session, unauth_sessions, and mansession_session::username.

Referenced by __init_manager().

◆ action_logoff()

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

Definition at line 3397 of file manager.c.

3398{
3399 astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
3400 return -1;
3401}
void astman_send_response(struct mansession *s, const struct message *m, char *resp, char *msg)
Send response in manager transaction.
Definition manager.c:1916

References astman_send_response().

Referenced by __init_manager().

◆ action_mailboxcount()

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

Definition at line 5487 of file manager.c.

5488{
5489 const char *mailbox = astman_get_header(m, "Mailbox");
5490 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;;
5491
5492 if (ast_strlen_zero(mailbox)) {
5493 astman_send_error(s, m, "Mailbox not specified");
5494 return 0;
5495 }
5496 ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs);
5497 astman_start_ack(s, m);
5498 astman_append(s, "Message: Mailbox Message Count\r\n"
5499 "Mailbox: %s\r\n"
5500 "UrgMessages: %d\r\n"
5501 "NewMessages: %d\r\n"
5502 "OldMessages: %d\r\n"
5503 "\r\n",
5504 mailbox, urgentmsgs, newmsgs, oldmsgs);
5505 return 0;
5506}
int ast_app_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Determine number of urgent/new/old messages in a mailbox.
Definition main/app.c:619

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

Referenced by __init_manager().

◆ action_mailboxstatus()

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

Definition at line 5470 of file manager.c.

5471{
5472 const char *mailbox = astman_get_header(m, "Mailbox");
5473 int ret;
5474
5475 if (ast_strlen_zero(mailbox)) {
5476 astman_send_error(s, m, "Mailbox not specified");
5477 return 0;
5478 }
5479 ret = ast_app_has_voicemail(mailbox, NULL);
5480 astman_start_ack(s, m);
5481 astman_append(s, "Message: Mailbox Status\r\n"
5482 "Mailbox: %s\r\n"
5483 "Waiting: %d\r\n\r\n", mailbox, ret);
5484 return 0;
5485}
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX"....
Definition main/app.c:582

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

Referenced by __init_manager().

◆ action_originate()

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

Definition at line 5275 of file manager.c.

5276{
5277 const char *name = astman_get_header(m, "Channel");
5278 const char *exten = astman_get_header(m, "Exten");
5279 const char *context = astman_get_header(m, "Context");
5280 const char *priority = astman_get_header(m, "Priority");
5281 const char *timeout = astman_get_header(m, "Timeout");
5282 const char *callerid = astman_get_header(m, "CallerID");
5283 const char *account = astman_get_header(m, "Account");
5284 const char *app = astman_get_header(m, "Application");
5285 const char *appdata = astman_get_header(m, "Data");
5286 const char *async = astman_get_header(m, "Async");
5287 const char *id = astman_get_header(m, "ActionID");
5288 const char *codecs = astman_get_header(m, "Codecs");
5289 const char *early_media = astman_get_header(m, "Earlymedia");
5290 struct ast_assigned_ids assignedids = {
5291 .uniqueid = astman_get_header(m, "ChannelId"),
5292 .uniqueid2 = astman_get_header(m, "OtherChannelId"),
5293 };
5294 const char *gosub = astman_get_header(m, "PreDialGoSub");
5295
5296 struct ast_variable *vars = NULL;
5297 char *tech, *data;
5298 char *l = NULL, *n = NULL;
5299 int pi = 0;
5300 int res;
5301 int to = 30000;
5302 int reason = 0;
5303 char tmp[256];
5304 char tmp2[256];
5306 pthread_t th;
5307 int bridge_early = 0;
5308
5309 if (!cap) {
5310 astman_send_error(s, m, "Internal Error. Memory allocation failure.");
5311 return 0;
5312 }
5314
5315 if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
5316 || (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
5317 astman_send_error_va(s, m, "Uniqueid length exceeds maximum of %d\n",
5319 res = 0;
5320 goto fast_orig_cleanup;
5321 }
5322
5323 if (ast_strlen_zero(name)) {
5324 astman_send_error(s, m, "Channel not specified");
5325 res = 0;
5326 goto fast_orig_cleanup;
5327 }
5328 if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) {
5329 if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) {
5330 astman_send_error(s, m, "Invalid priority");
5331 res = 0;
5332 goto fast_orig_cleanup;
5333 }
5334 }
5335 if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) {
5336 astman_send_error(s, m, "Invalid timeout");
5337 res = 0;
5338 goto fast_orig_cleanup;
5339 }
5340 ast_copy_string(tmp, name, sizeof(tmp));
5341 tech = tmp;
5342 data = strchr(tmp, '/');
5343 if (!data) {
5344 astman_send_error(s, m, "Invalid channel");
5345 res = 0;
5346 goto fast_orig_cleanup;
5347 }
5348 *data++ = '\0';
5349 ast_copy_string(tmp2, callerid, sizeof(tmp2));
5350 ast_callerid_parse(tmp2, &n, &l);
5351 if (n) {
5352 if (ast_strlen_zero(n)) {
5353 n = NULL;
5354 }
5355 }
5356 if (l) {
5358 if (ast_strlen_zero(l)) {
5359 l = NULL;
5360 }
5361 }
5362 if (!ast_strlen_zero(codecs)) {
5365 }
5366
5367 if (!ast_strlen_zero(app) && s->session) {
5368 if (!is_originate_app_permitted(app, appdata, s->session->writeperm)) {
5369 astman_send_error(s, m, "Originate Access Forbidden: app or data blacklisted");
5370 res = 0;
5371 goto fast_orig_cleanup;
5372 }
5373 }
5374
5375 /* Check early if the extension exists. If not, we need to bail out here. */
5376 if (exten && context && pi) {
5377 if (! ast_exists_extension(NULL, context, exten, pi, l)) {
5378 /* The extension does not exist. */
5379 astman_send_error(s, m, "Extension does not exist.");
5380 res = 0;
5381 goto fast_orig_cleanup;
5382 }
5383 }
5384
5385 /* Allocate requested channel variables */
5386 vars = astman_get_variables(m);
5387 if (s->session && s->session->chanvars) {
5388 struct ast_variable *v, *old;
5389 old = vars;
5390 vars = NULL;
5391
5392 /* The variables in the AMI originate action are appended at the end of the list, to override any user variables that apply */
5393
5395 if (old) {
5396 for (v = vars; v->next; v = v->next );
5397 v->next = old; /* Append originate variables at end of list */
5398 }
5399 }
5400
5401 /* For originate async - we can bridge in early media stage */
5402 bridge_early = ast_true(early_media);
5403
5404 if (ast_true(async)) {
5405 struct fast_originate_helper *fast;
5406
5407 fast = ast_calloc(1, sizeof(*fast));
5408 if (!fast || ast_string_field_init(fast, 252)) {
5409 ast_free(fast);
5411 res = -1;
5412 } else {
5413 if (!ast_strlen_zero(id)) {
5414 ast_string_field_build(fast, idtext, "ActionID: %s\r\n", id);
5415 }
5420 ast_string_field_set(fast, cid_num, l);
5425 ast_string_field_set(fast, channelid, assignedids.uniqueid);
5426 ast_string_field_set(fast, otherchannelid, assignedids.uniqueid2);
5427 fast->vars = vars;
5428 fast->cap = cap;
5429 cap = NULL; /* transferred originate helper the capabilities structure. It is now responsible for freeing it. */
5430 fast->timeout = to;
5431 fast->early_media = bridge_early;
5432 fast->priority = pi;
5435 res = -1;
5436 } else {
5437 res = 0;
5438 }
5439 }
5440 } else if (!ast_strlen_zero(app)) {
5441 res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason,
5443 assignedids.uniqueid ? &assignedids : NULL);
5445 } else {
5446 if (exten && context && pi) {
5448 context, exten, pi, &reason, AST_OUTGOING_WAIT,
5449 l, n, vars, account, NULL, bridge_early,
5450 assignedids.uniqueid ? &assignedids : NULL , gosub);
5452 } else {
5453 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
5455 res = 0;
5456 goto fast_orig_cleanup;
5457 }
5458 }
5459 if (!res) {
5460 astman_send_ack(s, m, "Originate successfully queued");
5461 } else {
5462 astman_send_error(s, m, "Originate failed");
5463 }
5464
5465fast_orig_cleanup:
5467 return 0;
5468}
static const char app[]
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition callerid.c:1162
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s,...
Definition callerid.c:1101
static int priority
#define AST_MAX_PUBLIC_UNIQUEID
Definition channel.h:147
static struct ao2_container * codecs
Registered codecs.
Definition codec.c:48
@ AST_MEDIA_TYPE_UNKNOWN
Definition codec.h:31
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
int ast_format_cap_update_by_allow_disallow(struct ast_format_cap *cap, const char *list, int allowing)
Parse an "allow" or "deny" list and modify a format capabilities structure accordingly.
Definition format_cap.c:328
void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Remove all formats matching a specific format type.
Definition format_cap.c:531
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition format_cap.h:49
static int is_originate_app_permitted(const char *app, const char *data, int permission)
Definition manager.c:5169
static void destroy_fast_originate_helper(struct fast_originate_helper *doomed)
Definition manager.c:4431
struct ast_variable * astman_get_variables(const struct message *m)
Get a linked list of the Variable: headers.
Definition manager.c:1668
static void * fast_originate(void *data)
Definition manager.c:4439
struct ast_variable * ast_variables_dup(struct ast_variable *var)
Duplicate variable list.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition extconf.c:1260
int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
Find the priority of an extension that has the specified label.
Definition pbx.c:2740
int ast_pbx_outgoing_exten_predial(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids, const char *predial_callee)
Definition pbx.c:6208
@ AST_OUTGOING_WAIT
Definition pbx.h:1145
int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, const struct ast_assigned_ids *assignedids)
Synchronously or asynchronously make an outbound call and execute an application on the channel.
Definition pbx.c:6262
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition pbx.c:2735
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition utils.c:2233
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
Structure to pass both assignedid values to channel drivers.
Definition channel.h:606
const char * uniqueid2
Definition channel.h:608
const char * uniqueid
Definition channel.h:607
Format capabilities structure, holds formats + preference order + etc.
Definition format_cap.c:54
helper function for originate
Definition manager.c:4403
const ast_string_field appdata
Definition manager.c:4421
struct ast_variable * vars
Definition manager.c:4423
const ast_string_field cid_num
Definition manager.c:4421
const ast_string_field account
Definition manager.c:4421
const ast_string_field tech
Definition manager.c:4421
const ast_string_field data
Definition manager.c:4421
const ast_string_field context
Definition manager.c:4421
const ast_string_field channelid
Definition manager.c:4421
const ast_string_field otherchannelid
Definition manager.c:4421
struct ast_format_cap * cap
Definition manager.c:4405
const ast_string_field exten
Definition manager.c:4421
const ast_string_field idtext
Definition manager.c:4421
const ast_string_field cid_name
Definition manager.c:4421
struct ast_variable * chanvars
Definition manager.c:289
#define ast_pthread_create_detached(a, b, c, d)
Definition utils.h:628

References ao2_cleanup, app, ast_callerid_parse(), ast_calloc, ast_copy_string(), ast_exists_extension(), ast_findlabel_extension(), ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_remove_by_type(), ast_format_cap_update_by_allow_disallow(), ast_format_slin, ast_free, AST_MAX_PUBLIC_UNIQUEID, AST_MEDIA_TYPE_UNKNOWN, AST_OUTGOING_WAIT, ast_pbx_outgoing_app(), ast_pbx_outgoing_exten_predial(), ast_pthread_create_detached, ast_shrink_phone_number(), ast_string_field_build, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_true(), ast_variables_destroy(), ast_variables_dup(), astman_get_header(), astman_get_variables(), astman_send_ack(), astman_send_error(), astman_send_error_va(), fast_originate_helper::cap, mansession_session::chanvars, codecs, destroy_fast_originate_helper(), fast_originate_helper::early_media, fast_originate(), is_originate_app_permitted(), name, ast_variable::next, NULL, priority, fast_originate_helper::priority, mansession::session, fast_originate_helper::timeout, ast_assigned_ids::uniqueid, ast_assigned_ids::uniqueid2, fast_originate_helper::vars, and mansession_session::writeperm.

Referenced by __init_manager().

◆ action_ping()

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

Definition at line 2376 of file manager.c.

2377{
2378 const char *actionid = astman_get_header(m, "ActionID");
2379 struct timeval now = ast_tvnow();
2380
2381 astman_append(s, "Response: Success\r\n");
2382 if (!ast_strlen_zero(actionid)){
2383 astman_append(s, "ActionID: %s\r\n", actionid);
2384 }
2386 s,
2387 "Ping: Pong\r\n"
2388 "Timestamp: %ld.%06lu\r\n"
2389 "\r\n",
2390 (long) now.tv_sec, (unsigned long) now.tv_usec);
2391 return 0;
2392}

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

Referenced by __init_manager().

◆ action_presencestate()

static int action_presencestate ( struct mansession s,
const struct message m 
)
static

Definition at line 5538 of file manager.c.

5539{
5540 const char *provider = astman_get_header(m, "Provider");
5542 char *subtype;
5543 char *message;
5544
5546 astman_send_error(s, m, "No provider specified");
5547 return 0;
5548 }
5549
5551 if (state == AST_PRESENCE_INVALID) {
5552 astman_send_error_va(s, m, "Invalid provider %s or provider in invalid state", provider);
5553 return 0;
5554 }
5555
5556 astman_start_ack(s, m);
5557 astman_append(s, "Message: Presence State\r\n"
5558 "State: %s\r\n", ast_presence_state2str(state));
5559
5560 if (!ast_strlen_zero(subtype)) {
5561 astman_append(s, "Subtype: %s\r\n", subtype);
5562 }
5563
5564 if (!ast_strlen_zero(message)) {
5565 /* XXX The Message header here is deprecated as it
5566 * duplicates the action response header 'Message'.
5567 * Remove it in the next major revision of AMI.
5568 */
5569 astman_append(s, "Message: %s\r\n"
5570 "PresenceMessage: %s\r\n",
5571 message, message);
5572 }
5573 astman_append(s, "\r\n");
5574
5575 ast_free(subtype);
5577
5578 return 0;
5579}
static struct prometheus_metrics_provider provider
Definition bridges.c:201
ast_presence_state
@ AST_PRESENCE_INVALID
const char * ast_presence_state2str(enum ast_presence_state state)
Convert presence state to text string for output.

References ast_free, AST_PRESENCE_INVALID, ast_presence_state2str(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_send_error_va(), astman_start_ack(), and provider.

Referenced by __init_manager().

◆ action_redirect()

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

action_redirect: The redirect manager command

Definition at line 4001 of file manager.c.

4002{
4003 char buf[256];
4004 const char *name = astman_get_header(m, "Channel");
4005 const char *name2 = astman_get_header(m, "ExtraChannel");
4006 const char *exten = astman_get_header(m, "Exten");
4007 const char *exten2 = astman_get_header(m, "ExtraExten");
4008 const char *context = astman_get_header(m, "Context");
4009 const char *context2 = astman_get_header(m, "ExtraContext");
4010 const char *priority = astman_get_header(m, "Priority");
4011 const char *priority2 = astman_get_header(m, "ExtraPriority");
4012 struct ast_channel *chan;
4013 struct ast_channel *chan2;
4014 int pi = 0;
4015 int pi2 = 0;
4016 int res;
4017 int chan1_wait = 0;
4018 int chan2_wait = 0;
4019
4020 if (ast_strlen_zero(name)) {
4021 astman_send_error(s, m, "Channel not specified");
4022 return 0;
4023 }
4024
4025 if (ast_strlen_zero(context)) {
4026 astman_send_error(s, m, "Context not specified");
4027 return 0;
4028 }
4029 if (ast_strlen_zero(exten)) {
4030 astman_send_error(s, m, "Exten not specified");
4031 return 0;
4032 }
4034 astman_send_error(s, m, "Priority not specified");
4035 return 0;
4036 }
4037 if (sscanf(priority, "%30d", &pi) != 1) {
4039 }
4040 if (pi < 1) {
4041 astman_send_error(s, m, "Priority is invalid");
4042 return 0;
4043 }
4044
4045 if (!ast_strlen_zero(name2) && !ast_strlen_zero(context2)) {
4046 /* We have an ExtraChannel and an ExtraContext */
4047 if (ast_strlen_zero(exten2)) {
4048 astman_send_error(s, m, "ExtraExten not specified");
4049 return 0;
4050 }
4051 if (ast_strlen_zero(priority2)) {
4052 astman_send_error(s, m, "ExtraPriority not specified");
4053 return 0;
4054 }
4055 if (sscanf(priority2, "%30d", &pi2) != 1) {
4056 pi2 = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL);
4057 }
4058 if (pi2 < 1) {
4059 astman_send_error(s, m, "ExtraPriority is invalid");
4060 return 0;
4061 }
4062 }
4063
4065 if (!chan) {
4066 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
4067 astman_send_error(s, m, buf);
4068 return 0;
4069 }
4070 if (ast_check_hangup_locked(chan)) {
4071 astman_send_error(s, m, "Redirect failed, channel not up.");
4072 chan = ast_channel_unref(chan);
4073 return 0;
4074 }
4075
4076 if (ast_strlen_zero(name2)) {
4077 /* Single channel redirect in progress. */
4079 if (!res) {
4080 astman_send_ack(s, m, "Redirect successful");
4081 } else {
4082 astman_send_error(s, m, "Redirect failed");
4083 }
4084 chan = ast_channel_unref(chan);
4085 return 0;
4086 }
4087
4088 chan2 = ast_channel_get_by_name(name2);
4089 if (!chan2) {
4090 snprintf(buf, sizeof(buf), "ExtraChannel does not exist: %s", name2);
4091 astman_send_error(s, m, buf);
4092 chan = ast_channel_unref(chan);
4093 return 0;
4094 }
4095 if (ast_check_hangup_locked(chan2)) {
4096 astman_send_error(s, m, "Redirect failed, extra channel not up.");
4097 chan2 = ast_channel_unref(chan2);
4098 chan = ast_channel_unref(chan);
4099 return 0;
4100 }
4101
4102 /* Dual channel redirect in progress. */
4103 ast_channel_lock(chan);
4104 if (ast_channel_is_bridged(chan)) {
4106 chan1_wait = 1;
4107 }
4108 ast_channel_unlock(chan);
4109
4110 ast_channel_lock(chan2);
4111 if (ast_channel_is_bridged(chan2)) {
4113 chan2_wait = 1;
4114 }
4115 ast_channel_unlock(chan2);
4116
4118 if (!res) {
4119 if (!ast_strlen_zero(context2)) {
4120 res = async_goto_with_discard_bridge_after(chan2, context2, exten2, pi2);
4121 } else {
4123 }
4124 if (!res) {
4125 astman_send_ack(s, m, "Dual Redirect successful");
4126 } else {
4127 astman_send_error(s, m, "Secondary redirect failed");
4128 }
4129 } else {
4130 astman_send_error(s, m, "Redirect failed");
4131 }
4132
4133 /* Release the bridge wait. */
4134 if (chan1_wait) {
4136 }
4137 if (chan2_wait) {
4139 }
4140
4141 chan2 = ast_channel_unref(chan2);
4142 chan = ast_channel_unref(chan);
4143 return 0;
4144}
void ast_channel_clear_flag(struct ast_channel *chan, unsigned int flag)
Clear a flag on a channel.
Definition channel.c:11214
@ AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT
Definition channel.h:1055
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
int ast_check_hangup_locked(struct ast_channel *chan)
Definition channel.c:460
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition channel.c:10725
static int async_goto_with_discard_bridge_after(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition manager.c:3994
#define ast_set_flag(p, flag)
Definition utils.h:71

References ast_channel_clear_flag(), ast_channel_flags(), ast_channel_get_by_name(), ast_channel_is_bridged(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_check_hangup_locked(), ast_findlabel_extension(), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT, ast_set_flag, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), async_goto_with_discard_bridge_after(), buf, name, NULL, and priority.

Referenced by __init_manager().

◆ action_reload()

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

Send a reload event.

Definition at line 6611 of file manager.c.

6612{
6613 const char *module = astman_get_header(m, "Module");
6615
6616 switch (res) {
6618 astman_send_error(s, m, "No such module");
6619 break;
6621 astman_send_error(s, m, "Module does not support reload");
6622 break;
6624 astman_send_error(s, m, "An unknown error occurred");
6625 break;
6627 astman_send_error(s, m, "A reload is in progress");
6628 break;
6630 astman_send_error(s, m, "Module not initialized");
6631 break;
6634 /* Treat a queued request as success */
6635 astman_send_ack(s, m, "Module Reloaded");
6636 break;
6637 }
6638 return 0;
6639}
ast_module_reload_result
Possible return types for ast_module_reload.
Definition module.h:109
@ AST_MODULE_RELOAD_IN_PROGRESS
Definition module.h:114
@ AST_MODULE_RELOAD_QUEUED
Definition module.h:111
@ AST_MODULE_RELOAD_SUCCESS
Definition module.h:110
@ AST_MODULE_RELOAD_ERROR
Definition module.h:113
@ AST_MODULE_RELOAD_NOT_IMPLEMENTED
Definition module.h:116
@ AST_MODULE_RELOAD_NOT_FOUND
Definition module.h:112
@ AST_MODULE_RELOAD_UNINITIALIZED
Definition module.h:115
enum ast_module_reload_result ast_module_reload(const char *name)
Reload asterisk modules.
Definition loader.c:1730

References ast_module_reload(), AST_MODULE_RELOAD_ERROR, AST_MODULE_RELOAD_IN_PROGRESS, AST_MODULE_RELOAD_NOT_FOUND, AST_MODULE_RELOAD_NOT_IMPLEMENTED, AST_MODULE_RELOAD_QUEUED, AST_MODULE_RELOAD_SUCCESS, AST_MODULE_RELOAD_UNINITIALIZED, astman_send_ack(), astman_send_error(), NULL, and S_OR.

Referenced by __init_manager().

◆ action_sendtext()

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

Definition at line 3952 of file manager.c.

3953{
3954 struct ast_channel *c;
3955 const char *name = astman_get_header(m, "Channel");
3956 const char *textmsg = astman_get_header(m, "Message");
3957 const char *content_type = astman_get_header(m, "Content-Type");
3958 int res;
3959
3960 if (ast_strlen_zero(name)) {
3961 astman_send_error(s, m, "No channel specified");
3962 return 0;
3963 }
3964
3965 if (ast_strlen_zero(textmsg)) {
3966 astman_send_error(s, m, "No Message specified");
3967 return 0;
3968 }
3969
3971 if (!c) {
3972 astman_send_error(s, m, "No such channel");
3973 return 0;
3974 }
3975
3976 /*
3977 * If the "extra" data is not available, then send using "string" only.
3978 * Doing such maintains backward compatibilities.
3979 */
3980 res = ast_strlen_zero(content_type) ? queue_sendtext(c, textmsg) :
3981 queue_sendtext_data(c, textmsg, content_type);
3982
3984
3985 if (res >= 0) {
3986 astman_send_ack(s, m, "Success");
3987 } else {
3988 astman_send_error(s, m, "Failure");
3989 }
3990
3991 return 0;
3992}
static int queue_sendtext_data(struct ast_channel *chan, const char *body, const char *content_type)
Queue a read action to send a text data message.
Definition manager.c:3933
static int queue_sendtext(struct ast_channel *chan, const char *body)
Queue a read action to send a text message.
Definition manager.c:3917

References ast_channel_get_by_name(), ast_channel_unref, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), c, name, queue_sendtext(), and queue_sendtext_data().

Referenced by __init_manager().

◆ action_setvar()

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

Definition at line 3596 of file manager.c.

3597{
3598 struct ast_channel *c = NULL;
3599 const char *name = astman_get_header(m, "Channel");
3600 const char *varname = astman_get_header(m, "Variable");
3601 const char *varval = astman_get_header(m, "Value");
3602 int res = 0;
3603
3604 if (ast_strlen_zero(varname)) {
3605 astman_send_error(s, m, "No variable specified");
3606 return 0;
3607 }
3608
3609 if (!ast_strlen_zero(name)) {
3610 if (!(c = ast_channel_get_by_name(name))) {
3611 astman_send_error(s, m, "No such channel");
3612 return 0;
3613 }
3614 }
3615
3616 res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, ""));
3617
3618 if (c) {
3620 }
3621 if (res == 0) {
3622 astman_send_ack(s, m, "Variable Set");
3623 } else {
3624 astman_send_error(s, m, "Variable not set");
3625 }
3626 return 0;
3627}

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

Referenced by __init_manager().

◆ action_status()

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

Manager "status" command to show channels.

Definition at line 3796 of file manager.c.

3797{
3798 const char *name = astman_get_header(m, "Channel");
3799 const char *chan_variables = astman_get_header(m, "Variables");
3800 const char *all_chan_variables = astman_get_header(m, "AllVariables");
3801 int all_variables = 0;
3802 const char *id = astman_get_header(m, "ActionID");
3803 char *variables = ast_strdupa(S_OR(chan_variables, ""));
3804 struct ast_channel *chan;
3805 int channels = 0;
3806 int all = ast_strlen_zero(name); /* set if we want all channels */
3807 char id_text[256];
3808 struct ast_channel_iterator *it_chans = NULL;
3810 AST_APP_ARG(name)[100];
3811 );
3812
3813 if (!ast_strlen_zero(all_chan_variables)) {
3814 all_variables = ast_true(all_chan_variables);
3815 }
3816
3818 astman_send_error(s, m, "Status Access Forbidden: Variables");
3819 return 0;
3820 }
3821
3822 if (all) {
3823 if (!(it_chans = ast_channel_iterator_all_new())) {
3824 astman_send_error(s, m, "Memory Allocation Failure");
3825 return 1;
3826 }
3827 chan = ast_channel_iterator_next(it_chans);
3828 } else {
3830 if (!chan) {
3831 astman_send_error(s, m, "No such channel");
3832 return 0;
3833 }
3834 }
3835
3836 astman_send_listack(s, m, "Channel status will follow", "start");
3837
3838 if (!ast_strlen_zero(id)) {
3839 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
3840 } else {
3841 id_text[0] = '\0';
3842 }
3843
3844 if (!ast_strlen_zero(chan_variables)) {
3845 AST_STANDARD_APP_ARGS(vars, variables);
3846 }
3847
3848 /* if we look by name, we break after the first iteration */
3849 for (; chan; all ? chan = ast_channel_iterator_next(it_chans) : 0) {
3850 ast_channel_lock(chan);
3851
3852 generate_status(s, chan, vars.name, vars.argc, all_variables, id_text, &channels);
3853
3854 ast_channel_unlock(chan);
3855 chan = ast_channel_unref(chan);
3856 }
3857
3858 if (it_chans) {
3860 }
3861
3862 astman_send_list_complete_start(s, m, "StatusComplete", channels);
3863 astman_append(s, "Items: %d\r\n", channels);
3865
3866 return 0;
3867}
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
Definition channel.c:1349
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition channel.c:1388
struct ast_channel_iterator * ast_channel_iterator_all_new(void)
Create a new channel iterator.
Definition channel.c:1380
static void generate_status(struct mansession *s, struct ast_channel *chan, char **vars, int varc, int all_variables, char *id_text, int *count)
Definition manager.c:3681
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.

References AST_APP_ARG, ast_channel_get_by_name(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, AST_DECLARE_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_true(), astman_append(), astman_get_header(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), channels, function_capable_string_allowed_with_auths(), generate_status(), name, NULL, S_OR, mansession::session, and mansession_session::writeperm.

Referenced by __init_manager().

◆ action_timeout()

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

Definition at line 5581 of file manager.c.

5582{
5583 struct ast_channel *c;
5584 const char *name = astman_get_header(m, "Channel");
5585 double timeout = atof(astman_get_header(m, "Timeout"));
5586 struct timeval when = { timeout, 0 };
5587
5588 if (ast_strlen_zero(name)) {
5589 astman_send_error(s, m, "No channel specified");
5590 return 0;
5591 }
5592
5593 if (!timeout || timeout < 0) {
5594 astman_send_error(s, m, "No timeout specified");
5595 return 0;
5596 }
5597
5598 if (!(c = ast_channel_get_by_name(name))) {
5599 astman_send_error(s, m, "No such channel");
5600 return 0;
5601 }
5602
5603 when.tv_usec = (timeout - when.tv_sec) * 1000000.0;
5604
5609
5610 astman_send_ack(s, m, "Timeout Set");
5611
5612 return 0;
5613}
void ast_channel_setwhentohangup_tv(struct ast_channel *chan, struct timeval offset)
Set when to hang a channel up.
Definition channel.c:511

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

Referenced by __init_manager().

◆ action_updateconfig()

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

Definition at line 2953 of file manager.c.

2954{
2955 struct ast_config *cfg;
2956 const char *sfn = astman_get_header(m, "SrcFilename");
2957 const char *dfn = astman_get_header(m, "DstFilename");
2958 int res;
2959 const char *rld = astman_get_header(m, "Reload");
2960 int preserve_effective_context = CONFIG_SAVE_FLAG_PRESERVE_EFFECTIVE_CONTEXT;
2961 const char *preserve_effective_context_string = astman_get_header(m, "PreserveEffectiveContext");
2962 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE };
2963 enum error_type result;
2964
2965 if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) {
2966 astman_send_error(s, m, "Filename not specified");
2967 return 0;
2968 }
2969 if (is_restricted_file(sfn) || is_restricted_file(dfn)) {
2970 astman_send_error(s, m, "File requires escalated privileges");
2971 return 0;
2972 }
2973 if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) {
2974 astman_send_error(s, m, "Config file not found");
2975 return 0;
2976 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2977 astman_send_error(s, m, "Config file has invalid format");
2978 return 0;
2979 }
2980 result = handle_updates(s, m, cfg, dfn);
2981 if (!result) {
2982 ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */
2983 if (!ast_strlen_zero(preserve_effective_context_string) && !ast_true(preserve_effective_context_string)) {
2984 preserve_effective_context = CONFIG_SAVE_FLAG_NONE;
2985 }
2986 res = ast_config_text_file_save2(dfn, cfg, "Manager", preserve_effective_context);
2987 ast_config_destroy(cfg);
2988 if (res) {
2989 astman_send_error(s, m, "Save of config failed");
2990 return 0;
2991 }
2992 astman_send_ack(s, m, NULL);
2993 if (!ast_strlen_zero(rld)) {
2994 if (ast_true(rld)) {
2995 ast_module_reload(NULL); /* Reload everything */
2996 } else if (!ast_false(rld)) {
2997 ast_module_reload(rld); /* Reload the specific module */
2998 }
2999 }
3000 } else {
3001 ast_config_destroy(cfg);
3002 switch(result) {
3003 case UNKNOWN_ACTION:
3004 astman_send_error(s, m, "Unknown action command");
3005 break;
3006 case UNKNOWN_CATEGORY:
3007 astman_send_error(s, m, "Given category does not exist");
3008 break;
3010 astman_send_error(s, m, "Category not specified");
3011 break;
3013 astman_send_error(s, m, "Problem with category, value, or line (if required)");
3014 break;
3015 case FAILURE_ALLOCATION:
3016 astman_send_error(s, m, "Memory allocation failure, this should not happen");
3017 break;
3018 case FAILURE_NEWCAT:
3019 astman_send_error(s, m, "Create category did not complete successfully");
3020 break;
3021 case FAILURE_DELCAT:
3022 astman_send_error(s, m, "Delete category did not complete successfully");
3023 break;
3024 case FAILURE_EMPTYCAT:
3025 astman_send_error(s, m, "Empty category did not complete successfully");
3026 break;
3027 case FAILURE_UPDATE:
3028 astman_send_error(s, m, "Update did not complete successfully");
3029 break;
3030 case FAILURE_DELETE:
3031 astman_send_error(s, m, "Delete did not complete successfully");
3032 break;
3033 case FAILURE_APPEND:
3034 astman_send_error(s, m, "Append did not complete successfully");
3035 break;
3036 case FAILURE_TEMPLATE:
3037 astman_send_error(s, m, "Template category not found");
3038 break;
3039 }
3040 }
3041 return 0;
3042}
static enum error_type handle_updates(struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn)
helper function for action_updateconfig
Definition manager.c:2670
error_type
Definition manager.c:108
void ast_include_rename(struct ast_config *conf, const char *from_file, const char *to_file)
int ast_config_text_file_save2(const char *filename, const struct ast_config *cfg, const char *generator, uint32_t flags)
Save a config text file.
@ CONFIG_SAVE_FLAG_NONE
@ CONFIG_SAVE_FLAG_PRESERVE_EFFECTIVE_CONTEXT
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition utils.c:2250

References ast_config_destroy(), ast_config_load2(), ast_config_text_file_save2(), ast_false(), ast_include_rename(), ast_module_reload(), ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, CONFIG_SAVE_FLAG_NONE, CONFIG_SAVE_FLAG_PRESERVE_EFFECTIVE_CONTEXT, CONFIG_STATUS_FILEINVALID, FAILURE_ALLOCATION, FAILURE_APPEND, FAILURE_DELCAT, FAILURE_DELETE, FAILURE_EMPTYCAT, FAILURE_NEWCAT, FAILURE_TEMPLATE, FAILURE_UPDATE, handle_updates(), is_restricted_file(), NULL, result, UNKNOWN_ACTION, UNKNOWN_CATEGORY, UNSPECIFIED_ARGUMENT, and UNSPECIFIED_CATEGORY.

Referenced by __init_manager().

◆ action_userevent()

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

Definition at line 6504 of file manager.c.

6505{
6506 const char *event = astman_get_header(m, "UserEvent");
6507 struct ast_str *body = ast_str_thread_get(&userevent_buf, 16);
6508 int x;
6509
6510 ast_str_reset(body);
6511
6512 for (x = 0; x < m->hdrcount; x++) {
6513 if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:")) &&
6514 strncasecmp("Action:", m->headers[x], strlen("Action:"))) {
6515 ast_str_append(&body, 0, "%s\r\n", m->headers[x]);
6516 }
6517 }
6518
6519 astman_send_ack(s, m, "Event Sent");
6520 manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, ast_str_buffer(body));
6521 return 0;
6522}
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition manager.h:255
#define EVENT_FLAG_USER
Definition manager.h:81
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition strings.h:693
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition strings.h:909

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

Referenced by __init_manager().

◆ action_waitevent()

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

Definition at line 3306 of file manager.c.

3307{
3308 const char *timeouts = astman_get_header(m, "Timeout");
3309 int timeout = -1;
3310 const char *id = astman_get_header(m, "ActionID");
3311 char idText[256];
3312
3313 if (!ast_strlen_zero(id)) {
3314 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
3315 } else {
3316 idText[0] = '\0';
3317 }
3318
3319 if (!ast_strlen_zero(timeouts)) {
3320 sscanf(timeouts, "%30i", &timeout);
3321 if (timeout < -1) {
3322 timeout = -1;
3323 }
3324 /* XXX maybe put an upper bound, or prevent the use of 0 ? */
3325 }
3326
3327 if (!s->session->managerid) {
3328 return action_waitevent_tcp(s, m, idText, timeout);
3329 } else {
3330 return action_waitevent_http(s, m, idText, timeout);
3331 }
3332}
static int action_waitevent_http(struct mansession *s, const struct message *m, const char *id, int timeout)
Definition manager.c:3200
static int action_waitevent_tcp(struct mansession *s, const struct message *m, const char *id, int timeout)
Definition manager.c:3118

References action_waitevent_http(), action_waitevent_tcp(), ast_strlen_zero(), astman_get_header(), mansession_session::managerid, and mansession::session.

Referenced by __init_manager().

◆ action_waitevent_http()

static int action_waitevent_http ( struct mansession s,
const struct message m,
const char *  id,
int  timeout 
)
static

Definition at line 3200 of file manager.c.

3201{
3202 time_t now;
3203 int max, needexit = 0, x;
3204
3207 pthread_kill(s->session->http_thread, SIGURG);
3208 }
3210
3211 ao2_lock(s->session);
3212
3213 /*
3214 * Make sure the timeout is within the expire time of the session,
3215 * as the client will likely abort the request if it does not see
3216 * data coming after some amount of time.
3217 */
3218 now = time(NULL);
3219 max = s->session->sessiontimeout - now - 10;
3220
3221 if (max < 0) { /* We are already late. Strange but possible. */
3222 max = 0;
3223 }
3224 if (timeout < 0 || timeout > max) {
3225 timeout = max;
3226 }
3227 if (!s->session->send_events) { /* make sure we record events */
3229 }
3230 ao2_unlock(s->session);
3231
3233 s->session->http_thread = pthread_self(); /* let new events wake up this thread */
3235 ast_debug(1, "Starting waiting for an event!\n");
3236
3237 for (x = 0; x < timeout || timeout < 0; x++) {
3240 needexit = 1;
3241 }
3243
3244 ao2_lock(s->session);
3245 if (s->session->needdestroy) {
3246 needexit = 1;
3247 }
3248 ao2_unlock(s->session);
3249 /* We can have multiple HTTP session point to the same mansession entry.
3250 * The way we deal with it is not very nice: newcomers kick out the previous
3251 * HTTP session. XXX this needs to be improved.
3252 */
3254 if (s->session->http_thread != pthread_self()) {
3255 needexit = 1;
3256 }
3258 if (needexit) {
3259 break;
3260 }
3261
3262 sleep(1);
3263 }
3264 ast_debug(1, "Finished waiting for an event!\n");
3265
3267 if (s->session->http_thread == pthread_self()) {
3268 size_t events_count;
3269 struct eventqent **events;
3270
3273
3274 /* To reduce contention we lock only long enough to steal the events */
3276 events_count = AST_VECTOR_SIZE(&s->session->pending_events);
3279
3280 ao2_lock(s->session);
3281 astman_send_response(s, m, "Success", "Waiting for Event completed.");
3282 for (x = 0; x < events_count; x++) {
3283 struct eventqent *eqe = events[x];
3284
3285 if (((s->session->send_events & eqe->category) == eqe->category) &&
3287 astman_append(s, "%s", ast_str_buffer(eqe->message));
3288 }
3289
3290 ao2_ref(eqe, -1);
3291 }
3292 astman_append(s,
3293 "Event: WaitEventComplete\r\n"
3294 "%s"
3295 "\r\n", id);
3296 ao2_unlock(s->session);
3298 } else {
3300 ast_debug(1, "Abandoning event request!\n");
3301 }
3302
3303 return 0;
3304}
static const struct adsi_event events[]
#define ao2_unlock(a)
Definition astobj2.h:729
#define ao2_lock(a)
Definition astobj2.h:717
#define max(a, b)
Definition f2c.h:198
static int should_send_event(struct ao2_container *includefilters, struct ao2_container *excludefilters, struct eventqent *eqe)
Definition manager.c:5696
#define AST_PTHREADT_NULL
Definition lock.h:73
int category
Category this event belongs to.
Definition manager.c:142
struct ast_str * message
The contents of the AMI event message.
Definition manager.c:146
pthread_t http_thread
Definition manager.c:275
struct mansession_session::@401 pending_events
ast_mutex_t pending_events_lock
Definition manager.c:299
ast_mutex_t http_thread_lock
Definition manager.c:274
time_t sessiontimeout
Definition manager.c:279
#define AST_VECTOR_STEAL_ELEMENTS(vec)
Steal the elements from a vector and reinitialize.
Definition vector.h:151

References ao2_lock, ao2_ref, ao2_unlock, ast_debug, ast_free, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, ast_str_buffer(), AST_VECTOR_SIZE, AST_VECTOR_STEAL_ELEMENTS, astman_append(), astman_send_response(), eventqent::category, events, mansession_session::excludefilters, mansession_session::http_thread, mansession_session::http_thread_lock, mansession_session::includefilters, max, eventqent::message, mansession_session::needdestroy, NULL, mansession_session::pending_events, mansession_session::pending_events_lock, mansession_session::readperm, mansession_session::send_events, mansession::session, mansession_session::sessiontimeout, and should_send_event().

Referenced by action_waitevent().

◆ action_waitevent_tcp()

static int action_waitevent_tcp ( struct mansession s,
const struct message m,
const char *  id,
int  timeout 
)
static

Definition at line 3118 of file manager.c.

3119{
3120 struct pollfd pfds[2];
3121 int x, res;
3122 size_t events_count;
3123 struct eventqent **events;
3124
3125 /* Since we don't have access to the reusable pollfd, we set it up each time */
3126 memset(pfds, 0, sizeof(pfds));
3127 pfds[0].fd = ast_iostream_get_fd(s->session->stream);
3128 pfds[0].events = POLLIN | POLLPRI;
3129 pfds[1].fd = ast_alertpipe_readfd(s->session->alert_pipe);
3130 pfds[1].events = POLLIN | POLLPRI;
3131
3132 ast_debug(1, "Starting waiting for an event!\n");
3133
3134 for (x = 0; x < timeout || timeout < 0; x++) {
3135 /*
3136 * Poll on both the TCP connection as well as the alert pipe for events,
3137 * and when it comes to the timeout we get it passed in as seconds and the
3138 * poll will wake up every second. The for loop then enforces the timeout.
3139 */
3140 res = ast_poll(pfds, 2, 1000);
3141 if (res == -1) {
3142 if (errno == EINTR || errno == EAGAIN) {
3143 continue;
3144 }
3145 ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno));
3146 return -1;
3147 }
3148
3149 /* If the alert pipe has data that means there are events waiting */
3150 if (pfds[1].revents) {
3151 /* If the session has been kicked go no further */
3152 if (s->session->kicked) {
3153 ast_debug(1, "Manager session has been kicked\n");
3154 return -1;
3155 }
3156
3158 break;
3159 }
3160
3161 /* If any data came from the TCP connection break now or else poll will return immediately */
3162 if (pfds[0].revents) {
3163 break;
3164 }
3165 }
3166
3167 ast_debug(1, "Finished waiting for an event!\n");
3168
3169 /* To reduce contention we lock only long enough to steal the events */
3171 events_count = AST_VECTOR_SIZE(&s->session->pending_events);
3174
3175 ao2_lock(s->session);
3176 astman_send_response(s, m, "Success", "Waiting for Event completed.");
3177
3178 for (x = 0; x < events_count; x++) {
3179 struct eventqent *eqe = events[x];
3180
3181 if (((s->session->send_events & eqe->category) == eqe->category) &&
3183 astman_append(s, "%s", ast_str_buffer(eqe->message));
3184 }
3185
3186 ao2_ref(eqe, -1);
3187 }
3188
3189 astman_append(s,
3190 "Event: WaitEventComplete\r\n"
3191 "%s"
3192 "\r\n", id);
3193 ao2_unlock(s->session);
3194
3196
3197 return 0;
3198}
int attribute_pure ast_alertpipe_readfd(int alert_pipe[2])
Get the alert pipe's read file descriptor.
Definition alertpipe.h:146
ast_alert_status_t ast_alertpipe_read(int alert_pipe[2])
Read an event from an alert pipe.
Definition alertpipe.c:102
#define LOG_WARNING
int ast_iostream_get_fd(struct ast_iostream *stream)
Get an iostream's file descriptor.
Definition iostream.c:85
#define ast_poll(a, b, c)
Definition poll-compat.h:88
unsigned int kicked
Definition manager.c:296
struct ast_iostream * stream
Definition manager.c:271

References mansession_session::alert_pipe, ao2_lock, ao2_ref, ao2_unlock, ast_alertpipe_read(), ast_alertpipe_readfd(), ast_debug, ast_free, ast_iostream_get_fd(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_poll, ast_str_buffer(), AST_VECTOR_SIZE, AST_VECTOR_STEAL_ELEMENTS, astman_append(), astman_send_response(), eventqent::category, errno, events, mansession_session::excludefilters, mansession_session::includefilters, mansession_session::kicked, LOG_WARNING, eventqent::message, mansession_session::pending_events, mansession_session::pending_events_lock, mansession_session::send_events, mansession::session, should_send_event(), and mansession_session::stream.

Referenced by action_waitevent().

◆ AO2_GLOBAL_OBJ_STATIC() [1/2]

static AO2_GLOBAL_OBJ_STATIC ( event_docs  )
static

A container of event documentation nodes.

◆ AO2_GLOBAL_OBJ_STATIC() [2/2]

static AO2_GLOBAL_OBJ_STATIC ( mgr_sessions  )
static

Active manager connection sessions container.

◆ aocmessage_get_unit_entry()

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

Definition at line 4519 of file manager.c.

4520{
4521 const char *unitamount;
4522 const char *unittype;
4523 struct ast_str *str = ast_str_alloca(32);
4524
4525 memset(entry, 0, sizeof(*entry));
4526
4527 ast_str_set(&str, 0, "UnitAmount(%u)", entry_num);
4528 unitamount = astman_get_header(m, ast_str_buffer(str));
4529
4530 ast_str_set(&str, 0, "UnitType(%u)", entry_num);
4531 unittype = astman_get_header(m, ast_str_buffer(str));
4532
4533 if (!ast_strlen_zero(unitamount) && (sscanf(unitamount, "%30u", &entry->amount) == 1)) {
4534 entry->valid_amount = 1;
4535 }
4536
4537 if (!ast_strlen_zero(unittype) && sscanf(unittype, "%30u", &entry->type) == 1) {
4538 entry->valid_type = 1;
4539 }
4540
4541 return 0;
4542}
const char * str
Definition app_jack.c:150
unsigned int amount
Definition aoc.h:180
unsigned int type
Definition aoc.h:182
char valid_type
Definition aoc.h:181
char valid_amount
Definition aoc.h:179

References ast_aoc_unit_entry::amount, ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_strlen_zero(), astman_get_header(), str, ast_aoc_unit_entry::type, ast_aoc_unit_entry::valid_amount, and ast_aoc_unit_entry::valid_type.

Referenced by action_aoc_de_message().

◆ app_match()

static int app_match ( const char *  app,
const char *  data,
const char *  search 
)
static

Definition at line 5057 of file manager.c.

5058{
5059 /*
5060 * We use strcasestr so we don't have to trim any blanks
5061 * from the front or back of the string.
5062 */
5063 return !!(strcasestr(app, search));
5064}
char * strcasestr(const char *, const char *)

References app, and strcasestr().

◆ appdata_match()

static int appdata_match ( const char *  app,
const char *  data,
const char *  search 
)
static

Definition at line 5076 of file manager.c.

5077{
5078 if (ast_strlen_zero(data)) {
5079 return 0;
5080 }
5081 return !!(strstr(data, search));
5082}

References ast_strlen_zero().

◆ append_channel_vars()

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

Definition at line 7604 of file manager.c.

7605{
7606 struct varshead *vars;
7607 struct ast_var_t *var;
7608
7609 vars = ast_channel_get_manager_vars(chan);
7610 if (!vars) {
7611 return;
7612 }
7613
7614 AST_LIST_TRAVERSE(vars, var, entries) {
7615 ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", ast_channel_name(chan), var->name, var->value);
7616 }
7617 ao2_ref(vars, -1);
7618}
struct varshead * ast_channel_get_manager_vars(struct ast_channel *chan)
Gets the variables for a given channel, as specified by ast_channel_set_manager_vars().
Definition channel.c:8032
const char * ast_channel_name(const struct ast_channel *chan)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
struct ast_var_t::@221 entries

References ao2_ref, ast_channel_get_manager_vars(), ast_channel_name(), AST_LIST_TRAVERSE, ast_str_append(), and var.

Referenced by __manager_event_sessions_va().

◆ ast_hook_send_action()

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

access for hooks to send action messages to ami

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

Definition at line 1699 of file manager.c.

1700{
1701 const char *action;
1702 int ret = 0;
1703 struct manager_action *act_found;
1704 struct mansession s = {.session = NULL, };
1705 struct message m = { 0 };
1706 char *dup_str;
1707 char *src;
1708 int x = 0;
1709 int curlen;
1710
1711 if (hook == NULL) {
1712 return -1;
1713 }
1714
1715 /* Create our own copy of the AMI action msg string. */
1716 src = dup_str = ast_strdup(msg);
1717 if (!dup_str) {
1718 return -1;
1719 }
1720
1721 /* convert msg string to message struct */
1722 curlen = strlen(src);
1723 for (x = 0; x < curlen; x++) {
1724 int cr; /* set if we have \r */
1725 if (src[x] == '\r' && x+1 < curlen && src[x+1] == '\n')
1726 cr = 2; /* Found. Update length to include \r\n */
1727 else if (src[x] == '\n')
1728 cr = 1; /* also accept \n only */
1729 else
1730 continue;
1731 /* don't keep empty lines */
1732 if (x && m.hdrcount < ARRAY_LEN(m.headers)) {
1733 /* ... but trim \r\n and terminate the header string */
1734 src[x] = '\0';
1735 m.headers[m.hdrcount++] = src;
1736 }
1737 x += cr;
1738 curlen -= x; /* remaining size */
1739 src += x; /* update pointer */
1740 x = -1; /* reset loop */
1741 }
1742
1743 action = astman_get_header(&m, "Action");
1744
1745 do {
1746 if (!strcasecmp(action, "login")) {
1747 break;
1748 }
1749
1750 act_found = action_find(action);
1751 if (!act_found) {
1752 break;
1753 }
1754
1755 /*
1756 * we have to simulate a session for this action request
1757 * to be able to pass it down for processing
1758 * This is necessary to meet the previous design of manager.c
1759 */
1760 s.hook = hook;
1761
1762 ret = -1;
1763 ao2_lock(act_found);
1764 if (act_found->registered && act_found->func) {
1765 struct ast_module *mod_ref = ast_module_running_ref(act_found->module);
1766
1767 ao2_unlock(act_found);
1768 /* If the action is in a module it must be running. */
1769 if (!act_found->module || mod_ref) {
1770 ret = act_found->func(&s, &m);
1771 ast_module_unref(mod_ref);
1772 }
1773 } else {
1774 ao2_unlock(act_found);
1775 }
1776 ao2_t_ref(act_found, -1, "done with found action object");
1777 } while (0);
1778
1779 ast_free(dup_str);
1780 return ret;
1781}
static struct manager_action * action_find(const char *name)
Definition manager.c:425
#define ast_module_unref(mod)
Release a reference to the module.
Definition module.h:483
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
Definition module.h:469
int(* func)(struct mansession *s, const struct message *m)
Definition manager.h:171
unsigned int registered
TRUE if the AMI action is registered and the callback can be called.
Definition manager.h:183
In case you didn't read that giant block of text above the mansession_session struct,...
Definition manager.c:314
struct manager_custom_hook * hook
Definition manager.c:320

References action_find(), ao2_lock, ao2_t_ref, ao2_unlock, ARRAY_LEN, ast_free, ast_module_running_ref, ast_module_unref, ast_strdup, astman_get_header(), manager_action::func, message::hdrcount, message::headers, mansession::hook, NULL, manager_action::registered, and mansession::session.

Referenced by hook_send().

◆ ast_instring()

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

795{
796 const char *val = bigstr, *next;
797
798 do {
799 if ((next = strchr(val, delim))) {
800 if (!strncmp(val, smallstr, (next - val))) {
801 return 1;
802 } else {
803 continue;
804 }
805 } else {
806 return !strcmp(smallstr, val);
807 }
808 } while (*(val = (next + 1)));
809
810 return 0;
811}

Referenced by get_perm().

◆ ast_manager_check_enabled()

int ast_manager_check_enabled ( void  )

Check if AMI is enabled.

Definition at line 683 of file manager.c.

684{
685 return manager_enabled;
686}
static int manager_enabled
Definition manager.c:154

References manager_enabled.

Referenced by handle_show_settings().

◆ ast_manager_get_message_router()

struct stasis_message_router * ast_manager_get_message_router ( void  )

Get the stasis_message_router for AMI.

Since
12
Returns
The stasis_message_router for AMI
Return values
NULLon error

Definition at line 446 of file manager.c.

447{
448 return stasis_router;
449}
static struct stasis_message_router * stasis_router
The stasis_message_router for all Stasis Message Bus API messages.
Definition manager.c:173

References stasis_router.

Referenced by manager_bridging_init(), manager_channels_init(), manager_mwi_init(), and manager_system_init().

◆ ast_manager_get_topic()

struct stasis_topic * ast_manager_get_topic ( void  )

Get the Stasis Message Bus API topic for AMI.

Since
12
Returns
The Stasis Message Bus API topic for AMI
Return values
NULLon error

Definition at line 441 of file manager.c.

442{
443 return manager_topic;
444}
static struct stasis_topic * manager_topic
A stasis_topic that all topics AMI cares about will be forwarded to.
Definition manager.c:170

References manager_topic.

Referenced by aoc_publish_blob(), ast_manager_publish_event(), endpoint_state_cb(), load_module(), load_module(), load_module(), load_module(), load_module(), manager_bridging_init(), manager_channels_init(), manager_mwi_init(), manager_system_init(), publish_load_message_type(), queue_publish_member_blob(), and stasis_app_user_event().

◆ ast_manager_hangup_helper()

int ast_manager_hangup_helper ( struct mansession s,
const struct message m,
manager_hangup_handler_t  handler,
manager_hangup_cause_validator_t  cause_validator 
)

A manager helper function that hangs up a channel using a supplied channel type specific hangup function and cause code validator.

This function handles the lookup of channel(s) and the AMI interaction but uses the supplied callbacks to actually perform the hangup. It can be used to implement a custom AMI 'Hangup' action without having to duplicate all the code in the standard Hangup action.

Parameters
sSession
mMessage
handlerFunction that actually performs the hangup
cause_validatorFunction that validates the cause code
Return values
0on success.
non-zeroon error.

Definition at line 3469 of file manager.c.

3472{
3473 struct ast_channel *c = NULL;
3474 int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */
3475 const char *id = astman_get_header(m, "ActionID");
3476 const char *name_or_regex = astman_get_header(m, "Channel");
3477 const char *cause = astman_get_header(m, "Cause");
3478 char idText[256];
3479 regex_t regexbuf;
3480 struct ast_channel_iterator *iter = NULL;
3481 struct ast_str *regex_string;
3482 int channels_matched = 0;
3483
3484 if (ast_strlen_zero(name_or_regex)) {
3485 astman_send_error(s, m, "No channel specified");
3486 return 0;
3487 }
3488
3489 if (!ast_strlen_zero(id)) {
3490 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
3491 } else {
3492 idText[0] = '\0';
3493 }
3494
3495 if (cause_validator) {
3496 causecode = cause_validator(name_or_regex, cause);
3497 } else if (!ast_strlen_zero(cause)) {
3498 char *endptr;
3499 causecode = strtol(cause, &endptr, 10);
3500 if (causecode < 0 || causecode > 127 || *endptr != '\0') {
3501 ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause);
3502 /* keep going, better to hangup without cause than to not hang up at all */
3503 causecode = 0; /* do not set channel's hangupcause */
3504 }
3505 }
3506
3507 /************************************************/
3508 /* Regular explicit match channel byname hangup */
3509
3510 if (name_or_regex[0] != '/') {
3511 if (!(c = ast_channel_get_by_name(name_or_regex))) {
3512 ast_log(LOG_NOTICE, "Request to hangup non-existent channel: %s\n",
3513 name_or_regex);
3514 astman_send_error(s, m, "No such channel");
3515 return 0;
3516 }
3517
3518 ast_verb(3, "%sManager '%s' from %s, hanging up channel: %s\n",
3519 (s->session->managerid ? "HTTP " : ""),
3520 s->session->username,
3523
3524 hangup_handler(c, causecode);
3526
3527 astman_send_ack(s, m, "Channel Hungup");
3528
3529 return 0;
3530 }
3531
3532 /***********************************************/
3533 /* find and hangup any channels matching regex */
3534
3535 regex_string = ast_str_create(strlen(name_or_regex));
3536 if (!regex_string) {
3537 astman_send_error(s, m, "Memory Allocation Failure");
3538 return 0;
3539 }
3540
3541 /* Make "/regex/" into "regex" */
3542 if (ast_regex_string_to_regex_pattern(name_or_regex, &regex_string) != 0) {
3543 astman_send_error(s, m, "Regex format invalid, Channel param should be /regex/");
3544 ast_free(regex_string);
3545 return 0;
3546 }
3547
3548 /* if regex compilation fails, hangup fails */
3549 if (regcomp(&regexbuf, ast_str_buffer(regex_string), REG_EXTENDED | REG_NOSUB)) {
3550 astman_send_error_va(s, m, "Regex compile failed on: %s", name_or_regex);
3551 ast_free(regex_string);
3552 return 0;
3553 }
3554
3555 astman_send_listack(s, m, "Channels hung up will follow", "start");
3556
3558 if (iter) {
3559 for (; (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) {
3560 if (regexec(&regexbuf, ast_channel_name(c), 0, NULL, 0)) {
3561 continue;
3562 }
3563
3564 ast_verb(3, "%sManager '%s' from %s, hanging up channel: %s\n",
3565 (s->session->managerid ? "HTTP " : ""),
3566 s->session->username,
3569
3570 hangup_handler(c, causecode);
3571 channels_matched++;
3572
3573 astman_append(s,
3574 "Event: ChannelHungup\r\n"
3575 "Channel: %s\r\n"
3576 "%s"
3577 "\r\n", ast_channel_name(c), idText);
3578 }
3580 }
3581
3582 regfree(&regexbuf);
3583 ast_free(regex_string);
3584
3585 astman_send_list_complete(s, m, "ChannelsHungupListComplete", channels_matched);
3586
3587 return 0;
3588}
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition strings.h:659
int ast_regex_string_to_regex_pattern(const char *regex_string, struct ast_str **regex_pattern)
Given a string regex_string in the form of "/regex/", convert it into the form of "regex".
Definition utils.c:2213

References mansession_session::addr, ast_channel_get_by_name(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_name(), ast_channel_unref, ast_free, ast_log, ast_regex_string_to_regex_pattern(), ast_sockaddr_stringify_addr(), ast_str_buffer(), ast_str_create, ast_strlen_zero(), ast_verb, astman_append(), astman_get_header(), astman_send_ack(), astman_send_error(), astman_send_error_va(), astman_send_list_complete(), astman_send_listack(), c, LOG_NOTICE, mansession_session::managerid, NULL, mansession::session, and mansession_session::username.

Referenced by action_hangup(), and pjsip_action_hangup().

◆ ast_manager_publish_event()

void ast_manager_publish_event ( const char *  type,
int  class_type,
struct ast_json obj 
)

Publish an event to AMI.

Since
12
Parameters
typeThe type of AMI event to publish
class_typeThe class on which to publish the event
objThe event data to be published.

Publishes a message to the Stasis Message Bus API message bus solely for the consumption of AMI. The message will be of the type provided by ast_manager_get_generic_type, and will be published to the topic provided by ast_manager_get_topic. As such, the JSON must be constructed as defined by the ast_manager_get_generic_type message.

Definition at line 637 of file manager.c.

638{
639 RAII_VAR(struct ast_json *, event_info, NULL, ast_json_unref);
640 RAII_VAR(struct ast_json_payload *, payload, NULL, ao2_cleanup);
642
643 if (!obj || !ast_manager_get_generic_type()) {
644 return;
645 }
646
647 ast_json_ref(obj);
648 event_info = ast_json_pack("{s: s, s: i, s: o}",
649 "type", type,
650 "class_type", class_type,
651 "event", obj);
652 if (!event_info) {
653 return;
654 }
655
656 payload = ast_json_payload_create(event_info);
657 if (!payload) {
658 return;
659 }
661 if (!message) {
662 return;
663 }
665}
static const char type[]
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
Definition manager.c:441
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition json.c:73
struct ast_json_payload * ast_json_payload_create(struct ast_json *json)
Create an ao2 object to pass json blobs as data payloads for stasis.
Definition json.c:756
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition json.c:612
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition json.c:67
struct stasis_message_type * ast_manager_get_generic_type(void)
Get the stasis_message_type for generic messages.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition stasis.c:1589
Abstract JSON element (object, array, string, int, ...).

References ao2_cleanup, ast_json_pack(), ast_json_payload_create(), ast_json_ref(), ast_json_unref(), ast_manager_get_generic_type(), ast_manager_get_topic(), NULL, RAII_VAR, stasis_message_create(), stasis_publish(), and type.

Referenced by analog_publish_channel_alarm_clear(), analog_publish_dnd_state(), publish_channel_alarm(), publish_channel_alarm_clear(), publish_dnd_state(), publish_fully_booted(), publish_span_alarm(), publish_span_alarm_clear(), really_quit(), and reset_user_pw().

◆ ast_manager_register2()

int ast_manager_register2 ( const char *  action,
int  auth,
int(*)(struct mansession *s, const struct message *m)  func,
struct ast_module module,
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 7908 of file manager.c.

7909{
7910 struct manager_action *cur;
7911
7912 cur = ao2_t_alloc(sizeof(*cur), action_destroy, action);
7913 if (!cur) {
7914 return -1;
7915 }
7916 if (ast_string_field_init(cur, 128)) {
7917 ao2_t_ref(cur, -1, "action object creation failed");
7918 return -1;
7919 }
7920
7921 if (ast_string_field_init_extended(cur, since)) {
7922 ao2_t_ref(cur, -1, "action object creation failed");
7923 return -1;
7924 }
7925
7926 if (ast_string_field_init_extended(cur, provided_by)) {
7927 ao2_t_ref(cur, -1, "action object creation failed");
7928 return -1;
7929 }
7930
7931 cur->action = action;
7932 cur->authority = auth;
7933 cur->func = func;
7934 cur->module = module;
7935#ifdef AST_XML_DOCS
7937 char *tmpxml;
7938
7939 tmpxml = ast_xmldoc_build_since("manager", action, NULL);
7940 ast_string_field_set(cur, since, tmpxml);
7941 ast_free(tmpxml);
7942
7943 tmpxml = ast_xmldoc_build_synopsis("manager", action, NULL);
7944 ast_string_field_set(cur, synopsis, tmpxml);
7945 ast_free(tmpxml);
7946
7947 tmpxml = ast_xmldoc_build_provided_by("manager", action, NULL);
7948 ast_string_field_set(cur, provided_by, tmpxml);
7949 ast_free(tmpxml);
7950
7951 tmpxml = ast_xmldoc_build_syntax("manager", action, NULL);
7952 ast_string_field_set(cur, syntax, tmpxml);
7953 ast_free(tmpxml);
7954
7955 tmpxml = ast_xmldoc_build_description("manager", action, NULL);
7956 ast_string_field_set(cur, description, tmpxml);
7957 ast_free(tmpxml);
7958
7959 tmpxml = ast_xmldoc_build_seealso("manager", action, NULL);
7960 ast_string_field_set(cur, seealso, tmpxml);
7961 ast_free(tmpxml);
7962
7963 tmpxml = ast_xmldoc_build_arguments("manager", action, NULL);
7964 ast_string_field_set(cur, arguments, tmpxml);
7965 ast_free(tmpxml);
7966
7969
7970 cur->docsrc = AST_XML_DOC;
7971 } else
7972#endif
7973 {
7976#ifdef AST_XML_DOCS
7977 cur->docsrc = AST_STATIC_DOC;
7978#endif
7979 }
7980 if (ast_manager_register_struct(cur)) {
7981 ao2_t_ref(cur, -1, "action object registration failed");
7982 return -1;
7983 }
7984
7985 ao2_t_ref(cur, -1, "action object registration successful");
7986 return 0;
7987}
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition astobj2.h:407
static char * synopsis
Definition func_enum.c:166
static int ast_manager_register_struct(struct manager_action *act)
Definition manager.c:7853
static void action_destroy(void *obj)
Definition manager.c:7894
#define ast_string_field_init_extended(x, field)
Initialize an extended string field.
struct ast_module *enum ast_doc_src docsrc
Definition manager.h:174
const ast_string_field description
Definition manager.h:163
const ast_string_field seealso
Definition manager.h:163
const ast_string_field syntax
Definition manager.h:163
const ast_string_field arguments
Definition manager.h:163
struct ast_xml_doc_item * ast_xmldoc_build_list_responses(const char *type, const char *name, const char *module)
Generate the [list responses] tag based on type of node ('application', 'function' or 'agi') and name...
Definition xmldoc.c:2648
char * ast_xmldoc_build_description(const char *type, const char *name, const char *module)
Generate description documentation from XML.
Definition xmldoc.c:2418
char * ast_xmldoc_build_syntax(const char *type, const char *name, const char *module)
Get the syntax for a specified application or function.
Definition xmldoc.c:1252
char * ast_xmldoc_build_arguments(const char *type, const char *name, const char *module)
Generate the [arguments] tag based on type of node ('application', 'function' or 'agi') and name.
Definition xmldoc.c:2231
char * ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module)
Generate synopsis documentation from XML.
Definition xmldoc.c:2395
char * ast_xmldoc_build_since(const char *type, const char *name, const char *module)
Parse the <since> node content.
Definition xmldoc.c:1792
@ AST_XML_DOC
Definition xmldoc.h:31
@ AST_STATIC_DOC
Definition xmldoc.h:32
char * ast_xmldoc_build_seealso(const char *type, const char *name, const char *module)
Parse the <see-also> node content.
Definition xmldoc.c:1707
char * ast_xmldoc_build_provided_by(const char *type, const char *name, const char *module)
Generate provided-by documentation from XML.
Definition xmldoc.c:1844
struct ast_xml_doc_item * ast_xmldoc_build_final_response(const char *type, const char *name, const char *module)
Generate the [final response] tag based on type of node ('application', 'function' or 'agi') and name...
Definition xmldoc.c:2718

References manager_action::action, action_destroy(), ao2_t_alloc, ao2_t_ref, ast_free, ast_manager_register_struct(), AST_STATIC_DOC, ast_string_field_init, ast_string_field_init_extended, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_final_response(), ast_xmldoc_build_list_responses(), ast_xmldoc_build_provided_by(), ast_xmldoc_build_seealso(), ast_xmldoc_build_since(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), manager_action::authority, manager_action::docsrc, manager_action::final_response, manager_action::func, manager_action::list_responses, NULL, and synopsis.

◆ ast_manager_register_hook()

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

669{
673}
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition linkedlists.h:52
#define AST_RWLIST_INSERT_TAIL

References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by create_test_dialplan(), and register_hook().

◆ ast_manager_register_struct()

static int ast_manager_register_struct ( struct manager_action act)
static

Definition at line 7853 of file manager.c.

7854{
7855 struct manager_action *cur, *prev = NULL;
7856
7859 int ret;
7860
7861 ret = strcasecmp(cur->action, act->action);
7862 if (ret == 0) {
7863 ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action);
7865 return -1;
7866 }
7867 if (ret > 0) { /* Insert these alphabetically */
7868 break;
7869 }
7870 prev = cur;
7871 }
7872
7873 ao2_t_ref(act, +1, "action object added to list");
7874 act->registered = 1;
7875 if (prev) {
7876 AST_RWLIST_INSERT_AFTER(&actions, prev, act, list);
7877 } else {
7879 }
7880
7881 ast_verb(5, "Manager registered action %s\n", act->action);
7882
7884
7885 return 0;
7886}
#define AST_RWLIST_INSERT_AFTER
#define AST_RWLIST_INSERT_HEAD

References manager_action::action, ao2_t_ref, ast_log, AST_RWLIST_INSERT_AFTER, AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, LOG_WARNING, NULL, ast_category::prev, and manager_action::registered.

Referenced by ast_manager_register2().

◆ ast_manager_str_from_json_object()

struct ast_str * ast_manager_str_from_json_object ( struct ast_json blob,
key_exclusion_cb  exclusion_cb 
)

Convert a JSON object into an AMI compatible string.

Since
12
Parameters
blobThe JSON blob containing key/value pairs to convert
exclusion_cbA key_exclusion_cb pointer to a function that will exclude keys from the final AMI string
Returns
A malloc'd ast_str object. Callers of this function should free the returned ast_str object
Return values
NULLon error

Definition at line 542 of file manager.c.

543{
544 struct ast_str *res = ast_str_create(1024);
545
546 if (!ast_json_is_null(blob)) {
547 manager_json_to_ast_str(blob, NULL, &res, exclusion_cb);
548 }
549
550 return res;
551}
static void manager_json_to_ast_str(struct ast_json *obj, const char *key, struct ast_str **res, key_exclusion_cb exclusion_cb)
Definition manager.c:501
int ast_json_is_null(const struct ast_json *value)
Check if value is JSON null.
Definition json.c:273

References ast_json_is_null(), ast_str_create, manager_json_to_ast_str(), and NULL.

Referenced by agi_channel_to_ami(), aoc_to_ami(), manager_generic_msg_cb(), multi_user_event_to_ami(), mwi_app_event_cb(), queue_channel_to_ami(), queue_member_to_ami(), and queue_multi_channel_to_ami().

◆ ast_manager_unregister()

int ast_manager_unregister ( const char *  action)

support functions to register/unregister AMI action handlers,

Unregister a registered manager command.

Definition at line 7782 of file manager.c.

7783{
7784 struct manager_action *cur;
7785
7788 if (!strcasecmp(action, cur->action)) {
7790 break;
7791 }
7792 }
7795
7796 if (cur) {
7797 /*
7798 * We have removed the action object from the container so we
7799 * are no longer in a hurry.
7800 */
7801 ao2_lock(cur);
7802 cur->registered = 0;
7803 ao2_unlock(cur);
7804
7805 ao2_t_ref(cur, -1, "action object removed from list");
7806 ast_verb(5, "Manager unregistered action %s\n", action);
7807 }
7808
7809 return 0;
7810}
#define AST_RWLIST_REMOVE_CURRENT
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#define AST_RWLIST_TRAVERSE_SAFE_END

References manager_action::action, ao2_lock, ao2_t_ref, ao2_unlock, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, and manager_action::registered.

Referenced by __unload_module(), __unload_module(), ast_res_pjsip_cleanup_options_handling(), ast_res_pjsip_destroy_configuration(), ast_sip_destroy_sorcery_auth(), ast_sip_destroy_sorcery_location(), astdb_atexit(), bridge_cleanup(), extension_state_cleanup(), load_module(), load_module(), local_shutdown(), manager_bridging_cleanup(), manager_shutdown(), message_shutdown(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_module(), unload_parking_manager(), and unload_pbx().

◆ ast_manager_unregister_hook()

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

677{
679 AST_RWLIST_REMOVE(&manager_hooks, hook, list);
681}
#define AST_RWLIST_REMOVE

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by register_hook(), unload_module(), unload_module(), and unregister_hook().

◆ AST_THREADSTORAGE_CUSTOM_SCOPE() [1/2]

AST_THREADSTORAGE_CUSTOM_SCOPE ( astman_append_buf  ,
NULL  ,
ast_free_ptr  ,
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.

◆ AST_THREADSTORAGE_CUSTOM_SCOPE() [2/2]

AST_THREADSTORAGE_CUSTOM_SCOPE ( userevent_buf  ,
NULL  ,
ast_free_ptr  ,
static   
)

◆ ast_webmanager_check_enabled()

int ast_webmanager_check_enabled ( void  )

Check if AMI/HTTP is enabled.

Definition at line 688 of file manager.c.

689{
691}
static int webmanager_enabled
Definition manager.c:156

References manager_enabled, and webmanager_enabled.

Referenced by action_coresettings(), and handle_show_settings().

◆ astman_append()

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

utility functions for creating AMI replies

Definition at line 1842 of file manager.c.

1843{
1844 int res;
1845 va_list ap;
1846 struct ast_str *buf;
1847
1848 if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
1849 return;
1850 }
1851
1852 va_start(ap, fmt);
1853 res = ast_str_set_va(&buf, 0, fmt, ap);
1854 va_end(ap);
1855 if (res == AST_DYNSTR_BUILD_FAILED) {
1856 return;
1857 }
1858
1859 if (s->hook || (s->tcptls_session != NULL && s->tcptls_session->stream != NULL)) {
1861 } else {
1862 ast_verbose("No connection stream in astman_append, should not happen\n");
1863 }
1864}
#define ASTMAN_APPEND_BUF_INITSIZE
initial allocated size for the astman_append_buf and astman_send_*_va
Definition manager.c:1828
static int send_string(struct mansession *s, char *string)
Definition manager.c:1787
#define ast_verbose(...)
int ast_str_set_va(struct ast_str **buf, ssize_t max_len, const char *fmt, va_list ap)
Set a dynamic string from a va_list.
Definition strings.h:1030
@ AST_DYNSTR_BUILD_FAILED
Definition strings.h:943
struct ast_iostream * stream
Definition tcptls.h:162
struct ast_tcptls_session_instance * tcptls_session
Definition manager.c:317

References AST_DYNSTR_BUILD_FAILED, ast_str_buffer(), ast_str_set_va(), ast_str_thread_get(), ast_verbose, ASTMAN_APPEND_BUF_INITSIZE, buf, mansession::hook, NULL, send_string(), ast_iostream::start, ast_tcptls_session_instance::stream, and mansession::tcptls_session.

Referenced by _iax2_show_peers_one(), action_agents(), action_challenge(), action_command(), action_confbridgelist_item(), action_confbridgelistrooms(), action_coresettings(), action_coreshowchannelmap(), action_coreshowchannels(), action_corestatus(), action_dahdishowchannels(), action_dahdishowstatus(), action_devicestatelist(), action_events(), action_extensionstate(), action_extensionstatelist(), action_getconfig(), action_getconfigjson(), action_getvar(), action_listcategories(), action_listcommands(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_meetmelistrooms(), action_ping(), action_presencestate(), action_presencestatelist(), action_status(), action_waitevent_http(), action_waitevent_tcp(), ami_maint_entry_cb(), ami_outbound_registration_task(), ami_registrations_aor(), ami_show_maintenance(), ami_show_outbound_registrations(), ami_subscription_detail(), append_vmbox_info_astman(), append_vmu_info_astman(), ast_cli_netstats(), ast_manager_hangup_helper(), ast_sip_format_contact_ami(), astman_append_json(), astman_send_list_complete_end(), do_print(), format_ami_aor_handler(), format_ami_aorlist_handler(), format_ami_auth_handler(), format_ami_authlist_handler(), format_ami_contactlist_handler(), format_ami_endpoint(), format_ami_endpoint_transport(), format_ami_endpoints(), format_ami_resource_lists(), generate_status(), manager_append_event_parking_lot_data_cb(), manager_bridge_info(), manager_bridge_tech_list(), manager_db_tree_get(), manager_dbget(), manager_fax_sessions(), manager_fax_sessions_entry(), manager_fax_stats(), manager_iax2_show_netstats(), manager_iax2_show_registry(), manager_jabber_send(), manager_mixmonitor(), manager_modulecheck(), manager_mute_mixmonitor(), manager_mutestream(), manager_parking_status_all_lots(), manager_parking_status_single_lot(), manager_queue_rule_show(), manager_queues_status(), manager_queues_summary(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_stop_mixmonitor(), mwi_mailbox_get(), send_bridge_info_item_cb(), send_bridge_list_item_cb(), send_identify_ami_event(), session_do(), and spandsp_manager_fax_session().

◆ astman_append_headers()

static void astman_append_headers ( struct message m,
const struct ast_variable params 
)
static

Append additional headers into the message structure from params.

Note
You likely want to initialize m->hdrcount to 0 before calling this.

Definition at line 1592 of file manager.c.

1593{
1594 const struct ast_variable *v;
1595
1596 for (v = params; v && m->hdrcount < ARRAY_LEN(m->headers); v = v->next) {
1597 if (ast_asprintf((char**)&m->headers[m->hdrcount], "%s: %s", v->name, v->value) > -1) {
1598 ++m->hdrcount;
1599 }
1600 }
1601}

References ARRAY_LEN, ast_asprintf, message::hdrcount, message::headers, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by auth_http_callback(), and generic_http_callback().

◆ astman_append_json()

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

Definition at line 2587 of file manager.c.

2588{
2589 char *buf;
2590
2591 buf = ast_alloca(2 * strlen(str) + 1);
2593 astman_append(s, "%s", buf);
2594}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition astmm.h:288
static void json_escape(char *out, const char *in)
Definition manager.c:2569

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

Referenced by action_getconfigjson().

◆ astman_flush()

static void astman_flush ( struct mansession s,
struct ast_str buf 
)
static

Definition at line 1830 of file manager.c.

1831{
1832 if (s->hook || (s->tcptls_session && s->tcptls_session->stream)) {
1834 } else {
1835 ast_verbose("No connection stream in astman_append, should not happen\n");
1836 }
1837}

References ast_str_buffer(), ast_verbose, buf, mansession::hook, send_string(), ast_tcptls_session_instance::stream, and mansession::tcptls_session.

Referenced by astman_send_list_complete(), astman_send_list_complete_start(), and astman_send_response_full().

◆ astman_free_headers()

static void astman_free_headers ( struct message m)
static

Free headers inside message structure, but not the message structure itself.

Definition at line 1606 of file manager.c.

1607{
1608 while (m->hdrcount) {
1609 --m->hdrcount;
1610 ast_free((void *) m->headers[m->hdrcount]);
1611 m->headers[m->hdrcount] = NULL;
1612 }
1613}

References ast_free, message::hdrcount, message::headers, and NULL.

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

◆ astman_get_header()

const char * astman_get_header ( const struct message m,
char *  var 
)

Return the first matching variable from an array.

Get header from manager transaction.

Note
This is the legacy function and is implemented in therms of __astman_get_header().
Never returns NULL.

Definition at line 1582 of file manager.c.

1583{
1585}
#define GET_HEADER_FIRST_MATCH
Definition manager.c:1528

References __astman_get_header(), GET_HEADER_FIRST_MATCH, and var.

Referenced by action_add_agi_cmd(), action_agent_logoff(), action_agents(), action_aoc_de_message(), action_aocmessage(), action_atxfer(), action_blind_transfer(), action_bridge(), action_cancel_atxfer(), action_challenge(), action_command(), action_confbridgekick(), action_confbridgelist(), action_confbridgelistrooms(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_coresettings(), action_coreshowchannelmap(), action_coreshowchannels(), action_corestatus(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdishowchannels(), action_dahdishowstatus(), action_devicestatelist(), action_events(), action_extensionstate(), action_extensionstatelist(), action_filter(), action_getconfig(), action_getconfigjson(), action_getvar(), action_listcategories(), action_lock_unlock_helper(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_meetmelistrooms(), action_messagesend(), action_mute_unmute_helper(), action_originate(), action_ping(), action_presencestate(), action_presencestatelist(), action_redirect(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), action_waitevent(), ami_register(), ami_set_maintenance(), ami_show_aors(), ami_show_auths(), ami_show_contacts(), ami_show_endpoint(), ami_show_endpoints(), ami_show_maintenance(), ami_show_outbound_registrations(), ami_show_registration_contact_statuses(), ami_show_registrations(), ami_show_resource_lists(), ami_show_subscriptions_inbound(), ami_show_subscriptions_outbound(), ami_sip_qualify(), ami_unregister(), aocmessage_get_unit_entry(), ast_hook_send_action(), ast_manager_hangup_helper(), astman_send_list_complete_start_common(), astman_send_response_full(), authenticate(), controlplayback_manager(), handle_manager_bridge_tech_suspend(), handle_updates(), manager_add_queue_member(), manager_bridge_destroy(), manager_bridge_info(), manager_bridge_kick(), manager_bridge_tech_list(), manager_bridges_list(), manager_change_priority_caller_on_queue(), manager_db_tree_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_dialplan_extension_add(), manager_dialplan_extension_remove(), manager_fax_session(), manager_fax_sessions(), manager_fax_stats(), manager_get_mailbox_summary(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_jabber_send(), manager_list_voicemail_users(), manager_match_mailbox(), manager_mixmonitor(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_notify(), manager_notify_endpoint(), manager_notify_uri(), manager_optimize_away(), manager_park(), manager_parking_lot_list(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_play_mf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_member_ringinuse(), manager_queue_reload(), manager_queue_reset(), manager_queue_rule_show(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), manager_request_withdraw_caller_from_queue(), manager_send_flash(), manager_show_dialplan(), manager_status_voicemail_user(), manager_stop_mixmonitor(), manager_voicemail_forward(), manager_voicemail_move(), manager_voicemail_remove(), meetmemute(), mwi_mailbox_delete(), mwi_mailbox_get(), mwi_mailbox_update(), process_message(), sorcery_memory_cache_ami_expire(), sorcery_memory_cache_ami_expire_object(), sorcery_memory_cache_ami_populate(), sorcery_memory_cache_ami_stale(), and sorcery_memory_cache_ami_stale_object().

◆ astman_get_variables()

struct ast_variable * astman_get_variables ( const struct message m)

Get a linked list of the Variable: headers.

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

Definition at line 1668 of file manager.c.

1669{
1671}
struct ast_variable * astman_get_variables_order(const struct message *m, enum variable_orders order)
Get a linked list of the Variable: headers with order specified.
Definition manager.c:1673
@ ORDER_REVERSE
Definition manager.h:291

References astman_get_variables_order(), and ORDER_REVERSE.

Referenced by action_originate().

◆ astman_get_variables_order()

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

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

Definition at line 1673 of file manager.c.

1675{
1676 int varlen;
1677 int x;
1678 struct ast_variable *head = NULL;
1679
1680 static const char var_hdr[] = "Variable:";
1681
1682 /* Process all "Variable:" headers. */
1683 varlen = strlen(var_hdr);
1684 for (x = 0; x < m->hdrcount; x++) {
1685 if (strncasecmp(var_hdr, m->headers[x], varlen)) {
1686 continue;
1687 }
1688 head = man_do_variable_value(head, m->headers[x] + varlen);
1689 }
1690
1691 if (order == ORDER_NATURAL) {
1692 head = ast_variables_reverse(head);
1693 }
1694
1695 return head;
1696}
integer order
Definition analys.c:66
static struct ast_variable * man_do_variable_value(struct ast_variable *head, const char *hdr_val)
Definition manager.c:1624
struct ast_variable * ast_variables_reverse(struct ast_variable *var)
Reverse a variable list.
@ ORDER_NATURAL
Definition manager.h:290

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

Referenced by action_messagesend(), astman_get_variables(), manager_notify_channel(), manager_notify_endpoint(), and manager_notify_uri().

◆ astman_live_dangerously()

void astman_live_dangerously ( int  new_live_dangerously)

Enable/disable the inclusion of 'dangerous' configurations outside of the ast_config_AST_CONFIG_DIR.

This function can globally enable/disable the loading of configuration files outside of ast_config_AST_CONFIG_DIR.

Parameters
new_live_dangerouslyIf true, enable the access of files outside ast_config_AST_CONFIG_DIR from astman.

Definition at line 2394 of file manager.c.

2395{
2396 if (new_live_dangerously && !live_dangerously)
2397 {
2398 ast_log(LOG_WARNING, "Manager Configuration load protection disabled.\n");
2399 }
2400
2401 if (!new_live_dangerously && live_dangerously)
2402 {
2403 ast_log(LOG_NOTICE, "Manager Configuration load protection enabled.\n");
2404 }
2405 live_dangerously = new_live_dangerously;
2406}

References ast_log, live_dangerously, LOG_NOTICE, and LOG_WARNING.

Referenced by load_asterisk_conf().

◆ astman_send_ack()

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

Send ack in manager transaction.

Definition at line 1953 of file manager.c.

1954{
1955 astman_send_response_full(s, m, "Success", msg, NULL);
1956}

References astman_send_response_full(), and NULL.

Referenced by action_add_agi_cmd(), action_agent_logoff(), action_aocmessage(), action_atxfer(), action_blind_transfer(), action_bridge(), action_cancel_atxfer(), action_confbridgekick(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_filter(), action_lock_unlock_helper(), action_loggerrotate(), action_login(), action_messagesend(), action_mute_unmute_helper(), action_originate(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), ami_register(), ami_set_maintenance(), ami_sip_qualify(), ami_unregister(), ast_manager_hangup_helper(), controlplayback_manager(), handle_manager_bridge_tech_suspend(), manager_add_queue_member(), manager_bridge_destroy(), manager_bridge_kick(), manager_change_priority_caller_on_queue(), manager_dbdel(), manager_dbdeltree(), manager_dbput(), manager_dialplan_extension_add(), manager_dialplan_extension_remove(), manager_fax_session(), manager_fax_stats(), manager_get_mailbox_summary(), manager_jabber_send(), manager_list_voicemail_users(), manager_moduleload(), manager_optimize_away(), manager_park_bridged(), manager_park_unbridged(), manager_pause_queue_member(), manager_play_dtmf(), manager_play_mf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_member_ringinuse(), manager_queue_reload(), manager_queue_reset(), manager_remove_queue_member(), manager_request_withdraw_caller_from_queue(), manager_send_flash(), manager_send_response(), manager_status_voicemail_user(), manager_voicemail_forward(), manager_voicemail_move(), manager_voicemail_refresh(), manager_voicemail_remove(), meetmemute(), mwi_mailbox_delete(), mwi_mailbox_update(), sorcery_memory_cache_ami_expire(), sorcery_memory_cache_ami_expire_object(), sorcery_memory_cache_ami_populate(), sorcery_memory_cache_ami_stale(), and sorcery_memory_cache_ami_stale_object().

◆ astman_send_error()

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

Send error in manager transaction.

Definition at line 1921 of file manager.c.

1922{
1923 astman_send_response_full(s, m, "Error", error, NULL);
1924}

References astman_send_response_full(), error(), and NULL.

Referenced by action_add_agi_cmd(), action_agent_logoff(), action_aoc_de_message(), action_aoc_s_message(), action_aoc_s_submessage(), action_aocmessage(), action_atxfer(), action_blind_transfer(), action_bridge(), action_cancel_atxfer(), action_challenge(), action_command(), action_confbridgekick(), action_confbridgelist(), action_confbridgelistrooms(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_coreshowchannelmap(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_dahdishowstatus(), action_devicestatelist(), action_events(), action_extensionstate(), action_extensionstatelist(), action_filter(), action_getconfig(), action_getconfigjson(), action_getvar(), action_listcategories(), action_lock_unlock_helper(), action_loggerrotate(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_meetmelistrooms(), action_messagesend(), action_mute_unmute_helper(), action_originate(), action_presencestate(), action_presencestatelist(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), ami_register(), ami_set_maintenance(), ami_show_aors(), ami_show_auths(), ami_show_contacts(), ami_show_endpoints(), ami_show_outbound_registrations(), ami_show_resource_lists(), ami_sip_qualify(), ami_unregister(), ast_manager_hangup_helper(), controlplayback_manager(), do_message(), handle_manager_bridge_tech_suspend(), handle_parse_error(), manager_add_queue_member(), manager_bridge_destroy(), manager_bridge_info(), manager_bridge_kick(), manager_bridge_tech_list(), manager_bridges_list(), manager_change_priority_caller_on_queue(), manager_db_tree_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_dialplan_extension_add(), manager_dialplan_extension_remove(), manager_fax_session(), manager_get_mailbox_summary(), manager_jabber_send(), manager_mixmonitor(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_notify(), manager_optimize_away(), manager_park(), manager_park_bridged(), manager_park_unbridged(), manager_parking_lot_list(), manager_parking_status_all_lots(), manager_parking_status_single_lot(), manager_pause_queue_member(), manager_play_dtmf(), manager_play_mf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_member_ringinuse(), manager_queue_reload(), manager_queue_reset(), manager_remove_queue_member(), manager_request_withdraw_caller_from_queue(), manager_send_flash(), manager_send_response(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_status_voicemail_user(), manager_stop_mixmonitor(), manager_voicemail_forward(), manager_voicemail_move(), manager_voicemail_remove(), meetmemute(), mwi_mailbox_delete(), mwi_mailbox_get(), mwi_mailbox_update(), process_message(), sorcery_memory_cache_ami_expire(), sorcery_memory_cache_ami_expire_object(), sorcery_memory_cache_ami_populate(), sorcery_memory_cache_ami_stale(), and sorcery_memory_cache_ami_stale_object().

◆ astman_send_error_va()

void astman_send_error_va ( struct mansession s,
const struct message m,
const char *  fmt,
  ... 
)

Send error in manager transaction (with va_args support)

Definition at line 1926 of file manager.c.

1927{
1928 int res;
1929 va_list ap;
1930 struct ast_str *buf;
1931 char *msg;
1932
1933 if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) {
1934 return;
1935 }
1936
1937 va_start(ap, fmt);
1938 res = ast_str_set_va(&buf, 0, fmt, ap);
1939 va_end(ap);
1940 if (res == AST_DYNSTR_BUILD_FAILED) {
1941 return;
1942 }
1943
1944 /* astman_append will use the same underlying buffer, so copy the message out
1945 * before sending the response */
1946 msg = ast_str_buffer(buf);
1947 if (msg) {
1948 msg = ast_strdupa(msg);
1949 }
1950 astman_send_response_full(s, m, "Error", msg, NULL);
1951}

References AST_DYNSTR_BUILD_FAILED, ast_str_buffer(), ast_str_set_va(), ast_str_thread_get(), ast_strdupa, ASTMAN_APPEND_BUF_INITSIZE, astman_send_response_full(), buf, and NULL.

Referenced by action_command(), action_originate(), action_presencestate(), ami_set_maintenance(), ami_show_endpoint(), ast_manager_hangup_helper(), ast_sip_create_ami_event(), format_ami_endpoint_transport(), manager_notify_endpoint(), manager_notify_uri(), manager_send_response(), mwi_mailbox_delete(), mwi_mailbox_get(), and mwi_mailbox_update().

◆ astman_send_list_complete()

static void astman_send_list_complete ( struct mansession s,
const struct message m,
const char *  event_name,
int  count 
)
static

Definition at line 1990 of file manager.c.

1991{
1992 struct ast_str *buf = astman_send_list_complete_start_common(s, m, event_name, count);
1993 if (buf) {
1994 ast_str_append(&buf, 0, "\r\n");
1995 astman_flush(s, buf);
1996 }
1997}
static void astman_flush(struct mansession *s, struct ast_str *buf)
Definition manager.c:1830
static struct ast_str * astman_send_list_complete_start_common(struct mansession *s, const struct message *m, const char *event_name, int count)
Definition manager.c:1968

References ast_str_append(), astman_flush(), astman_send_list_complete_start_common(), and buf.

Referenced by action_coreshowchannels(), and ast_manager_hangup_helper().

◆ astman_send_list_complete_end()

void astman_send_list_complete_end ( struct mansession s)

End the list complete event.

Since
13.2.0
Parameters
s- AMI session control struct.
Note
You need to call astman_send_list_complete_start() to start the AMI list completion event.
Between calling astman_send_list_complete_start() and astman_send_list_complete_end() you can add additonal headers using astman_append().

Definition at line 2007 of file manager.c.

2008{
2009 astman_append(s, "\r\n");
2010}

References astman_append().

Referenced by action_agents(), action_confbridgelist(), action_confbridgelistrooms(), action_coreshowchannelmap(), action_dahdishowchannels(), action_dahdishowstatus(), action_devicestatelist(), action_extensionstatelist(), action_meetmelist(), action_meetmelistrooms(), action_presencestatelist(), action_status(), ami_show_aors(), ami_show_auths(), ami_show_contacts(), ami_show_endpoint(), ami_show_endpoints(), ami_show_maintenance(), ami_show_outbound_registrations(), ami_show_registration_contact_statuses(), ami_show_registrations(), ami_show_resource_lists(), ami_show_subscriptions_inbound(), ami_show_subscriptions_outbound(), append_vmbox_info_astman(), manager_bridge_info(), manager_bridge_tech_list(), manager_bridges_list(), manager_db_tree_get(), manager_dbget(), manager_fax_sessions(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_list_voicemail_users(), manager_parking_lot_list(), manager_parking_status_all_lots(), manager_parking_status_single_lot(), manager_queues_status(), manager_queues_summary(), manager_show_dialplan(), manager_status_voicemail_user(), and mwi_mailbox_get().

◆ astman_send_list_complete_start()

void astman_send_list_complete_start ( struct mansession s,
const struct message m,
const char *  event_name,
int  count 
)

Start the list complete event.

Since
13.2.0
Parameters
s- AMI session control struct.
m- AMI action request that started the list.
event_name- AMI list complete event name.
count- Number of items in the list.
Note
You need to call astman_send_list_complete_end() to end the AMI list completion event.
Between calling astman_send_list_complete_start() and astman_send_list_complete_end() you can add additonal headers using astman_append().

Definition at line 1999 of file manager.c.

2000{
2001 struct ast_str *buf = astman_send_list_complete_start_common(s, m, event_name, count);
2002 if (buf) {
2003 astman_flush(s, buf);
2004 }
2005}

References astman_flush(), astman_send_list_complete_start_common(), and buf.

Referenced by action_agents(), action_confbridgelist(), action_confbridgelistrooms(), action_coreshowchannelmap(), action_dahdishowchannels(), action_dahdishowstatus(), action_devicestatelist(), action_extensionstatelist(), action_meetmelist(), action_meetmelistrooms(), action_presencestatelist(), action_status(), ami_show_aors(), ami_show_auths(), ami_show_contacts(), ami_show_endpoint(), ami_show_endpoints(), ami_show_maintenance(), ami_show_outbound_registrations(), ami_show_registration_contact_statuses(), ami_show_registrations(), ami_show_resource_lists(), ami_show_subscriptions_inbound(), ami_show_subscriptions_outbound(), append_vmbox_info_astman(), manager_bridge_info(), manager_bridge_tech_list(), manager_bridges_list(), manager_db_tree_get(), manager_dbget(), manager_fax_sessions(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_list_voicemail_users(), manager_parking_lot_list(), manager_parking_status_all_lots(), manager_parking_status_single_lot(), manager_queues_status(), manager_queues_summary(), manager_show_dialplan(), manager_status_voicemail_user(), and mwi_mailbox_get().

◆ astman_send_list_complete_start_common()

static struct ast_str * astman_send_list_complete_start_common ( struct mansession s,
const struct message m,
const char *  event_name,
int  count 
)
static

Definition at line 1968 of file manager.c.

1969{
1970 const char *id = astman_get_header(m, "ActionID");
1971 struct ast_str *buf;
1972
1973 buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE);
1974 if (!buf) {
1975 return NULL;
1976 }
1977
1978 ast_str_set(&buf, 0, "Event: %s\r\n", event_name);
1979 if (!ast_strlen_zero(id)) {
1980 ast_str_append(&buf, 0, "ActionID: %s\r\n", id);
1981 }
1982 ast_str_append(&buf, 0,
1983 "EventList: Complete\r\n"
1984 "ListItems: %d\r\n",
1985 count);
1986
1987 return buf;
1988}

References ast_str_append(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero(), ASTMAN_APPEND_BUF_INITSIZE, astman_get_header(), buf, and NULL.

Referenced by astman_send_list_complete(), and astman_send_list_complete_start().

◆ astman_send_listack()

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

Send ack in manager transaction to begin a list.

Parameters
s- AMI session control struct.
m- AMI action request that started the list.
msg- Message contents describing the list to follow.
listflag- Should always be set to "start".
Note
You need to call astman_send_list_complete_start() and astman_send_list_complete_end() to send the AMI list completion event.

Definition at line 1963 of file manager.c.

1964{
1965 astman_send_response_full(s, m, "Success", msg, listflag);
1966}

References astman_send_response_full().

Referenced by action_agents(), action_confbridgelist(), action_confbridgelistrooms(), action_coreshowchannelmap(), action_coreshowchannels(), action_dahdishowchannels(), action_dahdishowstatus(), action_devicestatelist(), action_extensionstatelist(), action_meetmelist(), action_meetmelistrooms(), action_presencestatelist(), action_status(), ami_show_aors(), ami_show_auths(), ami_show_contacts(), ami_show_endpoint(), ami_show_endpoints(), ami_show_maintenance(), ami_show_outbound_registrations(), ami_show_registration_contact_statuses(), ami_show_registrations(), ami_show_resource_lists(), ami_show_subscriptions_inbound(), ami_show_subscriptions_outbound(), append_vmbox_info_astman(), ast_manager_hangup_helper(), manager_bridge_info(), manager_bridge_tech_list(), manager_bridges_list(), manager_db_tree_get(), manager_dbget(), manager_dpsendack(), manager_fax_sessions(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_list_voicemail_users(), manager_parking_lot_list(), manager_parking_status_all_lots(), manager_parking_status_single_lot(), manager_queues_status(), manager_queues_summary(), manager_status_voicemail_user(), and mwi_mailbox_get().

◆ astman_send_response()

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

Send response in manager transaction.

Definition at line 1916 of file manager.c.

1917{
1918 astman_send_response_full(s, m, resp, msg, NULL);
1919}

References astman_send_response_full(), and NULL.

Referenced by action_logoff(), action_waitevent_http(), and action_waitevent_tcp().

◆ astman_send_response_full()

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

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

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

Definition at line 1885 of file manager.c.

1886{
1887 const char *id = astman_get_header(m, "ActionID");
1888 struct ast_str *buf;
1889
1890 buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE);
1891 if (!buf) {
1892 return;
1893 }
1894
1895 ast_str_set(&buf, 0, "Response: %s\r\n", resp);
1896
1897 if (!ast_strlen_zero(id)) {
1898 ast_str_append(&buf, 0, "ActionID: %s\r\n", id);
1899 }
1900
1901 if (listflag) {
1902 /* Start, complete, cancelled */
1903 ast_str_append(&buf, 0, "EventList: %s\r\n", listflag);
1904 }
1905
1906 if (msg != MSG_MOREDATA) {
1907 if (msg) {
1908 ast_str_append(&buf, 0, "Message: %s\r\n", msg);
1909 }
1910 ast_str_append(&buf, 0, "\r\n");
1911 }
1912
1913 astman_flush(s, buf);
1914}

References ast_str_append(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero(), ASTMAN_APPEND_BUF_INITSIZE, astman_flush(), astman_get_header(), buf, and MSG_MOREDATA.

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

◆ astman_start_ack()

static void astman_start_ack ( struct mansession s,
const struct message m 
)
static

◆ async_goto_with_discard_bridge_after()

static int async_goto_with_discard_bridge_after ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)
static

Definition at line 3994 of file manager.c.

3995{
3997 return ast_async_goto(chan, context, exten, priority);
3998}
void ast_bridge_discard_after_goto(struct ast_channel *chan)
Discard channel after bridge goto location.
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition pbx.c:5251

References ast_async_goto(), ast_bridge_discard_after_goto(), and priority.

Referenced by action_redirect().

◆ authenticate()

static int authenticate ( struct mansession s,
const struct message m 
)
static

Definition at line 2268 of file manager.c.

2269{
2270 const char *username = astman_get_header(m, "Username");
2271 const char *password = astman_get_header(m, "Secret");
2272 int error = -1;
2273 struct ast_manager_user *user = NULL;
2274 regex_t *regex_filter;
2275 struct ao2_iterator filter_iter;
2276 const char *events;
2277
2278 if (ast_strlen_zero(username)) { /* missing username */
2279 return -1;
2280 }
2281
2282 /* locate user in locked state */
2284
2285 if (!(user = get_manager_by_name_locked(username))) {
2286 report_invalid_user(s, username);
2287 ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_sockaddr_stringify_addr(&s->session->addr), username);
2288 } else if (user->acl && (ast_apply_acl(user->acl, &s->session->addr, "Manager User ACL: ") == AST_SENSE_DENY)) {
2289 report_failed_acl(s, username);
2290 ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_sockaddr_stringify_addr(&s->session->addr), username);
2291 } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) {
2292 const char *key = astman_get_header(m, "Key");
2293 if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) {
2294 int x;
2295 int len = 0;
2296 char md5key[256] = "";
2297 struct MD5Context md5;
2298 unsigned char digest[16];
2299
2300 MD5Init(&md5);
2301 MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge));
2302 MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret));
2303 MD5Final(digest, &md5);
2304 for (x = 0; x < 16; x++)
2305 len += sprintf(md5key + len, "%02hhx", digest[x]);
2306 if (!strcmp(md5key, key)) {
2307 error = 0;
2308 } else {
2309 report_failed_challenge_response(s, key, md5key);
2310 }
2311 } else {
2312 ast_debug(1, "MD5 authentication is not possible. challenge: '%s'\n",
2313 S_OR(s->session->challenge, ""));
2314 }
2315 } else if (user->secret) {
2316 if (!strcmp(password, user->secret)) {
2317 error = 0;
2318 } else {
2319 report_inval_password(s, username);
2320 }
2321 }
2322
2323 if (error) {
2324 ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_sockaddr_stringify_addr(&s->session->addr), username);
2326 return -1;
2327 }
2328
2329 /* auth complete */
2330
2331 /* All of the user parameters are copied to the session so that in the event
2332 * of a reload and a configuration change, the session parameters are not
2333 * changed. */
2334 ast_copy_string(s->session->username, username, sizeof(s->session->username));
2335 s->session->readperm = user->readperm;
2336 s->session->writeperm = user->writeperm;
2337 s->session->writetimeout = user->writetimeout;
2338 if (user->chanvars) {
2339 s->session->chanvars = ast_variables_dup(user->chanvars);
2340 }
2341
2342 filter_iter = ao2_iterator_init(user->includefilters, 0);
2343 while ((regex_filter = ao2_iterator_next(&filter_iter))) {
2344 ao2_t_link(s->session->includefilters, regex_filter, "add include user filter to session");
2345 ao2_t_ref(regex_filter, -1, "remove iterator ref");
2346 }
2347 ao2_iterator_destroy(&filter_iter);
2348
2349 filter_iter = ao2_iterator_init(user->excludefilters, 0);
2350 while ((regex_filter = ao2_iterator_next(&filter_iter))) {
2351 ao2_t_link(s->session->excludefilters, regex_filter, "add exclude user filter to session");
2352 ao2_t_ref(regex_filter, -1, "remove iterator ref");
2353 }
2354 ao2_iterator_destroy(&filter_iter);
2355
2356 s->session->sessionstart = time(NULL);
2358
2359 /* When authenticating an Events header can be used to specify what event
2360 * categories are desired. If no Events header is present or it is empty
2361 * then the default read permissions of the user should be used.
2362 */
2363 events = astman_get_header(m, "Events");
2364 if (!ast_strlen_zero(events)) {
2366 } else {
2368 }
2369
2371
2373 return 0;
2374}
enum ast_acl_sense ast_apply_acl(struct ast_acl_list *acl_list, const struct ast_sockaddr *addr, const char *purpose)
Apply a set of rules to a given IP address.
Definition acl.c:799
@ AST_SENSE_DENY
Definition acl.h:37
#define ao2_t_link(container, obj, tag)
Definition astobj2.h:1534
static int md5(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition func_md5.c:55
static struct ast_manager_user * get_manager_by_name_locked(const char *name)
Definition manager.c:1019
static void report_invalid_user(const struct mansession *s, const char *username)
Definition manager.c:2048
static void report_failed_acl(const struct mansession *s, const char *username)
Definition manager.c:2073
static void report_failed_challenge_response(const struct mansession *s, const char *response, const char *expected_response)
Definition manager.c:2206
static void report_inval_password(const struct mansession *s, const char *username)
Definition manager.c:2098
static void report_auth_success(const struct mansession *s)
Definition manager.c:2123
void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len)
Definition md5.c:72
void MD5Init(struct MD5Context *context)
Definition md5.c:57
void MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], struct MD5Context *context)
Definition md5.c:120
user descriptor, as read from the config file.
Definition manager.c:333
struct ast_sockaddr addr
Definition manager.c:270
struct timeval sessionstart_tv
Definition manager.c:278
char username[80]
Definition manager.c:280
time_t sessionstart
Definition manager.c:277
structure to hold users read from phoneprov_users.conf
list of users found in the config file
int error(const char *format,...)

References mansession_session::addr, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_t_link, ao2_t_ref, ast_apply_acl(), ast_copy_string(), ast_debug, ast_log, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, AST_SENSE_DENY, ast_sockaddr_stringify_addr(), ast_strlen_zero(), ast_tvnow(), ast_variables_dup(), astman_get_header(), mansession_session::challenge, mansession_session::chanvars, error(), events, mansession_session::excludefilters, get_manager_by_name_locked(), mansession_session::includefilters, len(), LOG_NOTICE, md5(), MD5Final(), MD5Init(), MD5Update(), NULL, mansession_session::readperm, report_auth_success(), report_failed_acl(), report_failed_challenge_response(), report_inval_password(), report_invalid_user(), S_OR, mansession_session::send_events, mansession::session, mansession_session::sessionstart, mansession_session::sessionstart_tv, set_eventmask(), mansession_session::username, mansession_session::writeperm, and mansession_session::writetimeout.

Referenced by action_login().

◆ authority_to_str()

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

Convert authority code to a list of options. Note that the EVENT_FLAG_ALL authority will always be returned.

Definition at line 766 of file manager.c.

767{
768 int i;
769 char *sep = "";
770
771 ast_str_reset(*res);
772 if (authority != EVENT_FLAG_SHUTDOWN) {
773 for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
774 if (authority & perms[i].num) {
775 ast_str_append(res, 0, "%s%s", sep, perms[i].label);
776 sep = ",";
777 }
778 }
779 }
780
781 if (ast_str_strlen(*res) == 0) {
782 /* replace empty string with something sensible */
783 ast_str_append(res, 0, "<none>");
784 }
785
786 return ast_str_buffer(*res);
787}

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

Referenced by __manager_event_sessions_va(), action_listcommands(), action_login(), and handle_showmancmd().

◆ build_mansession()

static struct mansession_session * build_mansession ( const struct ast_sockaddr addr,
unsigned int  needs_alert_pipe 
)
static

Allocate manager session structure and add it to the list of sessions.

Definition at line 934 of file manager.c.

935{
936 struct ao2_container *sessions;
937 struct mansession_session *newsession;
938
939 newsession = ao2_alloc(sizeof(*newsession), session_destructor);
940 if (!newsession) {
941 return NULL;
942 }
943
944 AST_VECTOR_INIT(&newsession->pending_events, 0);
945 ast_alertpipe_clear(newsession->alert_pipe);
947 ast_mutex_init(&newsession->http_thread_lock);
949
952 if (!newsession->includefilters || !newsession->excludefilters) {
953 ao2_ref(newsession, -1);
954 return NULL;
955 }
956
957 newsession->http_thread = AST_PTHREADT_NULL;
958 newsession->writetimeout = 100;
959 newsession->send_events = 0; /* Until authenticated this session will not receive events */
960 ast_sockaddr_copy(&newsession->addr, addr);
961
962 if (needs_alert_pipe && ast_alertpipe_init(newsession->alert_pipe)) {
963 ao2_ref(newsession, -1);
964 return NULL;
965 }
966
967 sessions = ao2_global_obj_ref(mgr_sessions);
968 if (sessions) {
969 ao2_link(sessions, newsession);
970 ao2_ref(sessions, -1);
971 }
972
973 return newsession;
974}
void ast_alertpipe_clear(int alert_pipe[2])
Sets the alert pipe file descriptors to default values.
Definition alertpipe.h:98
int ast_alertpipe_init(int alert_pipe[2])
Initialize an alert pipe.
Definition alertpipe.c:38
#define ao2_link(container, obj)
Add an object to a container.
Definition astobj2.h:1532
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition astobj2.h:363
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition astobj2.h:1327
#define ao2_alloc(data_size, destructor_fn)
Definition astobj2.h:409
static void session_destructor(void *obj)
Definition manager.c:901
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#define ast_mutex_init(pmutex)
Definition lock.h:193
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
Definition netsock2.h:167
struct mansession_session::mansession_datastores datastores
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition vector.h:124

References mansession_session::addr, mansession_session::alert_pipe, ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_list, ao2_global_obj_ref, ao2_link, ao2_ref, ast_alertpipe_clear(), ast_alertpipe_init(), AST_LIST_HEAD_INIT_NOLOCK, ast_mutex_init, AST_PTHREADT_NULL, ast_sockaddr_copy(), AST_VECTOR_INIT, mansession_session::datastores, mansession_session::excludefilters, mansession_session::http_thread, mansession_session::http_thread_lock, mansession_session::includefilters, NULL, mansession_session::pending_events, mansession_session::pending_events_lock, mansession_session::send_events, session_destructor(), sessions, and mansession_session::writetimeout.

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

◆ check_blacklist()

static int check_blacklist ( const char *  cmd)
static

Definition at line 4287 of file manager.c.

4288{
4289 char *cmd_copy, *cur_cmd;
4290 char *cmd_words[AST_MAX_CMD_LEN] = { NULL, };
4291 int i;
4292
4293 cmd_copy = ast_strdupa(cmd);
4294 for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) {
4295 cur_cmd = ast_strip(cur_cmd);
4296 if (ast_strlen_zero(cur_cmd)) {
4297 i--;
4298 continue;
4299 }
4300
4301 cmd_words[i] = cur_cmd;
4302 }
4303
4304 for (i = 0; i < ARRAY_LEN(command_blacklist); i++) {
4305 int j, match = 1;
4306
4307 for (j = 0; command_blacklist[i].words[j]; j++) {
4308 if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) {
4309 match = 0;
4310 break;
4311 }
4312 }
4313
4314 if (match) {
4315 return 1;
4316 }
4317 }
4318
4319 return 0;
4320}
#define AST_MAX_CMD_LEN
Definition cli.h:48
static const struct @400 command_blacklist[]
#define MAX_BLACKLIST_CMD_LEN
Descriptor for a manager session, either on the AMI socket or over HTTP.
Definition manager.c:208
const char * words[AST_MAX_CMD_LEN]
Definition manager.c:210

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

Referenced by action_command().

◆ check_manager_session_inuse()

static int check_manager_session_inuse ( const char *  name)
static

Definition at line 996 of file manager.c.

997{
998 struct ao2_container *sessions;
1000 int inuse = 0;
1001
1002 sessions = ao2_global_obj_ref(mgr_sessions);
1003 if (sessions) {
1004 session = ao2_find(sessions, (char *) name, 0);
1005 ao2_ref(sessions, -1);
1006 if (session) {
1008 inuse = 1;
1009 }
1010 }
1011 return inuse;
1012}
#define ao2_find(container, arg, flags)
Definition astobj2.h:1736

References ao2_find, ao2_global_obj_ref, ao2_ref, mansession_session::inuse, name, session, sessions, and unref_mansession().

Referenced by process_message().

◆ coreshowchannelmap_add_connected_channels()

static int coreshowchannelmap_add_connected_channels ( struct ao2_container channel_map,
struct ast_channel_snapshot channel_snapshot,
struct ast_bridge_snapshot bridge_snapshot 
)
static

Recursive function to get all channels in a bridge. Follow local channels as well.

Definition at line 6727 of file manager.c.

6729{
6730 int res = 0;
6731 struct ao2_iterator iter;
6732 char *current_channel_uid;
6733
6734 iter = ao2_iterator_init(bridge_snapshot->channels, 0);
6735 while ((current_channel_uid = ao2_iterator_next(&iter))) {
6736 struct ast_channel_snapshot *current_channel_snapshot;
6737 int add_channel_res;
6738
6739 /* Don't add the original channel to the list - it's either already in there,
6740 * or it's the channel we want the map for */
6741 if (!strcmp(current_channel_uid, channel_snapshot->base->uniqueid)) {
6742 ao2_ref(current_channel_uid, -1);
6743 continue;
6744 }
6745
6746 current_channel_snapshot = ast_channel_snapshot_get_latest(current_channel_uid);
6747 if (!current_channel_snapshot) {
6748 ast_debug(5, "Unable to get channel snapshot\n");
6749 ao2_ref(current_channel_uid, -1);
6750 continue;
6751 }
6752
6753 add_channel_res = coreshowchannelmap_add_to_map(channel_map, current_channel_snapshot->base->name);
6754 if (add_channel_res) {
6755 res = 1;
6756 ao2_ref(current_channel_snapshot, -1);
6757 ao2_ref(current_channel_uid, -1);
6758 break;
6759 }
6760
6761 /* If this is a local channel that we haven't seen yet, let's go ahead and find out what else is connected to it */
6762 if (ast_begins_with(current_channel_snapshot->base->name, "Local")) {
6763 struct ast_channel_snapshot *other_local_snapshot;
6764 struct ast_bridge_snapshot *other_bridge_snapshot;
6765 int size = strlen(current_channel_snapshot->base->name);
6766 char other_local[size + 1];
6767
6768 /* Don't copy the trailing number - set it to 1 or 2, whichever one it currently is not */
6769 ast_copy_string(other_local, current_channel_snapshot->base->name, size);
6770 other_local[size - 1] = ast_ends_with(current_channel_snapshot->base->name, "1") ? '2' : '1';
6771 other_local[size] = '\0';
6772
6773 other_local_snapshot = ast_channel_snapshot_get_latest_by_name(other_local);
6774 if (!other_local_snapshot) {
6775 ast_debug(5, "Unable to get other local channel snapshot\n");
6776 ao2_ref(current_channel_snapshot, -1);
6777 ao2_ref(current_channel_uid, -1);
6778 continue;
6779 }
6780
6781 if (coreshowchannelmap_add_to_map(channel_map, other_local_snapshot->base->name)) {
6782 res = 1;
6783 ao2_ref(current_channel_snapshot, -1);
6784 ao2_ref(current_channel_uid, -1);
6785 ao2_ref(other_local_snapshot, -1);
6786 break;
6787 }
6788
6789 other_bridge_snapshot = ast_bridge_get_snapshot_by_uniqueid(other_local_snapshot->bridge->id);
6790 if (other_bridge_snapshot) {
6791 res = coreshowchannelmap_add_connected_channels(channel_map, other_local_snapshot, other_bridge_snapshot);
6792 }
6793
6794 ao2_ref(current_channel_snapshot, -1);
6795 ao2_ref(current_channel_uid, -1);
6796 ao2_ref(other_local_snapshot, -1);
6797 ao2_ref(other_bridge_snapshot, -1);
6798
6799 if (res) {
6800 break;
6801 }
6802 }
6803 }
6804 ao2_iterator_destroy(&iter);
6805
6806 return res;
6807}
static int coreshowchannelmap_add_to_map(struct ao2_container *c, const char *s)
Helper function to add a channel name to the vector.
Definition manager.c:6710
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object,...
static int force_inline attribute_pure ast_ends_with(const char *str, const char *suffix)
Checks whether a string ends with another.
Definition strings.h:116
struct ao2_container * channels
Definition bridge.h:335
const ast_string_field uniqueid
const ast_string_field name

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_begins_with(), ast_bridge_get_snapshot_by_uniqueid(), ast_channel_snapshot_get_latest(), ast_channel_snapshot_get_latest_by_name(), ast_copy_string(), ast_debug, ast_ends_with(), ast_channel_snapshot::base, ast_channel_snapshot::bridge, ast_bridge_snapshot::channels, coreshowchannelmap_add_connected_channels(), coreshowchannelmap_add_to_map(), ast_channel_snapshot_bridge::id, ast_channel_snapshot_base::name, and ast_channel_snapshot_base::uniqueid.

Referenced by action_coreshowchannelmap(), and coreshowchannelmap_add_connected_channels().

◆ coreshowchannelmap_add_to_map()

static int coreshowchannelmap_add_to_map ( struct ao2_container c,
const char *  s 
)
static

Helper function to add a channel name to the vector.

Definition at line 6710 of file manager.c.

6711{
6712 char *str;
6713
6714 str = ast_strdup(s);
6715 if (!str) {
6716 ast_log(LOG_ERROR, "Unable to append channel to channel map\n");
6717 return 1;
6718 }
6719
6720 /* If this is a duplicate, it will be ignored */
6722
6723 return 0;
6724}
int ast_str_container_add(struct ao2_container *str_container, const char *add)
Adds a string to a string container allocated by ast_str_container_alloc.
Definition strings.c:205

References ast_log, ast_str_container_add(), ast_strdup, c, LOG_ERROR, and str.

Referenced by coreshowchannelmap_add_connected_channels().

◆ destroy_fast_originate_helper()

static void destroy_fast_originate_helper ( struct fast_originate_helper doomed)
static

◆ do_message()

static int do_message ( struct mansession s)
static

Definition at line 7342 of file manager.c.

7343{
7344 struct message m = { 0 };
7345 char header_buf[sizeof(s->session->inbuf)] = { '\0' };
7346 int res;
7347 int hdr_loss;
7348 time_t now;
7349 struct pollfd pfds[2];
7350
7351 /* TCP based manager never has the underlying stream change, so we can setup the pollfd once */
7352 memset(pfds, 0, sizeof(pfds));
7353 pfds[0].fd = ast_iostream_get_fd(s->session->stream);
7354 pfds[0].events = POLLIN | POLLPRI;
7355 pfds[1].fd = ast_alertpipe_readfd(s->session->alert_pipe);
7356 pfds[1].events = POLLIN | POLLPRI;
7357
7358 hdr_loss = 0;
7359 for (;;) {
7360 res = get_input(s, pfds, header_buf);
7361 if (res == 0) {
7362 /* No input line received. */
7363 if (!s->session->authenticated) {
7364 if (time(&now) == -1) {
7365 ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
7366 res = -1;
7367 break;
7368 }
7369
7370 if (now - s->session->authstart > authtimeout) {
7371 if (displayconnects) {
7372 ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_sockaddr_stringify_addr(&s->session->addr), authtimeout);
7373 }
7374 res = -1;
7375 break;
7376 }
7377 }
7378 continue;
7379 } else if (res > 0) {
7380 /* Input line received. */
7381 if (ast_strlen_zero(header_buf)) {
7382 if (hdr_loss) {
7383 mansession_lock(s);
7384 astman_send_error(s, &m, "Too many lines in message or allocation failure");
7386 res = 0;
7387 } else {
7388 switch (s->parsing) {
7389 case MESSAGE_OKAY:
7390 res = process_message(s, &m) ? -1 : 0;
7391 break;
7393 handle_parse_error(s, &m, "Failed to parse message: line too long");
7394 res = 0;
7395 break;
7396 }
7397 }
7398 break;
7399 } else if (m.hdrcount < ARRAY_LEN(m.headers)) {
7400 m.headers[m.hdrcount] = ast_strdup(header_buf);
7401 if (!m.headers[m.hdrcount]) {
7402 /* Allocation failure. */
7403 hdr_loss = 1;
7404 } else {
7405 ++m.hdrcount;
7406 }
7407 } else {
7408 /* Too many lines in message. */
7409 hdr_loss = 1;
7410 }
7411 } else {
7412 /* Input error. */
7413 break;
7414 }
7415 }
7416
7418
7419 return res;
7420}
static int process_message(struct mansession *s, const struct message *m)
Process an AMI message, performing desired action. Return 0 on success, -1 on error that require the ...
Definition manager.c:7089
static void astman_free_headers(struct message *m)
Free headers inside message structure, but not the message structure itself.
Definition manager.c:1606
static int displayconnects
Definition manager.c:149
static void handle_parse_error(struct mansession *s, struct message *m, char *error)
Definition manager.c:7325
static int get_input(struct mansession *s, struct pollfd *pfds, char *output)
Definition manager.c:7217
static int authtimeout
Definition manager.c:158
char inbuf[1025]
Definition manager.c:285
enum mansession_message_parsing parsing
Definition manager.c:318

References mansession_session::addr, mansession_session::alert_pipe, ARRAY_LEN, ast_alertpipe_readfd(), ast_iostream_get_fd(), ast_log, ast_sockaddr_stringify_addr(), ast_strdup, ast_strlen_zero(), ast_verb, astman_free_headers(), astman_send_error(), mansession_session::authenticated, mansession_session::authstart, authtimeout, displayconnects, errno, get_input(), handle_parse_error(), message::hdrcount, message::headers, mansession_session::inbuf, LOG_ERROR, mansession_lock(), mansession_unlock(), MESSAGE_LINE_TOO_LONG, MESSAGE_OKAY, mansession::parsing, process_message(), mansession::session, and mansession_session::stream.

Referenced by session_do().

◆ event_filter_destructor()

static void event_filter_destructor ( void *  obj)
static

Definition at line 874 of file manager.c.

875{
876 struct event_filter_entry *entry = obj;
877 if (entry->regex_filter) {
878 regfree(entry->regex_filter);
879 ast_free(entry->regex_filter);
880 }
881 ast_free(entry->event_name);
882 ast_free(entry->header_name);
883 ast_free(entry->string_filter);
884}
Definition manager.c:394
char * string_filter
Definition manager.c:397
char * event_name
Definition manager.c:398
regex_t * regex_filter
Definition manager.c:396
char * header_name
Definition manager.c:400

References ast_free, event_filter_entry::event_name, event_filter_entry::header_name, event_filter_entry::regex_filter, and event_filter_entry::string_filter.

Referenced by manager_add_filter().

◆ eventqent_alloc()

static struct eventqent * eventqent_alloc ( const char *  event_name,
int  category 
)
static

Allocate a manager event.

Parameters
event_nameThe name of the event
categoryThe category of the event
Returns
non-NULL on success, NULL on failure

Definition at line 7579 of file manager.c.

7580{
7581 struct eventqent *event;
7582
7584 if (!event) {
7585 return NULL;
7586 }
7587
7588 event->category = category;
7589 event->event_name_hash = ast_str_hash(event_name);
7590
7591 /*
7592 * This event will most likely be queued to at least one session so we do message
7593 * creation directly inside the event to avoid having to duplicate the string.
7594 */
7596 if (!event->message) {
7597 ao2_ref(event, -1);
7598 return NULL;
7599 }
7600
7601 return event;
7602}
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition astobj2.h:404
static void eventqent_destructor(void *obj)
Destructor for manager event message.
Definition manager.c:7561
#define MANAGER_EVENT_BUF_INITSIZE
Initial size of the manager event message buffer.
Definition manager.c:7569
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition strings.h:1259

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_ref, ast_str_create, ast_str_hash(), eventqent_destructor(), MANAGER_EVENT_BUF_INITSIZE, and NULL.

Referenced by __manager_event_sessions_va().

◆ eventqent_destructor()

static void eventqent_destructor ( void *  obj)
static

Destructor for manager event message.

Parameters
objThe event message to free

Definition at line 7561 of file manager.c.

7562{
7563 struct eventqent *event = obj;
7564
7565 ast_free(event->message);
7566}

References ast_free.

Referenced by eventqent_alloc().

◆ fast_originate()

static void * fast_originate ( void *  data)
static

Definition at line 4439 of file manager.c.

4440{
4441 struct fast_originate_helper *in = data;
4442 int res;
4443 int reason = 0;
4444 struct ast_channel *chan = NULL, *chans[1];
4445 char requested_channel[AST_CHANNEL_NAME];
4446 struct ast_assigned_ids assignedids = {
4447 .uniqueid = in->channelid,
4448 .uniqueid2 = in->otherchannelid
4449 };
4450
4451 if (!ast_strlen_zero(in->app)) {
4452 res = ast_pbx_outgoing_app(in->tech, in->cap, in->data,
4453 in->timeout, in->app, in->appdata, &reason,
4455 S_OR(in->cid_num, NULL),
4456 S_OR(in->cid_name, NULL),
4457 in->vars, in->account, &chan, &assignedids);
4458 } else {
4459 res = ast_pbx_outgoing_exten(in->tech, in->cap, in->data,
4460 in->timeout, in->context, in->exten, in->priority, &reason,
4462 S_OR(in->cid_num, NULL),
4463 S_OR(in->cid_name, NULL),
4464 in->vars, in->account, &chan, in->early_media, &assignedids);
4465 }
4466
4467 if (!chan) {
4468 snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);
4469 }
4470 /* Tell the manager what happened with the channel */
4471 chans[0] = chan;
4472 if (!ast_strlen_zero(in->app)) {
4473 ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans,
4474 "%s"
4475 "Response: %s\r\n"
4476 "Channel: %s\r\n"
4477 "Application: %s\r\n"
4478 "Data: %s\r\n"
4479 "Reason: %d\r\n"
4480 "Uniqueid: %s\r\n"
4481 "CallerIDNum: %s\r\n"
4482 "CallerIDName: %s\r\n",
4483 in->idtext, res ? "Failure" : "Success",
4484 chan ? ast_channel_name(chan) : requested_channel,
4485 in->app, in->appdata, reason,
4486 chan ? ast_channel_uniqueid(chan) : S_OR(in->channelid, "<unknown>"),
4487 S_OR(in->cid_num, "<unknown>"),
4488 S_OR(in->cid_name, "<unknown>")
4489 );
4490 } else {
4491 ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans,
4492 "%s"
4493 "Response: %s\r\n"
4494 "Channel: %s\r\n"
4495 "Context: %s\r\n"
4496 "Exten: %s\r\n"
4497 "Reason: %d\r\n"
4498 "Uniqueid: %s\r\n"
4499 "CallerIDNum: %s\r\n"
4500 "CallerIDName: %s\r\n",
4501 in->idtext, res ? "Failure" : "Success",
4502 chan ? ast_channel_name(chan) : requested_channel,
4503 in->context, in->exten, reason,
4504 chan ? ast_channel_uniqueid(chan) : S_OR(in->channelid, "<unknown>"),
4505 S_OR(in->cid_num, "<unknown>"),
4506 S_OR(in->cid_name, "<unknown>")
4507 );
4508 }
4509
4510 /* Locked and ref'd by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */
4511 if (chan) {
4512 ast_channel_unlock(chan);
4513 ast_channel_unref(chan);
4514 }
4516 return NULL;
4517}
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define AST_CHANNEL_NAME
Definition channel.h:173
#define ast_manager_event_multichan(category, event, nchans, chans, contents,...)
Definition manager.h:262
#define EVENT_FLAG_CALL
Definition manager.h:76
int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids)
Synchronously or asynchronously make an outbound call and send it to a particular extension.
Definition pbx.c:6198
FILE * in
Definition utils/frame.c:33

References AST_CHANNEL_NAME, ast_channel_name(), ast_channel_uniqueid(), ast_channel_unlock, ast_channel_unref, ast_manager_event_multichan, AST_OUTGOING_WAIT, ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_strlen_zero(), destroy_fast_originate_helper(), EVENT_FLAG_CALL, in, NULL, S_OR, and ast_assigned_ids::uniqueid.

Referenced by action_originate().

◆ file_in_modules_dir()

static int file_in_modules_dir ( const char *  filename)
static

Check if the given file path is in the modules dir or not.

Note
When the module is being loaded / reloaded / unloaded, the modules dir is automatically prepended
Returns
1 if inside modules dir
0 if outside modules dir
-1 on failure

Definition at line 6943 of file manager.c.

6944{
6945 char *stripped_filename;
6946 RAII_VAR(char *, path, NULL, ast_free);
6947 RAII_VAR(char *, real_path, NULL, ast_free);
6948
6949 /* Don't bother checking */
6950 if (live_dangerously) {
6951 return 1;
6952 }
6953
6954 stripped_filename = ast_strip(ast_strdupa(filename));
6955
6956 /* Always prepend the modules dir since that is what the code does for ModuleLoad */
6957 if (ast_asprintf(&path, "%s/%s", ast_config_AST_MODULE_DIR, stripped_filename) == -1) {
6958 return -1;
6959 }
6960
6961 real_path = realpath(path, NULL);
6962 if (!real_path) {
6963 return -1;
6964 }
6965
6966 return ast_begins_with(real_path, ast_config_AST_MODULE_DIR);
6967}
const char * ast_config_AST_MODULE_DIR
Definition options.c:154

References ast_asprintf, ast_begins_with(), ast_config_AST_MODULE_DIR, ast_free, ast_strdupa, ast_strip(), live_dangerously, NULL, and RAII_VAR.

Referenced by manager_moduleload().

◆ filter_cmp_fn()

static int filter_cmp_fn ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Definition at line 5643 of file manager.c.

5644{
5645 struct eventqent *eqe = arg;
5646 struct event_filter_entry *filter_entry = obj;
5647 char *line_buffer_start = NULL;
5648 char *line_buffer = NULL;
5649 char *line = NULL;
5650 int match = 0;
5651 int *result = data;
5652
5653 if (filter_entry->event_name_hash) {
5654 if (eqe->event_name_hash != filter_entry->event_name_hash) {
5655 goto done;
5656 }
5657 }
5658
5659 /* We're looking at the entire event data */
5660 if (!filter_entry->header_name) {
5661 match = match_eventdata(filter_entry, ast_str_buffer(eqe->message));
5662 goto done;
5663 }
5664
5665 /* We're looking at a specific header */
5666 line_buffer_start = ast_strdup(ast_str_buffer(eqe->message));
5667 line_buffer = line_buffer_start;
5668 if (!line_buffer_start) {
5669 goto done;
5670 }
5671
5672 while ((line = ast_read_line_from_buffer(&line_buffer))) {
5673 if (ast_begins_with(line, filter_entry->header_name)) {
5674 line += strlen(filter_entry->header_name);
5675 line = ast_skip_blanks(line);
5676 if (ast_strlen_zero(line)) {
5677 continue;
5678 }
5679 match = match_eventdata(filter_entry, line);
5680 if (match) {
5681 ast_free(line_buffer_start);
5682 line_buffer_start = NULL;
5683 break;
5684 }
5685 }
5686 }
5687
5688 ast_free(line_buffer_start);
5689
5690done:
5691
5692 *result = match;
5693 return match ? CMP_MATCH | CMP_STOP : 0;
5694}
@ CMP_MATCH
Definition astobj2.h:1027
@ CMP_STOP
Definition astobj2.h:1028
static int match_eventdata(struct event_filter_entry *entry, const char *eventdata)
Test eventdata against a filter entry.
Definition manager.c:5623
char * ast_read_line_from_buffer(char **buffer)
Read lines from a string buffer.
Definition strings.c:385
unsigned int event_name_hash
Definition manager.c:399
int event_name_hash
Hash of the name of the event.
Definition manager.c:144
int done

References ast_begins_with(), ast_free, ast_read_line_from_buffer(), ast_skip_blanks(), ast_str_buffer(), ast_strdup, ast_strlen_zero(), CMP_MATCH, CMP_STOP, done, eventqent::event_name_hash, event_filter_entry::event_name_hash, event_filter_entry::header_name, match(), match_eventdata(), eventqent::message, NULL, and result.

Referenced by should_send_event().

◆ function_capable_string_allowed_with_auths()

static int function_capable_string_allowed_with_auths ( const char *  evaluating,
int  writepermlist 
)
static

Checks to see if a string which can be used to evaluate functions should be rejected.

Definition at line 728 of file manager.c.

729{
730 if (!(writepermlist & EVENT_FLAG_SYSTEM)
731 && (
732 strstr(evaluating, "SHELL") || /* NoOp(${SHELL(rm -rf /)}) */
733 strstr(evaluating, "EVAL") /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
734 )) {
735 return 0;
736 }
737 return 1;
738}

References EVENT_FLAG_SYSTEM.

Referenced by action_getvar(), and action_status().

◆ generate_status()

static void generate_status ( struct mansession s,
struct ast_channel chan,
char **  vars,
int  varc,
int  all_variables,
char *  id_text,
int *  count 
)
static

Definition at line 3681 of file manager.c.

3682{
3683 struct timeval now;
3684 long elapsed_seconds;
3685 struct ast_bridge *bridge;
3686 RAII_VAR(struct ast_str *, variable_str, NULL, ast_free);
3687 struct ast_str *write_transpath = ast_str_alloca(256);
3688 struct ast_str *read_transpath = ast_str_alloca(256);
3689 struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
3690 struct ast_party_id effective_id;
3691 int i;
3692 RAII_VAR(struct ast_channel_snapshot *, snapshot,
3694 ao2_cleanup);
3695 RAII_VAR(struct ast_str *, snapshot_str, NULL, ast_free);
3696
3697 if (!snapshot) {
3698 return;
3699 }
3700
3701 snapshot_str = ast_manager_build_channel_state_string(snapshot);
3702 if (!snapshot_str) {
3703 return;
3704 }
3705
3706 if (all_variables) {
3707 variable_str = ast_str_create(2048);
3708 } else {
3709 variable_str = ast_str_create(1024);
3710 }
3711 if (!variable_str) {
3712 return;
3713 }
3714
3715 now = ast_tvnow();
3716 elapsed_seconds = ast_tvdiff_sec(now, ast_channel_creationtime(chan));
3717
3718 /* Even if all_variables has been specified, explicitly requested variables
3719 * may be global variables or dialplan functions */
3720 for (i = 0; i < varc; i++) {
3721 char valbuf[512], *ret = NULL;
3722
3723 if (vars[i][strlen(vars[i]) - 1] == ')') {
3724 if (ast_func_read(chan, vars[i], valbuf, sizeof(valbuf)) < 0) {
3725 valbuf[0] = '\0';
3726 }
3727 ret = valbuf;
3728 } else {
3729 pbx_retrieve_variable(chan, vars[i], &ret, valbuf, sizeof(valbuf), NULL);
3730 }
3731
3732 ast_str_append(&variable_str, 0, "Variable: %s=%s\r\n", vars[i], ret);
3733 }
3734
3735 /* Walk all channel variables and add them */
3736 if (all_variables) {
3737 struct ast_var_t *variables;
3738
3740 ast_str_append(&variable_str, 0, "Variable: %s=%s\r\n",
3741 ast_var_name(variables), ast_var_value(variables));
3742 }
3743 }
3744
3745 bridge = ast_channel_get_bridge(chan);
3746 effective_id = ast_channel_connected_effective_id(chan);
3747
3748 astman_append(s,
3749 "Event: Status\r\n"
3750 "Privilege: Call\r\n"
3751 "%s"
3752 "Type: %s\r\n"
3753 "DNID: %s\r\n"
3754 "EffectiveConnectedLineNum: %s\r\n"
3755 "EffectiveConnectedLineName: %s\r\n"
3756 "TimeToHangup: %ld\r\n"
3757 "BridgeID: %s\r\n"
3758 "Application: %s\r\n"
3759 "Data: %s\r\n"
3760 "Nativeformats: %s\r\n"
3761 "Readformat: %s\r\n"
3762 "Readtrans: %s\r\n"
3763 "Writeformat: %s\r\n"
3764 "Writetrans: %s\r\n"
3765 "Callgroup: %llu\r\n"
3766 "Pickupgroup: %llu\r\n"
3767 "Seconds: %ld\r\n"
3768 "%s"
3769 "%s"
3770 "\r\n",
3771 ast_str_buffer(snapshot_str),
3772 ast_channel_tech(chan)->type,
3773 S_OR(ast_channel_dialed(chan)->number.str, ""),
3774 S_COR(effective_id.number.valid, effective_id.number.str, "<unknown>"),
3775 S_COR(effective_id.name.valid, effective_id.name.str, "<unknown>"),
3776 (long)ast_channel_whentohangup(chan)->tv_sec,
3777 bridge ? bridge->uniqueid : "",
3778 ast_channel_appl(chan),
3779 ast_channel_data(chan),
3782 ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath),
3784 ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath),
3787 (long)elapsed_seconds,
3788 ast_str_buffer(variable_str),
3789 id_text);
3790 ++*count;
3791
3792 ao2_cleanup(bridge);
3793}
const char * ast_channel_data(const struct ast_channel *chan)
struct varshead * ast_channel_varshead(struct ast_channel *chan)
struct ast_trans_pvt * ast_channel_readtrans(const struct ast_channel *chan)
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
struct ast_trans_pvt * ast_channel_writetrans(const struct ast_channel *chan)
ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan)
const char * ast_channel_appl(const struct ast_channel *chan)
struct timeval ast_channel_creationtime(struct ast_channel *chan)
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
Definition channel.c:10714
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
struct timeval * ast_channel_whentohangup(struct ast_channel *chan)
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
ast_group_t ast_channel_callgroup(const struct ast_channel *chan)
struct ast_party_id ast_channel_connected_effective_id(struct ast_channel *chan)
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
const char * ast_var_name(const struct ast_var_t *var)
Definition chanvars.c:60
const char * ast_var_value(const struct ast_var_t *var)
Definition chanvars.c:80
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition format.c:334
#define AST_FORMAT_CAP_NAMES_LEN
Definition format_cap.h:324
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition format_cap.c:742
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
Structure that contains information about a bridge.
Definition bridge.h:355
const ast_string_field uniqueid
Definition bridge.h:407
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition channel.h:648
Information needed to identify an endpoint in a call.
Definition channel.h:340
Number structure.
int64_t ast_tvdiff_sec(struct timeval end, struct timeval start)
Computes the difference (in seconds) between two struct timeval instances.
Definition time.h:73
const char * ast_translate_path_to_str(struct ast_trans_pvt *t, struct ast_str **str)
Puts a string representation of the translation path into outbuf.
Definition translate.c:1145

References ao2_cleanup, ast_channel_appl(), ast_channel_callgroup(), ast_channel_connected_effective_id(), ast_channel_creationtime(), ast_channel_data(), ast_channel_dialed(), ast_channel_get_bridge(), ast_channel_nativeformats(), ast_channel_pickupgroup(), ast_channel_readformat(), ast_channel_readtrans(), ast_channel_snapshot_get_latest(), ast_channel_uniqueid(), ast_channel_varshead(), ast_channel_whentohangup(), ast_channel_writeformat(), ast_channel_writetrans(), ast_format_cap_get_names(), AST_FORMAT_CAP_NAMES_LEN, ast_format_get_name(), ast_free, ast_func_read(), AST_LIST_TRAVERSE, ast_manager_build_channel_state_string(), ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_create, ast_translate_path_to_str(), ast_tvdiff_sec(), ast_tvnow(), ast_var_name(), ast_var_value(), astman_append(), ast_party_id::name, NULL, ast_party_id::number, pbx_retrieve_variable(), RAII_VAR, S_COR, S_OR, ast_party_name::str, ast_party_number::str, type, ast_bridge::uniqueid, ast_party_name::valid, and ast_party_number::valid.

Referenced by action_status().

◆ get_input()

static int get_input ( struct mansession s,
struct pollfd *  pfds,
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 7217 of file manager.c.

7218{
7219 int res = 0, x;
7220 int maxlen = sizeof(s->session->inbuf) - 1;
7221 char *src = s->session->inbuf;
7222 int timeout = -1;
7223 time_t now;
7224
7225 /*
7226 * Look for \r\n within the buffer. If found, copy to the output
7227 * buffer and return, trimming the \r\n (not used afterwards).
7228 */
7229 for (x = 0; x < s->session->inlen; x++) {
7230 int cr; /* set if we have \r */
7231 if (src[x] == '\r' && x+1 < s->session->inlen && src[x + 1] == '\n') {
7232 cr = 2; /* Found. Update length to include \r\n */
7233 } else if (src[x] == '\n') {
7234 cr = 1; /* also accept \n only */
7235 } else {
7236 continue;
7237 }
7238 memmove(output, src, x); /*... but trim \r\n */
7239 output[x] = '\0'; /* terminate the string */
7240 x += cr; /* number of bytes used */
7241 s->session->inlen -= x; /* remaining size */
7242 memmove(src, src + x, s->session->inlen); /* remove used bytes */
7243 return 1;
7244 }
7245 if (s->session->inlen >= maxlen) {
7246 /* no crlf found, and buffer full - sorry, too long for us
7247 * keep the last character in case we are in the middle of a CRLF. */
7248 ast_log(LOG_WARNING, "Discarding message from %s. Line too long: %.25s...\n", ast_sockaddr_stringify_addr(&s->session->addr), src);
7249 src[0] = src[s->session->inlen - 1];
7250 s->session->inlen = 1;
7252 }
7253 res = 0;
7254 while (res == 0) {
7255 /* calculate a timeout if we are not authenticated */
7256 if (!s->session->authenticated) {
7257 if(time(&now) == -1) {
7258 ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
7259 return -1;
7260 }
7261
7262 timeout = (authtimeout - (now - s->session->authstart)) * 1000;
7263 if (timeout < 0) {
7264 /* we have timed out */
7265 return 0;
7266 }
7267 }
7268
7269 res = ast_poll(pfds, 2, timeout);
7270
7271 /* If polling resulted in an error, break out of the loop */
7272 if (res < 0) {
7273 /* If in reality we were interrupted, iterate again */
7274 if (errno == EINTR || errno == EAGAIN) {
7275 continue;
7276 }
7277
7278 ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno));
7279 return -1;
7280 } else if (!res) {
7281 /* If nothing happened we loop again */
7282 continue;
7283 }
7284
7285 if (pfds[1].revents) {
7286 /* There are pending events to send, or this session has been kicked */
7287 if (s->session->kicked) {
7288 ast_debug(1, "Manager session has been kicked\n");
7289 return -1;
7290 }
7292
7293 if (process_events(s)) {
7294 return -1;
7295 }
7296 }
7297
7298 if (pfds[0].revents) {
7299 ao2_lock(s->session);
7300 res = ast_iostream_read(s->session->stream, src + s->session->inlen, maxlen - s->session->inlen);
7301 if (res < 1) {
7302 res = -1; /* error return */
7303 } else {
7304 s->session->inlen += res;
7305 src[s->session->inlen] = '\0';
7306 res = 0;
7307 }
7308 ao2_unlock(s->session);
7309 return res;
7310 }
7311 }
7312
7313 return 0;
7314}
static int process_events(struct mansession *s)
Send any pending events to the client listening on this socket.
Definition manager.c:6459
ssize_t ast_iostream_read(struct ast_iostream *stream, void *buffer, size_t count)
Read data from an iostream.
Definition iostream.c:289

References mansession_session::addr, mansession_session::alert_pipe, ao2_lock, ao2_unlock, ast_alertpipe_read(), ast_debug, ast_iostream_read(), ast_log, ast_poll, ast_sockaddr_stringify_addr(), mansession_session::authenticated, mansession_session::authstart, authtimeout, errno, mansession_session::inbuf, mansession_session::inlen, mansession_session::kicked, LOG_ERROR, LOG_WARNING, MESSAGE_LINE_TOO_LONG, mansession::parsing, process_events(), mansession::session, and mansession_session::stream.

Referenced by do_message().

◆ get_manager_by_name_locked()

static struct ast_manager_user * get_manager_by_name_locked ( const char *  name)
static

lookup an entry in the list of registered users. must be called with the list lock held.

Definition at line 1019 of file manager.c.

1020{
1021 struct ast_manager_user *user = NULL;
1022
1024 if (!strcasecmp(user->username, name)) {
1025 break;
1026 }
1027 }
1028
1029 return user;
1030}
struct ast_manager_user::@403 list

References AST_RWLIST_TRAVERSE, ast_manager_user::list, name, and NULL.

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

◆ get_perm()

static int get_perm ( const char *  instr)
static

Definition at line 813 of file manager.c.

814{
815 int x = 0, ret = 0;
816
817 if (!instr) {
818 return 0;
819 }
820
821 for (x = 0; x < ARRAY_LEN(perms); x++) {
822 if (ast_instring(instr, perms[x].label, ',')) {
823 ret |= perms[x].num;
824 }
825 }
826
827 return ret;
828}
static int ast_instring(const char *bigstr, const char *smallstr, const char delim)
Definition manager.c:794

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

Referenced by __init_manager(), and strings_to_mask().

◆ handle_kickmanconn()

static char * handle_kickmanconn ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

CLI command manager kick session.

Definition at line 1391 of file manager.c.

1392{
1393 struct ao2_container *sessions;
1395 struct ao2_iterator i;
1396 int fd = -1;
1397 int found = 0;
1398
1399 switch (cmd) {
1400 case CLI_INIT:
1401 e->command = "manager kick session";
1402 e->usage =
1403 "Usage: manager kick session <file descriptor>\n"
1404 " Kick an active Asterisk Manager Interface session\n";
1405 return NULL;
1406 case CLI_GENERATE:
1407 return NULL;
1408 }
1409
1410 if (a->argc != 4) {
1411 return CLI_SHOWUSAGE;
1412 }
1413
1414 fd = atoi(a->argv[3]);
1415 if (fd <= 0) { /* STDOUT won't be a valid AMI fd either */
1416 ast_cli(a->fd, "Invalid AMI file descriptor: %s\n", a->argv[3]);
1417 return CLI_FAILURE;
1418 }
1419
1420 sessions = ao2_global_obj_ref(mgr_sessions);
1421 if (sessions) {
1423 ao2_ref(sessions, -1);
1424 while ((session = ao2_iterator_next(&i))) {
1426 if (session->stream) {
1427 if (ast_iostream_get_fd(session->stream) == fd) {
1428 if (session->kicked) {
1429 ast_cli(a->fd, "Manager session using file descriptor %d has already been kicked\n", fd);
1432 break;
1433 }
1434 fd = ast_iostream_get_fd(session->stream);
1435 found = fd;
1436 ast_cli(a->fd, "Kicking manager session connected using file descriptor %d\n", fd);
1437 session->kicked = 1;
1441 break;
1442 }
1443 }
1446 }
1448 }
1449
1450 if (!found) {
1451 ast_cli(a->fd, "No manager session found using file descriptor %d\n", fd);
1452 }
1453 return CLI_SUCCESS;
1454}
#define CLI_SHOWUSAGE
Definition cli.h:45
#define CLI_SUCCESS
Definition cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition clicompat.c:6
@ CLI_INIT
Definition cli.h:152
@ CLI_GENERATE
Definition cli.h:153
#define CLI_FAILURE
Definition cli.h:46
char * command
Definition cli.h:186
const char * usage
Definition cli.h:177
static struct test_val a

References a, ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), ast_iostream_get_fd(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, session, session_notify(), sessions, unref_mansession(), and ast_cli_entry::usage.

◆ handle_manager_reload()

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

1510{
1511 switch (cmd) {
1512 case CLI_INIT:
1513 e->command = "manager reload";
1514 e->usage =
1515 "Usage: manager reload\n"
1516 " Reloads the manager configuration.\n";
1517 return NULL;
1518 case CLI_GENERATE:
1519 return NULL;
1520 }
1521 if (a->argc > 2) {
1522 return CLI_SHOWUSAGE;
1523 }
1524 reload_module();
1525 return CLI_SUCCESS;
1526}
static int reload_module(void)
Definition manager.c:10185

References a, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, reload_module(), and ast_cli_entry::usage.

◆ handle_mandebug()

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

Definition at line 1208 of file manager.c.

1209{
1210 switch (cmd) {
1211 case CLI_INIT:
1212 e->command = "manager set debug [on|off]";
1213 e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n";
1214 return NULL;
1215 case CLI_GENERATE:
1216 return NULL;
1217 }
1218
1219 if (a->argc == 3) {
1220 ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off");
1221 } else if (a->argc == 4) {
1222 if (!strcasecmp(a->argv[3], "on")) {
1223 manager_debug = 1;
1224 } else if (!strcasecmp(a->argv[3], "off")) {
1225 manager_debug = 0;
1226 } else {
1227 return CLI_SHOWUSAGE;
1228 }
1229 }
1230 return CLI_SUCCESS;
1231}

References a, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, manager_debug, NULL, and ast_cli_entry::usage.

◆ handle_parse_error()

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

Definition at line 7325 of file manager.c.

7326{
7327 mansession_lock(s);
7328 astman_send_error(s, m, error);
7329 s->parsing = MESSAGE_OKAY;
7331}

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

Referenced by do_message().

◆ handle_showmanager()

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

Definition at line 1233 of file manager.c.

1234{
1235 struct ast_manager_user *user = NULL;
1236 int l;
1237 struct ast_str *rauthority = ast_str_alloca(MAX_AUTH_PERM_STRING);
1238 struct ast_str *wauthority = ast_str_alloca(MAX_AUTH_PERM_STRING);
1239 struct ast_variable *v;
1240
1241 switch (cmd) {
1242 case CLI_INIT:
1243 e->command = "manager show user";
1244 e->usage =
1245 " Usage: manager show user <user>\n"
1246 " Display all information related to the manager user specified.\n";
1247 return NULL;
1248 case CLI_GENERATE:
1249 l = strlen(a->word);
1250 if (a->pos != 3) {
1251 return NULL;
1252 }
1254 AST_RWLIST_TRAVERSE(&users, user, list) {
1255 if (!strncasecmp(a->word, user->username, l)) {
1256 if (ast_cli_completion_add(ast_strdup(user->username))) {
1257 break;
1258 }
1259 }
1260 }
1262 return NULL;
1263 }
1264
1265 if (a->argc != 4) {
1266 return CLI_SHOWUSAGE;
1267 }
1268
1270
1271 if (!(user = get_manager_by_name_locked(a->argv[3]))) {
1272 ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]);
1274 return CLI_SUCCESS;
1275 }
1276
1277 ast_cli(a->fd, "\n");
1278 ast_cli(a->fd,
1279 " username: %s\n"
1280 " secret: %s\n"
1281 " ACL: %s\n"
1282 " read perm: %s\n"
1283 " write perm: %s\n"
1284 " displayconnects: %s\n"
1285 "allowmultiplelogin: %s\n",
1286 S_OR(user->username, "(N/A)"),
1287 (user->secret ? "<Set>" : "(N/A)"),
1288 ((user->acl && !ast_acl_list_is_empty(user->acl)) ? "yes" : "no"),
1289 user_authority_to_str(user->readperm, &rauthority),
1290 user_authority_to_str(user->writeperm, &wauthority),
1291 (user->displayconnects ? "yes" : "no"),
1292 (user->allowmultiplelogin ? "yes" : "no"));
1293 ast_cli(a->fd, " Variables: \n");
1294 for (v = user->chanvars ; v ; v = v->next) {
1295 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
1296 }
1297 if (!ast_acl_list_is_empty(user->acl)) {
1298 ast_acl_output(a->fd, user->acl, NULL);
1299 }
1300
1302
1303 return CLI_SUCCESS;
1304}
void ast_acl_output(int fd, struct ast_acl_list *acl, const char *prefix)
output an ACL to the provided fd
Definition acl.c:1115
int ast_acl_list_is_empty(struct ast_acl_list *acl_list)
Determines if an ACL is empty or if it contains entries.
Definition acl.c:540
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition main/cli.c:2845
static const char * user_authority_to_str(int authority, struct ast_str **res)
Convert authority code to a list of options for a user. This will only display those authority codes ...
Definition manager.c:742
static int allowmultiplelogin
Definition manager.c:150

References a, ast_acl_list_is_empty(), ast_acl_output(), ast_cli(), ast_cli_completion_add(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_strdup, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, get_manager_by_name_locked(), MAX_AUTH_PERM_STRING, ast_variable::name, ast_variable::next, NULL, S_OR, ast_cli_entry::usage, user_authority_to_str(), and ast_variable::value.

◆ handle_showmanagers()

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

Definition at line 1306 of file manager.c.

1307{
1308 struct ast_manager_user *user = NULL;
1309 int count_amu = 0;
1310 switch (cmd) {
1311 case CLI_INIT:
1312 e->command = "manager show users";
1313 e->usage =
1314 "Usage: manager show users\n"
1315 " Prints a listing of all managers that are currently configured on that\n"
1316 " system.\n";
1317 return NULL;
1318 case CLI_GENERATE:
1319 return NULL;
1320 }
1321 if (a->argc != 3) {
1322 return CLI_SHOWUSAGE;
1323 }
1324
1326
1327 /* If there are no users, print out something along those lines */
1328 if (AST_RWLIST_EMPTY(&users)) {
1329 ast_cli(a->fd, "There are no manager users.\n");
1331 return CLI_SUCCESS;
1332 }
1333
1334 ast_cli(a->fd, "\nusername\n--------\n");
1335
1337 ast_cli(a->fd, "%s\n", user->username);
1338 count_amu++;
1339 }
1340
1342
1343 ast_cli(a->fd,"-------------------\n"
1344 "%d manager users configured.\n", count_amu);
1345 return CLI_SUCCESS;
1346}

References a, ast_cli(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_manager_user::list, NULL, and ast_cli_entry::usage.

◆ handle_showmancmd()

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

Definition at line 1054 of file manager.c.

1055{
1056 struct manager_action *cur;
1057 struct ast_str *authority;
1058 int num;
1059 int l;
1060 const char *auth_str;
1061
1062 switch (cmd) {
1063 case CLI_INIT:
1064 e->command = "manager show command";
1065 e->usage =
1066 "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n"
1067 " Shows the detailed description for a specific Asterisk manager interface command.\n";
1068 return NULL;
1069 case CLI_GENERATE:
1070 l = strlen(a->word);
1072 AST_RWLIST_TRAVERSE(&actions, cur, list) {
1073 if (!strncasecmp(a->word, cur->action, l)) {
1075 break;
1076 }
1077 }
1078 }
1080 return NULL;
1081 }
1082 if (a->argc < 4) {
1083 return CLI_SHOWUSAGE;
1084 }
1085
1087
1089 AST_RWLIST_TRAVERSE(&actions, cur, list) {
1090 for (num = 3; num < a->argc; num++) {
1091 if (!strcasecmp(cur->action, a->argv[num])) {
1092 auth_str = authority_to_str(cur->authority, &authority);
1093
1094#ifdef AST_XML_DOCS
1095 if (cur->docsrc == AST_XML_DOC) {
1096 char *synopsis = ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1);
1097 char *provided_by = ast_xmldoc_printable(S_OR(cur->provided_by, "Not available"), 1);
1098 char *since = ast_xmldoc_printable(S_OR(cur->since, "Not available"), 1);
1099 char *description = ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1);
1100 char *syntax = ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1);
1101 char *arguments = ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1);
1102 char *privilege = ast_xmldoc_printable(S_OR(auth_str, "Not available"), 1);
1103 char *seealso = ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1);
1104 char *responses = ast_xmldoc_printable("None", 1);
1105
1106 if (!synopsis || !provided_by || !since || !description || !syntax || !arguments
1107 || !privilege || !seealso || !responses) {
1109 ast_free(provided_by);
1110 ast_free(since);
1111 ast_free(description);
1112 ast_free(syntax);
1113 ast_free(arguments);
1114 ast_free(privilege);
1115 ast_free(seealso);
1116 ast_free(responses);
1117 ast_cli(a->fd, "Allocation failure.\n");
1119
1120 return CLI_FAILURE;
1121 }
1122
1123 ast_cli(a->fd, "\n"
1124 "%s -= Info about Manager Command '%s' =- %s\n\n"
1125 COLORIZE_FMT "\n"
1126 "%s\n\n"
1127 COLORIZE_FMT "\n"
1128 "%s\n\n"
1129 COLORIZE_FMT "\n"
1130 "%s\n\n"
1131 COLORIZE_FMT "\n"
1132 "%s\n\n"
1133 COLORIZE_FMT "\n"
1134 "%s\n\n"
1135 COLORIZE_FMT "\n"
1136 "%s\n\n"
1137 COLORIZE_FMT "\n"
1138 "%s\n\n"
1139 COLORIZE_FMT "\n"
1140 "%s\n\n"
1141 COLORIZE_FMT "\n",
1143 COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis,
1144 COLORIZE(COLOR_MAGENTA, 0, "[Provided By]"), provided_by,
1145 COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since,
1146 COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description,
1147 COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax,
1148 COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments,
1149 COLORIZE(COLOR_MAGENTA, 0, "[Privilege]"), privilege,
1150 COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso,
1151 COLORIZE(COLOR_MAGENTA, 0, "[List Responses]")
1152 );
1153
1154 if (!cur->list_responses) {
1155 ast_cli(a->fd, "%s\n\n", responses);
1156 } else {
1157 struct ast_xml_doc_item *temp;
1158 for (temp = cur->list_responses; temp; temp = AST_LIST_NEXT(temp, next)) {
1159 ast_cli(a->fd, "Event: %s\n", temp->name);
1160 print_event_instance(a, temp);
1161 }
1162 }
1163 ast_cli(a->fd,
1164 COLORIZE_FMT "\n",
1165 COLORIZE(COLOR_MAGENTA, 0, "[End List Responses]")
1166 );
1167
1168 ast_cli(a->fd, "\n"
1169 COLORIZE_FMT "\n",
1170 COLORIZE(COLOR_MAGENTA, 0, "[Final Response]")
1171 );
1172 if (!cur->final_response) {
1173 ast_cli(a->fd, "%s\n\n", responses);
1174 } else {
1175 ast_cli(a->fd, "Event: %s\n", cur->final_response->name);
1177 }
1178 ast_cli(a->fd,
1179 COLORIZE_FMT "\n",
1180 COLORIZE(COLOR_MAGENTA, 0, "[End Final Response]")
1181 );
1182
1185 ast_free(since);
1189 ast_free(privilege);
1191 ast_free(responses);
1192 } else
1193#endif
1194 {
1195 ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
1196 cur->action, cur->synopsis,
1197 auth_str,
1198 S_OR(cur->description, ""));
1199 }
1200 }
1201 }
1202 }
1204
1205 return CLI_SUCCESS;
1206}
static void print_event_instance(struct ast_cli_args *a, struct ast_xml_doc_item *instance)
Definition manager.c:9358
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Struct that contains the XML documentation for a particular item. Note that this is an ao2 ref counte...
Definition xmldoc.h:56
struct ast_str * syntax
Definition xmldoc.h:58
struct ast_str * provided_by
Definition xmldoc.h:84
struct ast_xml_doc_item * next
Definition xmldoc.h:80
struct ast_str * arguments
Definition xmldoc.h:62
struct ast_str * since
Definition xmldoc.h:82
struct ast_str * description
Definition xmldoc.h:66
const ast_string_field name
Definition xmldoc.h:74
struct ast_str * seealso
Definition xmldoc.h:60
const char * ast_term_reset(void)
Returns the terminal reset code.
Definition term.c:357
#define COLOR_MAGENTA
Definition term.h:60
const char * ast_term_color(int fgcolor, int bgcolor)
Return a color sequence string.
Definition term.c:341
#define COLORIZE(fg, bg, str)
Definition term.h:72
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
Definition term.h:71
char * ast_xmldoc_printable(const char *bwinput, int withcolors)
Colorize and put delimiters (instead of tags) to the xmldoc output.
Definition xmldoc.c:241

References a, manager_action::action, manager_action::arguments, ast_xml_doc_item::arguments, ast_cli(), ast_cli_completion_add(), ast_free, AST_LIST_NEXT, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_strdup, ast_term_color(), ast_term_reset(), AST_XML_DOC, ast_xmldoc_printable(), manager_action::authority, authority_to_str(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_MAGENTA, COLORIZE, COLORIZE_FMT, ast_cli_entry::command, manager_action::description, ast_xml_doc_item::description, manager_action::docsrc, manager_action::final_response, manager_action::list_responses, MAX_AUTH_PERM_STRING, ast_xml_doc_item::name, ast_xml_doc_item::next, NULL, print_event_instance(), ast_xml_doc_item::provided_by, S_OR, manager_action::seealso, ast_xml_doc_item::seealso, ast_xml_doc_item::since, synopsis, manager_action::synopsis, manager_action::syntax, ast_xml_doc_item::syntax, and ast_cli_entry::usage.

◆ handle_showmancmds()

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

1350{
1351 struct manager_action *cur;
1352 int name_len = 1;
1353 int space_remaining;
1354#define HSMC_FORMAT " %-*.*s %-.*s\n"
1355 switch (cmd) {
1356 case CLI_INIT:
1357 e->command = "manager show commands";
1358 e->usage =
1359 "Usage: manager show commands\n"
1360 " Prints a listing of all the available Asterisk manager interface commands.\n";
1361 return NULL;
1362 case CLI_GENERATE:
1363 return NULL;
1364 }
1365
1368 int incoming_len = strlen(cur->action);
1369 if (incoming_len > name_len) {
1370 name_len = incoming_len;
1371 }
1372 }
1373
1374 space_remaining = MGR_SHOW_TERMINAL_WIDTH - name_len - 4;
1375 if (space_remaining < 0) {
1376 space_remaining = 0;
1377 }
1378
1379 ast_cli(a->fd, HSMC_FORMAT, name_len, name_len, "Action", space_remaining, "Synopsis");
1380 ast_cli(a->fd, HSMC_FORMAT, name_len, name_len, "------", space_remaining, "--------");
1381
1383 ast_cli(a->fd, HSMC_FORMAT, name_len, name_len, cur->action, space_remaining, cur->synopsis);
1384 }
1386
1387 return CLI_SUCCESS;
1388}
#define MGR_SHOW_TERMINAL_WIDTH
Definition manager.c:191
#define HSMC_FORMAT

References a, manager_action::action, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, HSMC_FORMAT, manager_action::list, MGR_SHOW_TERMINAL_WIDTH, NULL, manager_action::synopsis, and ast_cli_entry::usage.

◆ handle_showmanconn()

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

1458{
1459 struct ao2_container *sessions;
1461 time_t now = time(NULL);
1462#define HSMCONN_FORMAT1 " %-15.15s %-55.55s %-10.10s %-10.10s %-8.8s %-8.8s %-10.10s %-10.10s\n"
1463#define HSMCONN_FORMAT2 " %-15.15s %-55.55s %-10d %-10d %-8d %-8d %-10.10d %-10.10d\n"
1464 int count = 0;
1465 struct ao2_iterator i;
1466
1467 switch (cmd) {
1468 case CLI_INIT:
1469 e->command = "manager show connected";
1470 e->usage =
1471 "Usage: manager show connected\n"
1472 " Prints a listing of the users that are currently connected to the\n"
1473 "Asterisk manager interface.\n";
1474 return NULL;
1475 case CLI_GENERATE:
1476 return NULL;
1477 }
1478
1479 ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "ReadPerms", "WritePerms");
1480
1481 sessions = ao2_global_obj_ref(mgr_sessions);
1482 if (sessions) {
1484 ao2_ref(sessions, -1);
1485 while ((session = ao2_iterator_next(&i))) {
1487 ast_cli(a->fd, HSMCONN_FORMAT2, session->username,
1489 (int) (session->sessionstart),
1490 (int) (now - session->sessionstart),
1491 session->stream ? ast_iostream_get_fd(session->stream) : -1,
1492 session->inuse,
1493 session->readperm,
1494 session->writeperm);
1495 count++;
1498 }
1500 }
1501 ast_cli(a->fd, "%d users connected.\n", count);
1502
1503 return CLI_SUCCESS;
1504}
#define HSMCONN_FORMAT1
#define HSMCONN_FORMAT2

References a, ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), ast_iostream_get_fd(), ast_sockaddr_stringify_addr(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, HSMCONN_FORMAT1, HSMCONN_FORMAT2, NULL, session, sessions, unref_mansession(), and ast_cli_entry::usage.

◆ handle_updates()

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

helper function for action_updateconfig

Definition at line 2670 of file manager.c.

2671{
2672 int x;
2673 char hdr[40];
2674 const char *action, *cat, *var, *value, *match, *line, *options;
2675 struct ast_variable *v;
2676 struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16);
2677 enum error_type result = 0;
2678
2679 for (x = 0; x < 100000; x++) { /* 100000 = the max number of allowed updates + 1 */
2680 unsigned int object = 0;
2681 char *dupoptions;
2682 int allowdups = 0;
2683 int istemplate = 0;
2684 int ignoreerror = 0;
2685 RAII_VAR(char *, inherit, NULL, ast_free);
2686 RAII_VAR(char *, catfilter, NULL, ast_free);
2687 char *token;
2688 int foundvar = 0;
2689 int foundcat = 0;
2690 struct ast_category *category = NULL;
2691
2692 snprintf(hdr, sizeof(hdr), "Action-%06d", x);
2693 action = astman_get_header(m, hdr);
2694 if (ast_strlen_zero(action)) /* breaks the for loop if no action header */
2695 break; /* this could cause problems if actions come in misnumbered */
2696
2697 snprintf(hdr, sizeof(hdr), "Cat-%06d", x);
2698 cat = astman_get_header(m, hdr);
2699 if (ast_strlen_zero(cat)) { /* every action needs a category */
2701 break;
2702 }
2703
2704 snprintf(hdr, sizeof(hdr), "Var-%06d", x);
2705 var = astman_get_header(m, hdr);
2706
2707 snprintf(hdr, sizeof(hdr), "Value-%06d", x);
2708 value = astman_get_header(m, hdr);
2709
2710 if (!ast_strlen_zero(value) && *value == '>') {
2711 object = 1;
2712 value++;
2713 }
2714
2715 snprintf(hdr, sizeof(hdr), "Match-%06d", x);
2716 match = astman_get_header(m, hdr);
2717
2718 snprintf(hdr, sizeof(hdr), "Line-%06d", x);
2719 line = astman_get_header(m, hdr);
2720
2721 snprintf(hdr, sizeof(hdr), "Options-%06d", x);
2722 options = astman_get_header(m, hdr);
2723 if (!ast_strlen_zero(options)) {
2724 char copy[strlen(options) + 1];
2725 strcpy(copy, options); /* safe */
2726 dupoptions = copy;
2727 while ((token = ast_strsep(&dupoptions, ',', AST_STRSEP_STRIP))) {
2728 if (!strcasecmp("allowdups", token)) {
2729 allowdups = 1;
2730 continue;
2731 }
2732 if (!strcasecmp("template", token)) {
2733 istemplate = 1;
2734 continue;
2735 }
2736 if (!strcasecmp("ignoreerror", token)) {
2737 ignoreerror = 1;
2738 continue;
2739 }
2740 if (ast_begins_with(token, "inherit")) {
2741 char *c = ast_strsep(&token, '=', AST_STRSEP_STRIP);
2742 c = ast_strsep(&token, '=', AST_STRSEP_STRIP);
2743 if (c) {
2744 inherit = ast_strdup(c);
2745 }
2746 continue;
2747 }
2748 if (ast_begins_with(token, "catfilter")) {
2749 char *c = ast_strsep(&token, '=', AST_STRSEP_STRIP);
2750 c = ast_strsep(&token, '=', AST_STRSEP_STRIP);
2751 if (c) {
2752 catfilter = ast_strdup(c);
2753 }
2754 continue;
2755 }
2756 }
2757 }
2758
2759 if (!strcasecmp(action, "newcat")) {
2760 struct ast_category *template;
2761 char *tmpl_name = NULL;
2762
2763 if (!allowdups) {
2764 if (ast_category_get(cfg, cat, "TEMPLATES=include")) {
2765 if (ignoreerror) {
2766 continue;
2767 } else {
2768 result = FAILURE_NEWCAT; /* already exist */
2769 break;
2770 }
2771 }
2772 }
2773
2774 if (istemplate) {
2775 category = ast_category_new_template(cat, dfn, -1);
2776 } else {
2777 category = ast_category_new(cat, dfn, -1);
2778 }
2779
2780 if (!category) {
2782 break;
2783 }
2784
2785 if (inherit) {
2786 while ((tmpl_name = ast_strsep(&inherit, ',', AST_STRSEP_STRIP))) {
2787 if ((template = ast_category_get(cfg, tmpl_name, "TEMPLATES=restrict"))) {
2788 if (ast_category_inherit(category, template)) {
2790 break;
2791 }
2792 } else {
2793 ast_category_destroy(category);
2794 category = NULL;
2795 result = FAILURE_TEMPLATE; /* template not found */
2796 break;
2797 }
2798 }
2799 }
2800
2801 if (category != NULL) {
2802 if (ast_strlen_zero(match)) {
2803 ast_category_append(cfg, category);
2804 } else {
2805 if (ast_category_insert(cfg, category, match)) {
2806 ast_category_destroy(category);
2808 break;
2809 }
2810 }
2811 }
2812 } else if (!strcasecmp(action, "renamecat")) {
2813 if (ast_strlen_zero(value)) {
2815 break;
2816 }
2817
2818 foundcat = 0;
2819 while ((category = ast_category_browse_filtered(cfg, cat, category, catfilter))) {
2820 ast_category_rename(category, value);
2821 foundcat = 1;
2822 }
2823
2824 if (!foundcat) {
2826 break;
2827 }
2828 } else if (!strcasecmp(action, "delcat")) {
2829 foundcat = 0;
2830 while ((category = ast_category_browse_filtered(cfg, cat, category, catfilter))) {
2831 category = ast_category_delete(cfg, category);
2832 foundcat = 1;
2833 }
2834
2835 if (!foundcat && !ignoreerror) {
2837 break;
2838 }
2839 } else if (!strcasecmp(action, "emptycat")) {
2840 foundcat = 0;
2841 while ((category = ast_category_browse_filtered(cfg, cat, category, catfilter))) {
2842 ast_category_empty(category);
2843 foundcat = 1;
2844 }
2845
2846 if (!foundcat) {
2848 break;
2849 }
2850 } else if (!strcasecmp(action, "update")) {
2851 if (ast_strlen_zero(var)) {
2853 break;
2854 }
2855
2856 foundcat = 0;
2857 foundvar = 0;
2858 while ((category = ast_category_browse_filtered(cfg, cat, category, catfilter))) {
2859 if (!ast_variable_update(category, var, value, match, object)) {
2860 foundvar = 1;
2861 }
2862 foundcat = 1;
2863 }
2864
2865 if (!foundcat) {
2867 break;
2868 }
2869
2870 if (!foundvar) {
2872 break;
2873 }
2874 } else if (!strcasecmp(action, "delete")) {
2875 if ((ast_strlen_zero(var) && ast_strlen_zero(line))) {
2877 break;
2878 }
2879
2880 foundcat = 0;
2881 foundvar = 0;
2882 while ((category = ast_category_browse_filtered(cfg, cat, category, catfilter))) {
2883 if (!ast_variable_delete(category, var, match, line)) {
2884 foundvar = 1;
2885 }
2886 foundcat = 1;
2887 }
2888
2889 if (!foundcat) {
2891 break;
2892 }
2893
2894 if (!foundvar && !ignoreerror) {
2896 break;
2897 }
2898 } else if (!strcasecmp(action, "append")) {
2899 if (ast_strlen_zero(var)) {
2901 break;
2902 }
2903
2904 foundcat = 0;
2905 while ((category = ast_category_browse_filtered(cfg, cat, category, catfilter))) {
2906 if (!(v = ast_variable_new(var, value, dfn))) {
2908 break;
2909 }
2910 if (object || (match && !strcasecmp(match, "object"))) {
2911 v->object = 1;
2912 }
2913 ast_variable_append(category, v);
2914 foundcat = 1;
2915 }
2916
2917 if (!foundcat) {
2919 break;
2920 }
2921 } else if (!strcasecmp(action, "insert")) {
2922 if (ast_strlen_zero(var) || ast_strlen_zero(line)) {
2924 break;
2925 }
2926
2927 foundcat = 0;
2928 while ((category = ast_category_browse_filtered(cfg, cat, category, catfilter))) {
2929 if (!(v = ast_variable_new(var, value, dfn))) {
2931 break;
2932 }
2933 ast_variable_insert(category, v, line);
2934 foundcat = 1;
2935 }
2936
2937 if (!foundcat) {
2939 break;
2940 }
2941 }
2942 else {
2943 ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action);
2945 break;
2946 }
2947 }
2948 ast_free(str1);
2949 ast_free(str2);
2950 return result;
2951}
static int copy(char *infile, char *outfile)
Utility function to copy a file.
int ast_category_inherit(struct ast_category *existing, const struct ast_category *base)
Applies base (template) to category.
struct ast_category * ast_category_new_template(const char *name, const char *in_file, int lineno)
Create a category making it a template.
struct ast_category * ast_category_delete(struct ast_config *cfg, struct ast_category *cat)
Delete a category.
void ast_category_rename(struct ast_category *cat, const char *name)
int ast_variable_delete(struct ast_category *category, const char *variable, const char *match, const char *line)
int ast_category_insert(struct ast_config *config, struct ast_category *cat, const char *match)
Inserts new category.
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
Definition extconf.c:2831
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition extconf.c:1175
int ast_variable_update(struct ast_category *category, const char *variable, const char *value, const char *match, unsigned int object)
Update variable value within a config.
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category.
Definition extconf.c:2786
#define ast_variable_new(name, value, filename)
void ast_category_destroy(struct ast_category *cat)
Definition extconf.c:2843
int ast_category_empty(struct ast_category *category)
Removes and destroys all variables in a category.
void ast_variable_insert(struct ast_category *category, struct ast_variable *variable, const char *line)
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
@ AST_STRSEP_STRIP
Definition strings.h:255
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Definition utils.c:1869
static struct test_options options

References ast_begins_with(), ast_category_append(), ast_category_browse_filtered(), ast_category_delete(), ast_category_destroy(), ast_category_empty(), ast_category_get(), ast_category_inherit(), ast_category_insert(), ast_category_new(), ast_category_new_template(), ast_category_rename(), ast_free, ast_log, ast_str_create, ast_strdup, ast_strlen_zero(), ast_strsep(), AST_STRSEP_STRIP, ast_variable_append(), ast_variable_delete(), ast_variable_insert(), ast_variable_new, ast_variable_update(), astman_get_header(), c, copy(), FAILURE_ALLOCATION, FAILURE_NEWCAT, FAILURE_TEMPLATE, FAILURE_UPDATE, LOG_WARNING, match(), NULL, ast_variable::object, options, RAII_VAR, result, UNKNOWN_ACTION, UNKNOWN_CATEGORY, UNSPECIFIED_ARGUMENT, UNSPECIFIED_CATEGORY, value, and var.

Referenced by action_updateconfig().

◆ is_originate_app_permitted()

static int is_originate_app_permitted ( const char *  app,
const char *  data,
int  permission 
)
static

Definition at line 5169 of file manager.c.

5171{
5172 int i;
5173
5174 for (i = 0; originate_app_permissions[i].search; i++) {
5175 if (originate_app_permissions[i].searchfn(app, data, originate_app_permissions[i].search)) {
5177 }
5178 }
5179
5180 return 1;
5181}
static struct originate_permissions_entry originate_app_permissions[]
Definition manager.c:5133
int permission
Definition manager.c:5043
const char * search
Definition manager.c:5042

References app, originate_app_permissions, originate_permissions_entry::permission, and originate_permissions_entry::search.

Referenced by action_originate().

◆ is_restricted_file()

static int is_restricted_file ( const char *  filename)
static

Check if a file is restricted or not.

Returns
0 on success
1 on restricted file
-1 on failure

Definition at line 2415 of file manager.c.

2416{
2417 char *stripped_filename;
2418 RAII_VAR(char *, path, NULL, ast_free);
2419 RAII_VAR(char *, real_path, NULL, ast_std_free);
2420
2421 if (live_dangerously) {
2422 return 0;
2423 }
2424
2425 stripped_filename = ast_strip(ast_strdupa(filename));
2426
2427 /* If the file path starts with '/', don't prepend ast_config_AST_CONFIG_DIR */
2428 if (stripped_filename[0] == '/') {
2429 real_path = realpath(stripped_filename, NULL);
2430 } else {
2431 if (ast_asprintf(&path, "%s/%s", ast_config_AST_CONFIG_DIR, stripped_filename) == -1) {
2432 return -1;
2433 }
2434 real_path = realpath(path, NULL);
2435 }
2436
2437 if (!real_path) {
2438 return -1;
2439 }
2440
2441 if (!ast_begins_with(real_path, ast_config_AST_CONFIG_DIR)) {
2442 return 1;
2443 }
2444
2445 return 0;
2446}

References ast_asprintf, ast_begins_with(), ast_config_AST_CONFIG_DIR, ast_free, ast_std_free(), ast_strdupa, ast_strip(), live_dangerously, NULL, and RAII_VAR.

Referenced by action_getconfig(), action_getconfigjson(), action_listcategories(), and action_updateconfig().

◆ json_escape()

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

2570{
2571 for (; *in; in++) {
2572 if (*in == '\\' || *in == '\"') {
2573 *out++ = '\\';
2574 }
2575 *out++ = *in;
2576 }
2577 *out = '\0';
2578}
FILE * out
Definition utils/frame.c:33

References in, and out.

Referenced by astman_append_json().

◆ log_action()

static void log_action ( const struct message m,
const char *  action 
)
static

Definition at line 7050 of file manager.c.

7051{
7052 struct ast_str *buf;
7053 int x;
7054
7055 if (!manager_debug) {
7056 return;
7057 }
7058
7059 buf = ast_str_create(256);
7060 if (!buf) {
7061 return;
7062 }
7063
7064 for (x = 0; x < m->hdrcount; ++x) {
7065 if (!strncasecmp(m->headers[x], "Secret", 6)) {
7066 ast_str_append(&buf, 0, "Secret: <redacted from logging>\n");
7067 } else {
7068 ast_str_append(&buf, 0, "%s\n", m->headers[x]);
7069 }
7070 }
7071
7072 ast_verbose("<--- Examining AMI action: -->\n%s\n", ast_str_buffer(buf));
7073 ast_free(buf);
7074}

References ast_free, ast_str_append(), ast_str_buffer(), ast_str_create, ast_verbose, buf, message::hdrcount, message::headers, and manager_debug.

Referenced by process_message().

◆ man_do_variable_value()

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

Definition at line 1624 of file manager.c.

1625{
1626 char *parse;
1628 AST_APP_ARG(vars)[64];
1629 );
1630
1631 hdr_val = ast_skip_blanks(hdr_val); /* ignore leading spaces in the value */
1632 parse = ast_strdupa(hdr_val);
1633
1634 /* Break the header value string into name=val pair items. */
1636 if (args.argc) {
1637 int y;
1638
1639 /* Process each name=val pair item. */
1640 for (y = 0; y < args.argc; y++) {
1641 struct ast_variable *cur;
1642 char *var;
1643 char *val;
1644
1645 if (!args.vars[y]) {
1646 continue;
1647 }
1648 var = val = args.vars[y];
1649 strsep(&val, "=");
1650
1651 /* XXX We may wish to trim whitespace from the strings. */
1652 if (!val || ast_strlen_zero(var)) {
1653 continue;
1654 }
1655
1656 /* Create new variable list node and prepend it to the list. */
1657 cur = ast_variable_new(var, val, "");
1658 if (cur) {
1659 cur->next = head;
1660 head = cur;
1661 }
1662 }
1663 }
1664
1665 return head;
1666}
static struct @522 args

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_skip_blanks(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_variable_new, ast_variable::next, strsep(), and var.

Referenced by astman_get_variables_order().

◆ manager_add_filter()

static enum add_filter_result manager_add_filter ( const char *  criteria,
const char *  filter_pattern,
struct ao2_container includefilters,
struct ao2_container excludefilters 
)
static

Add an event filter to a manager session.

Parameters
criteriaSee examples in manager.conf.sample
filter_patternFilter pattern
includefilters,excludefilters
Returns
FILTER_ALLOC_FAILED Memory allocation failure
FILTER_COMPILE_FAIL If the filter did not compile
FILTER_FORMAT_ERROR If the criteria weren't formatted correctly
FILTER_SUCCESS Success

Examples: See examples in manager.conf.sample

Definition at line 5800 of file manager.c.

5803{
5804 RAII_VAR(struct event_filter_entry *, filter_entry,
5805 ao2_t_alloc(sizeof(*filter_entry), event_filter_destructor, "event_filter allocation"),
5806 ao2_cleanup);
5807 const char *options_start = NULL;
5808 SCOPE_ENTER(3, "manager_add_filter(%s, %s, %p, %p)", criteria, filter_pattern, includefilters, excludefilters);
5809
5810 if (!filter_entry) {
5811 SCOPE_EXIT_LOG_RTN_VALUE(FILTER_ALLOC_FAILED, LOG_WARNING, "Unable to allocate filter_entry");
5812 }
5813
5814 /*
5815 * At a minimum, criteria must be "eventfilter" but may contain additional
5816 * constraints.
5817 */
5818 if (ast_strlen_zero(criteria)) {
5820 }
5821
5822 /*
5823 * filter_pattern could be empty but it should never be NULL.
5824 */
5825 if (!filter_pattern) {
5826 SCOPE_EXIT_LOG_RTN_VALUE(FILTER_FORMAT_ERROR, LOG_WARNING, "Filter pattern was NULL");
5827 }
5828
5829 /*
5830 * For a legacy filter, if the first character of filter_pattern is
5831 * '!' then it's an exclude filter. It's also accepted as an alternative
5832 * to specifying "action(exclude)" for an advanced filter. If
5833 * "action" is specified however, it will take precedence.
5834 */
5835 if (filter_pattern[0] == '!') {
5836 filter_entry->is_excludefilter = 1;
5837 filter_pattern++;
5838 }
5839
5840 /*
5841 * This is the default
5842 */
5843 filter_entry->match_type = FILTER_MATCH_REGEX;
5844
5845 /*
5846 * If the criteria has a '(' in it, then it's an advanced filter.
5847 */
5848 options_start = strstr(criteria, "(");
5849
5850 /*
5851 * If it's a legacy filter, there MUST be a filter pattern.
5852 */
5853 if (!options_start && ast_strlen_zero(filter_pattern)) {
5855 "'%s = %s': Legacy filter with no filter pattern specified\n",
5856 criteria, filter_pattern);
5857 }
5858
5859 if (options_start) {
5860 /*
5861 * This is an advanced filter
5862 */
5863 char *temp = ast_strdupa(options_start + 1); /* skip over the leading '(' */
5864 char *saveptr = NULL;
5865 char *option = NULL;
5866 enum found_options {
5867 action_found = (1 << 0),
5868 name_found = (1 << 1),
5869 header_found = (1 << 2),
5870 method_found = (1 << 3),
5871 };
5872 enum found_options options_found = 0;
5873
5874 filter_entry->match_type = FILTER_MATCH_NONE;
5875
5876 ast_strip(temp);
5877 if (ast_strlen_zero(temp) || !ast_ends_with(temp, ")")) {
5879 "'%s = %s': Filter options not formatted correctly\n",
5880 criteria, filter_pattern);
5881 }
5882
5883 /*
5884 * These can actually be in any order...
5885 * action(include|exclude),name(<event_name>),header(<header_name>),method(<match_method>)
5886 * At least one of action, name, or header is required.
5887 */
5888 while ((option = strtok_r(temp, " ,)", &saveptr))) {
5889 if (!strncmp(option, "action", 6)) {
5890 char *method = strstr(option, "(");
5891 if (ast_strlen_zero(method)) {
5892 SCOPE_EXIT_LOG_RTN_VALUE(FILTER_FORMAT_ERROR, LOG_WARNING, "'%s = %s': 'action' parameter not formatted correctly\n",
5893 criteria, filter_pattern);
5894 }
5895 method++;
5897 if (!strcmp(method, "include")) {
5898 filter_entry->is_excludefilter = 0;
5899 } else if (!strcmp(method, "exclude")) {
5900 filter_entry->is_excludefilter = 1;
5901 } else {
5902 SCOPE_EXIT_LOG_RTN_VALUE(FILTER_FORMAT_ERROR, LOG_WARNING, "'%s = %s': 'action' option '%s' is unknown\n",
5903 criteria, filter_pattern, method);
5904 }
5905 options_found |= action_found;
5906 } else if (!strncmp(option, "name", 4)) {
5907 char *event_name = strstr(option, "(");
5908 event_name++;
5909 ast_strip(event_name);
5910 if (ast_strlen_zero(event_name)) {
5911 SCOPE_EXIT_LOG_RTN_VALUE(FILTER_FORMAT_ERROR, LOG_WARNING, "'%s = %s': 'name' parameter not formatted correctly\n",
5912 criteria, filter_pattern);
5913 }
5914 filter_entry->event_name = ast_strdup(event_name);
5915 filter_entry->event_name_hash = ast_str_hash(event_name);
5916 options_found |= name_found;
5917 } else if (!strncmp(option, "header", 6)) {
5918 char *header_name = strstr(option, "(");
5919 header_name++;
5920 ast_strip(header_name);
5921 if (ast_strlen_zero(header_name)) {
5922 SCOPE_EXIT_LOG_RTN_VALUE(FILTER_FORMAT_ERROR, LOG_WARNING, "'%s = %s': 'header' parameter not formatted correctly\n",
5923 criteria, filter_pattern);
5924 }
5925 if (!ast_ends_with(header_name, ":")) {
5926 filter_entry->header_name = ast_malloc(strlen(header_name) + 2);
5927 if (!filter_entry->header_name) {
5928 SCOPE_EXIT_LOG_RTN_VALUE(FILTER_ALLOC_FAILED, LOG_ERROR, "Unable to allocate memory for header_name");
5929 }
5930 sprintf(filter_entry->header_name, "%s:", header_name); /* Safe */
5931 } else {
5932 filter_entry->header_name = ast_strdup(header_name);
5933 }
5934 options_found |= header_found;
5935 } else if (!strncmp(option, "method", 6)) {
5936 char *method = strstr(option, "(");
5937 method++;
5939 if (ast_strlen_zero(method)) {
5940 SCOPE_EXIT_LOG_RTN_VALUE(FILTER_FORMAT_ERROR, LOG_WARNING, "'%s = %s': 'method' parameter not formatted correctly\n",
5941 criteria, filter_pattern);
5942 }
5943 if (!strcmp(method, "regex")) {
5944 filter_entry->match_type = FILTER_MATCH_REGEX;
5945 } else if (!strcmp(method, "exact")) {
5946 filter_entry->match_type = FILTER_MATCH_EXACT;
5947 } else if (!strcmp(method, "starts_with")) {
5948 filter_entry->match_type = FILTER_MATCH_STARTS_WITH;
5949 } else if (!strcmp(method, "ends_with")) {
5950 filter_entry->match_type = FILTER_MATCH_ENDS_WITH;
5951 } else if (!strcmp(method, "contains")) {
5952 filter_entry->match_type = FILTER_MATCH_CONTAINS;
5953 } else if (!strcmp(method, "none")) {
5954 filter_entry->match_type = FILTER_MATCH_NONE;
5955 } else {
5956 SCOPE_EXIT_LOG_RTN_VALUE(FILTER_FORMAT_ERROR, LOG_WARNING, "'%s = %s': 'method' option '%s' is unknown\n",
5957 criteria, filter_pattern, method);
5958 }
5959 options_found |= method_found;
5960 } else {
5961 SCOPE_EXIT_LOG_RTN_VALUE(FILTER_FORMAT_ERROR, LOG_WARNING, "'%s = %s': Filter option '%s' is unknown\n",
5962 criteria, filter_pattern, option);
5963 }
5964 temp = NULL;
5965 }
5966 if (!options_found) {
5968 "'%s = %s': No action, name, header, or method option found\n",
5969 criteria, filter_pattern);
5970 }
5971 if (ast_strlen_zero(filter_pattern) && filter_entry->match_type != FILTER_MATCH_NONE) {
5973 "'%s = %s': method can't be '%s' with no filter pattern\n",
5974 criteria, filter_pattern, match_type_names[filter_entry->match_type]);
5975 }
5976 if (!ast_strlen_zero(filter_pattern) && filter_entry->match_type == FILTER_MATCH_NONE) {
5978 "'%s = %s': method can't be 'none' with a filter pattern\n",
5979 criteria, filter_pattern);
5980 }
5981 if (!(options_found & name_found) && !(options_found & header_found) &&
5982 filter_entry->match_type == FILTER_MATCH_NONE) {
5984 "'%s = %s': No name or header option found and no filter pattern\n",
5985 criteria, filter_pattern);
5986 }
5987 }
5988
5989 if (!ast_strlen_zero(filter_pattern)) {
5990 if (filter_entry->match_type == FILTER_MATCH_REGEX) {
5991 filter_entry->regex_filter = ast_calloc(1, sizeof(regex_t));
5992 if (!filter_entry->regex_filter) {
5993 SCOPE_EXIT_LOG_RTN_VALUE(FILTER_ALLOC_FAILED, LOG_ERROR, "Unable to allocate memory for regex_filter");
5994 }
5995 if (regcomp(filter_entry->regex_filter, filter_pattern, REG_EXTENDED | REG_NOSUB)) {
5996 SCOPE_EXIT_LOG_RTN_VALUE(FILTER_COMPILE_FAIL, LOG_WARNING, "Unable to compile regex filter for '%s'", filter_pattern);
5997 }
5998 } else {
5999 filter_entry->string_filter = ast_strdup(filter_pattern);
6000 }
6001 }
6002
6003 ast_debug(2, "Event filter:\n"
6004 "conf entry: %s = %s\n"
6005 "event_name: %s (hash: %d)\n"
6006 "test_header: %s\n"
6007 "match_type: %s\n"
6008 "regex_filter: %p\n"
6009 "string filter: %s\n"
6010 "is excludefilter: %d\n",
6011 criteria, filter_pattern,
6012 S_OR(filter_entry->event_name, "<not used>"),
6013 filter_entry->event_name_hash,
6014 S_OR(filter_entry->header_name, "<not used>"),
6015 match_type_names[filter_entry->match_type],
6016 filter_entry->regex_filter,
6017 filter_entry->string_filter,
6018 filter_entry->is_excludefilter);
6019
6020 if (filter_entry->is_excludefilter) {
6021 ao2_t_link(excludefilters, filter_entry, "link new filter into exclude user container");
6022 } else {
6023 ao2_t_link(includefilters, filter_entry, "link new filter into include user container");
6024 }
6025
6026 SCOPE_EXIT_RTN_VALUE(FILTER_SUCCESS, "Filter added successfully");
6027}
static char * match_type_names[]
Definition manager.c:385
static void event_filter_destructor(void *obj)
Definition manager.c:874
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_EXIT_LOG_RTN_VALUE(__value, __log_level,...)
#define SCOPE_ENTER(level,...)
const char * method
Definition res_pjsip.c:1277

References ao2_cleanup, ao2_t_alloc, ao2_t_link, ast_calloc, ast_debug, ast_ends_with(), ast_malloc, ast_str_hash(), ast_strdup, ast_strdupa, ast_strip(), ast_strlen_zero(), event_filter_destructor(), FILTER_ALLOC_FAILED, FILTER_COMPILE_FAIL, FILTER_FORMAT_ERROR, FILTER_MATCH_CONTAINS, FILTER_MATCH_ENDS_WITH, FILTER_MATCH_EXACT, FILTER_MATCH_NONE, FILTER_MATCH_REGEX, FILTER_MATCH_STARTS_WITH, FILTER_SUCCESS, LOG_ERROR, LOG_WARNING, match_type_names, method, NULL, RAII_VAR, S_OR, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, and SCOPE_EXIT_RTN_VALUE.

Referenced by __init_manager(), and action_filter().

◆ manager_default_msg_cb()

static void manager_default_msg_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 559 of file manager.c.

561{
562 struct ao2_container *sessions = data;
563 struct ast_manager_event_blob *ev;
564
565 /*
566 * This callback only receives messages that can be turned into AMI events, so
567 * no need to check that the message can be turned into an event before checking for listeners.
568 */
570 /* Nobody is listening */
571 return;
572 }
573
575 if (!ev) {
576 /* Conversion failure */
577 return;
578 }
579
581 "%s", ev->extra_fields);
582 ao2_ref(ev, -1);
583}
#define manager_event_sessions(sessions, category, event, contents,...)
Definition manager.c:553
struct ast_manager_event_blob * stasis_message_to_ami(struct stasis_message *msg)
Build the AMI representation of the message.
Struct containing info for an AMI event to send out.
Definition manager.h:504
const ast_string_field extra_fields
Definition manager.h:509
const char * manager_event
Definition manager.h:506

References any_manager_listeners, ao2_ref, ast_manager_event_blob::event_flags, ast_manager_event_blob::extra_fields, ast_manager_event_blob::manager_event, manager_event_sessions, sessions, and stasis_message_to_ami().

Referenced by manager_subscriptions_init().

◆ manager_displayconnects()

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

1037{
1038 struct ast_manager_user *user = NULL;
1039 int ret = 0;
1040
1042 if ((user = get_manager_by_name_locked(session->username))) {
1043 ret = user->displayconnects;
1044 }
1046
1047 return ret;
1048}

References AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, get_manager_by_name_locked(), NULL, and session.

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

◆ manager_generic_msg_cb()

static void manager_generic_msg_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 585 of file manager.c.

587{
588 struct ast_json_payload *payload;
589 int class_type;
590 const char *type;
591 struct ast_json *event;
592 struct ast_str *event_buffer;
593 struct ao2_container *sessions = data;
594
596 /* Nobody is listening */
597 return;
598 }
599
600 payload = stasis_message_data(message);
601 class_type = ast_json_integer_get(ast_json_object_get(payload->json, "class_type"));
603 event = ast_json_object_get(payload->json, "event");
604
606 if (!event_buffer) {
607 ast_log(AST_LOG_WARNING, "Error while creating payload for event %s\n", type);
608 return;
609 }
610
612 "%s", ast_str_buffer(event_buffer));
613 ast_free(event_buffer);
614}
struct ast_str * ast_manager_str_from_json_object(struct ast_json *blob, key_exclusion_cb exclusion_cb)
Convert a JSON object into an AMI compatible string.
Definition manager.c:542
#define AST_LOG_WARNING
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition json.c:283
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition json.c:407
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition json.c:332
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct ast_json * json
Definition json.h:1083

References any_manager_listeners, ast_free, ast_json_integer_get(), ast_json_object_get(), ast_json_string_get(), ast_log, AST_LOG_WARNING, ast_manager_str_from_json_object(), ast_str_buffer(), ast_json_payload::json, manager_event_sessions, NULL, sessions, stasis_message_data(), and type.

Referenced by manager_subscriptions_init().

◆ manager_json_array_with_key()

static void manager_json_array_with_key ( struct ast_json obj,
const char *  key,
size_t  index,
struct ast_str **  res,
key_exclusion_cb  exclusion_cb 
)
static

Definition at line 476 of file manager.c.

479{
480 struct ast_str *key_str = ast_str_alloca(64);
481 ast_str_set(&key_str, 0, "%s(%zu)", key, index);
483 res, exclusion_cb);
484}

References ast_str_alloca, ast_str_buffer(), ast_str_set(), and manager_json_to_ast_str().

Referenced by manager_json_to_ast_str().

◆ manager_json_obj_with_key()

static void manager_json_obj_with_key ( struct ast_json obj,
const char *  key,
const char *  parent_key,
struct ast_str **  res,
key_exclusion_cb  exclusion_cb 
)
static

Definition at line 486 of file manager.c.

489{
490 if (parent_key) {
491 struct ast_str *key_str = ast_str_alloca(64);
492 ast_str_set(&key_str, 0, "%s/%s", parent_key, key);
494 res, exclusion_cb);
495 return;
496 }
497
498 manager_json_to_ast_str(obj, key, res, exclusion_cb);
499}

References ast_str_alloca, ast_str_buffer(), ast_str_set(), and manager_json_to_ast_str().

Referenced by manager_json_to_ast_str().

◆ manager_json_to_ast_str()

void manager_json_to_ast_str ( struct ast_json obj,
const char *  key,
struct ast_str **  res,
key_exclusion_cb  exclusion_cb 
)
static

Definition at line 501 of file manager.c.

503{
504 struct ast_json_iter *i;
505
506 /* If obj or res is not given, just return */
507 if (!obj || !res) {
508 return;
509 }
510
511 if (!*res && !(*res = ast_str_create(1024))) {
512 return;
513 }
514
515 if (exclusion_cb && key && exclusion_cb(key)) {
516 return;
517 }
518
519 if (ast_json_typeof(obj) != AST_JSON_OBJECT &&
521 manager_json_value_str_append(obj, key, res);
522 return;
523 }
524
525 if (ast_json_typeof(obj) == AST_JSON_ARRAY) {
526 size_t j;
527 for (j = 0; j < ast_json_array_size(obj); ++j) {
529 key, j, res, exclusion_cb);
530 }
531 return;
532 }
533
534 for (i = ast_json_object_iter(obj); i;
535 i = ast_json_object_iter_next(obj, i)) {
538 key, res, exclusion_cb);
539 }
540}
static void manager_json_array_with_key(struct ast_json *obj, const char *key, size_t index, struct ast_str **res, key_exclusion_cb exclusion_cb)
Definition manager.c:476
static void manager_json_value_str_append(struct ast_json *value, const char *key, struct ast_str **res)
Definition manager.c:451
static void manager_json_obj_with_key(struct ast_json *obj, const char *key, const char *parent_key, struct ast_str **res, key_exclusion_cb exclusion_cb)
Definition manager.c:486
struct ast_json * ast_json_object_iter_value(struct ast_json_iter *iter)
Get the value from an iterator.
Definition json.c:455
enum ast_json_type ast_json_typeof(const struct ast_json *value)
Get the type of value.
Definition json.c:78
struct ast_json_iter * ast_json_object_iter_next(struct ast_json *object, struct ast_json_iter *iter)
Get the next iterator.
Definition json.c:447
struct ast_json * ast_json_array_get(const struct ast_json *array, size_t index)
Get an element from an array.
Definition json.c:370
struct ast_json_iter * ast_json_object_iter(struct ast_json *object)
Get an iterator pointing to the first field in a JSON object.
Definition json.c:439
@ AST_JSON_ARRAY
Definition json.h:165
@ AST_JSON_OBJECT
Definition json.h:164
const char * ast_json_object_iter_key(struct ast_json_iter *iter)
Get the key from an iterator.
Definition json.c:451
size_t ast_json_array_size(const struct ast_json *array)
Get the size of a JSON array.
Definition json.c:366
Iterator for JSON object key/values.

References AST_JSON_ARRAY, ast_json_array_get(), ast_json_array_size(), AST_JSON_OBJECT, ast_json_object_iter(), ast_json_object_iter_key(), ast_json_object_iter_next(), ast_json_object_iter_value(), ast_json_typeof(), ast_str_create, manager_json_array_with_key(), manager_json_obj_with_key(), and manager_json_value_str_append().

Referenced by ast_manager_str_from_json_object(), manager_json_array_with_key(), and manager_json_obj_with_key().

◆ manager_json_value_str_append()

static void manager_json_value_str_append ( struct ast_json value,
const char *  key,
struct ast_str **  res 
)
static

Definition at line 451 of file manager.c.

453{
454 switch (ast_json_typeof(value)) {
455 case AST_JSON_STRING:
456 ast_str_append(res, 0, "%s: %s\r\n", key, ast_json_string_get(value));
457 break;
458 case AST_JSON_INTEGER:
459 ast_str_append(res, 0, "%s: %jd\r\n", key, ast_json_integer_get(value));
460 break;
461 case AST_JSON_TRUE:
462 ast_str_append(res, 0, "%s: True\r\n", key);
463 break;
464 case AST_JSON_FALSE:
465 ast_str_append(res, 0, "%s: False\r\n", key);
466 break;
467 default:
468 ast_str_append(res, 0, "%s: \r\n", key);
469 break;
470 }
471}
@ AST_JSON_STRING
Definition json.h:166
@ AST_JSON_FALSE
Definition json.h:170
@ AST_JSON_INTEGER
Definition json.h:167
@ AST_JSON_TRUE
Definition json.h:169

References AST_JSON_FALSE, AST_JSON_INTEGER, ast_json_integer_get(), AST_JSON_STRING, ast_json_string_get(), AST_JSON_TRUE, ast_json_typeof(), ast_str_append(), and value.

Referenced by manager_json_to_ast_str().

◆ manager_modulecheck()

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

Manager function to check if module is loaded.

Definition at line 6904 of file manager.c.

6905{
6906 const char *module = astman_get_header(m, "Module");
6907 const char *id = astman_get_header(m, "ActionID");
6908
6909 ast_debug(1, "**** ModuleCheck .so file %s\n", module);
6910 if (!ast_module_check(module)) {
6911 astman_send_error(s, m, "Module not loaded");
6912 return 0;
6913 }
6914
6915 astman_append(s, "Response: Success\r\n");
6916
6917 if (!ast_strlen_zero(id)) {
6918 astman_append(s, "ActionID: %s\r\n", id);
6919 }
6920
6921#if !defined(LOW_MEMORY)
6922 /* When we switched from subversion to git we lost the ability to
6923 * retrieve the 'ASTERISK_FILE_VERSION' from that file, but we retain
6924 * the response header here for backwards compatibility. */
6925 astman_append(s, "Version: \r\n");
6926#endif
6927
6928 astman_append(s, "\r\n");
6929
6930 return 0;
6931}
int ast_module_check(const char *name)
Check if module with the name given is loaded.
Definition loader.c:2832

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

Referenced by __init_manager().

◆ manager_moduleload()

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

Definition at line 6969 of file manager.c.

6970{
6971 int res;
6972 const char *module = astman_get_header(m, "Module");
6973 const char *loadtype = astman_get_header(m, "LoadType");
6974 const char *recursive = astman_get_header(m, "Recursive");
6975
6976 if (!loadtype || strlen(loadtype) == 0) {
6977 astman_send_error(s, m, "Incomplete ModuleLoad action.");
6978 }
6979 if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0) {
6980 astman_send_error(s, m, "Need module name");
6981 }
6982
6983 res = file_in_modules_dir(module);
6984 if (res == 0) {
6985 astman_send_error(s, m, "Module must be in the configured modules directory.");
6986 return 0;
6987 } else if (res == -1) {
6988 astman_send_error(s, m, "Module not found.");
6989 return 0;
6990 }
6991
6992 if (!strcasecmp(loadtype, "load")) {
6993 res = ast_load_resource(module);
6994 if (res) {
6995 astman_send_error(s, m, "Could not load module.");
6996 } else {
6997 astman_send_ack(s, m, "Module loaded.");
6998 }
6999 } else if (!strcasecmp(loadtype, "unload")) {
7000 res = ast_unload_resource(module, AST_FORCE_SOFT);
7001 if (res) {
7002 astman_send_error(s, m, "Could not unload module.");
7003 } else {
7004 astman_send_ack(s, m, "Module unloaded.");
7005 }
7006 } else if (!strcasecmp(loadtype, "refresh")) {
7007 res = ast_refresh_resource(module, AST_FORCE_SOFT, !ast_strlen_zero(recursive) && ast_true(recursive));
7008 if (res) {
7009 astman_send_error(s, m, "Could not refresh module.");
7010 } else {
7011 astman_send_ack(s, m, "Module unloaded and loaded.");
7012 }
7013 } else if (!strcasecmp(loadtype, "reload")) {
7014 /* TODO: Unify the ack/error messages here with action_reload */
7015 if (!ast_strlen_zero(module)) {
7016 enum ast_module_reload_result reload_res = ast_module_reload(module);
7017
7018 switch (reload_res) {
7020 astman_send_error(s, m, "No such module.");
7021 break;
7023 astman_send_error(s, m, "Module does not support reload action.");
7024 break;
7026 astman_send_error(s, m, "An unknown error occurred");
7027 break;
7029 astman_send_error(s, m, "A reload is in progress");
7030 break;
7032 astman_send_error(s, m, "Module not initialized");
7033 break;
7036 /* Treat a queued request as success */
7037 astman_send_ack(s, m, "Module reloaded.");
7038 break;
7039 }
7040 } else {
7041 ast_module_reload(NULL); /* Reload all modules */
7042 astman_send_ack(s, m, "All modules reloaded");
7043 }
7044 } else {
7045 astman_send_error(s, m, "Incomplete ModuleLoad action.");
7046 }
7047 return 0;
7048}
static int file_in_modules_dir(const char *filename)
Check if the given file path is in the modules dir or not.
Definition manager.c:6943
int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode)
Unload a module.
Definition loader.c:1457
enum ast_module_load_result ast_load_resource(const char *resource_name)
Load a module.
Definition loader.c:1987
int ast_refresh_resource(const char *resource_name, enum ast_module_unload_mode force, int recursive)
Unload and load a module again.
Definition loader.c:1416
@ AST_FORCE_SOFT
Definition module.h:62

References AST_FORCE_SOFT, ast_load_resource(), ast_module_reload(), AST_MODULE_RELOAD_ERROR, AST_MODULE_RELOAD_IN_PROGRESS, AST_MODULE_RELOAD_NOT_FOUND, AST_MODULE_RELOAD_NOT_IMPLEMENTED, AST_MODULE_RELOAD_QUEUED, AST_MODULE_RELOAD_SUCCESS, AST_MODULE_RELOAD_UNINITIALIZED, ast_refresh_resource(), ast_strlen_zero(), ast_true(), ast_unload_resource(), astman_get_header(), astman_send_ack(), astman_send_error(), file_in_modules_dir(), and NULL.

Referenced by __init_manager().

◆ manager_state_cb()

static int manager_state_cb ( const char *  context,
const char *  exten,
struct ast_state_cb_info info,
void *  data 
)
static

Definition at line 7812 of file manager.c.

7813{
7814 /* Notify managers of change */
7815 char hint[512];
7816
7817 hint[0] = '\0';
7818 ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten);
7819
7820 switch(info->reason) {
7822 manager_event(EVENT_FLAG_CALL, "ExtensionStatus",
7823 "Exten: %s\r\n"
7824 "Context: %s\r\n"
7825 "Hint: %s\r\n"
7826 "Status: %d\r\n"
7827 "StatusText: %s\r\n",
7828 exten,
7829 context,
7830 hint,
7831 info->exten_state,
7832 ast_extension_state2str(info->exten_state));
7833 break;
7835 manager_event(EVENT_FLAG_CALL, "PresenceStatus",
7836 "Exten: %s\r\n"
7837 "Context: %s\r\n"
7838 "Hint: %s\r\n"
7839 "Status: %s\r\n"
7840 "Subtype: %s\r\n"
7841 "Message: %s\r\n",
7842 exten,
7843 context,
7844 hint,
7845 ast_presence_state2str(info->presence_state),
7846 info->presence_subtype,
7847 info->presence_message);
7848 break;
7849 }
7850 return 0;
7851}
@ AST_HINT_UPDATE_DEVICE
Definition pbx.h:91
@ AST_HINT_UPDATE_PRESENCE
Definition pbx.h:93

References ast_extension_state2str(), ast_get_hint(), AST_HINT_UPDATE_DEVICE, AST_HINT_UPDATE_PRESENCE, ast_presence_state2str(), EVENT_FLAG_CALL, manager_event, and NULL.

Referenced by __init_manager().

◆ manager_subscription_change_msg_cb()

static void manager_subscription_change_msg_cb ( void *  userdata,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Callback for subscription change messages.

Parameters
userdataThe subscription user data (in our case a pointer to the sessions container)
subThe subscription
messageThe message

Definition at line 622 of file manager.c.

624{
625 /*
626 * When the subscription unsubscribes a final message is sent to the subscription
627 * to indicate it. We use this to manage the lifetime of the sessions container
628 * pointer stored with the subscription. When the subscription is done we drop
629 * the reference to the sessions container (userdata) so it can be cleaned up
630 * if needed.
631 */
633 ao2_cleanup(userdata);
634 }
635}
static struct stasis_subscription * sub
Statsd channel stats. Exmaple of how to subscribe to Stasis events.
int stasis_subscription_final_message(struct stasis_subscription *sub, struct stasis_message *msg)
Determine whether a message is the final message to be received on a subscription.
Definition stasis.c:1252

References ao2_cleanup, stasis_subscription_final_message(), and sub.

Referenced by manager_subscriptions_init().

◆ mansession_cmp_fn()

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

Definition at line 976 of file manager.c.

977{
978 struct mansession_session *s = obj;
979 char *str = arg;
980 return !strcasecmp(s->username, str) ? CMP_MATCH : 0;
981}

References CMP_MATCH, str, and mansession_session::username.

Referenced by __init_manager().

◆ mansession_get_transport()

static enum ast_transport mansession_get_transport ( const struct mansession s)
static

◆ mansession_lock()

static void mansession_lock ( struct mansession s)
static

Lock the 'mansession' structure.

Definition at line 2013 of file manager.c.

2014{
2015 ast_mutex_lock(&s->lock);
2016}
ast_mutex_t lock
Definition manager.c:321

References ast_mutex_lock, and mansession::lock.

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

◆ mansession_unlock()

static void mansession_unlock ( struct mansession s)
static

Unlock the 'mansession' structure.

Definition at line 2019 of file manager.c.

2020{
2022}

References ast_mutex_unlock, and mansession::lock.

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

◆ match_eventdata()

static int match_eventdata ( struct event_filter_entry entry,
const char *  eventdata 
)
static

Test eventdata against a filter entry.

Parameters
entryThe event_filter entry to match with
eventdataThe data to match against
Return values
0if no match
1if match

Definition at line 5623 of file manager.c.

5624{
5625 switch(entry->match_type) {
5626 case FILTER_MATCH_REGEX:
5627 return regexec(entry->regex_filter, eventdata, 0, NULL, 0) == 0;
5629 return ast_begins_with(eventdata, entry->string_filter);
5631 return ast_ends_with(eventdata, entry->string_filter);
5633 return strstr(eventdata, entry->string_filter) != NULL;
5634 case FILTER_MATCH_EXACT:
5635 return strcmp(eventdata, entry->string_filter) == 0;
5636 case FILTER_MATCH_NONE:
5637 return 1;
5638 }
5639
5640 return 0;
5641}
enum event_filter_match_type match_type
Definition manager.c:395

References ast_begins_with(), ast_ends_with(), FILTER_MATCH_CONTAINS, FILTER_MATCH_ENDS_WITH, FILTER_MATCH_EXACT, FILTER_MATCH_NONE, FILTER_MATCH_REGEX, FILTER_MATCH_STARTS_WITH, event_filter_entry::match_type, NULL, event_filter_entry::regex_filter, and event_filter_entry::string_filter.

Referenced by filter_cmp_fn().

◆ print_event_instance()

static void print_event_instance ( struct ast_cli_args a,
struct ast_xml_doc_item instance 
)
static

Definition at line 9358 of file manager.c.

9359{
9360 char *since, *syntax, *provided_by, *description, *synopsis, *seealso, *arguments;
9361
9362 synopsis = ast_xmldoc_printable(AS_OR(instance->synopsis, "Not available"), 1);
9363 provided_by = ast_xmldoc_printable(AS_OR(instance->provided_by, "Not available"), 1);
9364 since = ast_xmldoc_printable(AS_OR(instance->since, "Not available"), 1);
9365 description = ast_xmldoc_printable(AS_OR(instance->description, "Not available"), 1);
9366 syntax = ast_xmldoc_printable(AS_OR(instance->syntax, "Not available"), 1);
9367 arguments = ast_xmldoc_printable(AS_OR(instance->arguments, "Not available"), 1);
9368 seealso = ast_xmldoc_printable(AS_OR(instance->seealso, "Not available"), 1);
9369
9370 if (!synopsis || !provided_by || !since || !description || !syntax || !arguments || !seealso) {
9371 ast_cli(a->fd, "Error: Memory allocation failed\n");
9372 goto free_docs;
9373 }
9374
9375 ast_cli(a->fd, "\n"
9376 "%s -= Info about Manager Event '%s' =- %s\n\n"
9377 COLORIZE_FMT "\n"
9378 "%s\n\n"
9379 COLORIZE_FMT "\n"
9380 "%s\n\n"
9381 COLORIZE_FMT "\n"
9382 "%s\n\n"
9383 COLORIZE_FMT "\n"
9384 "%s\n\n"
9385 COLORIZE_FMT "\n"
9386 "%s\n\n"
9387 COLORIZE_FMT "\n"
9388 "%s\n\n"
9389 COLORIZE_FMT "\n"
9390 "%s\n\n",
9392 COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis,
9393 COLORIZE(COLOR_MAGENTA, 0, "[Provided By]"), provided_by,
9394 COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since,
9395 COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description,
9396 COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax,
9397 COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments,
9398 COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso
9399 );
9400
9401free_docs:
9403 ast_free(since);
9404 ast_free(description);
9405 ast_free(syntax);
9406 ast_free(arguments);
9407 ast_free(seealso);
9408}
#define AS_OR(a, b)
Definition strings.h:49
struct ast_str * synopsis
Definition xmldoc.h:64

References a, ast_xml_doc_item::arguments, AS_OR, ast_cli(), ast_free, ast_term_color(), ast_term_reset(), ast_xmldoc_printable(), COLOR_MAGENTA, COLORIZE, COLORIZE_FMT, ast_xml_doc_item::description, ast_xml_doc_item::name, ast_xml_doc_item::provided_by, ast_xml_doc_item::seealso, ast_xml_doc_item::since, synopsis, ast_xml_doc_item::synopsis, and ast_xml_doc_item::syntax.

Referenced by handle_manager_show_event(), and handle_showmancmd().

◆ process_events()

static int process_events ( struct mansession s)
static

Send any pending events to the client listening on this socket.

Parameters
sThe manager session to send events for.

Definition at line 6459 of file manager.c.

6460{
6461 int ret = 0;
6462 size_t events_count;
6463 struct eventqent **events;
6464 int i;
6465
6466 ao2_lock(s->session);
6467
6468 if (!s->session->stream) {
6469 ao2_unlock(s->session);
6470 return 0;
6471 }
6472
6473 /* To reduce contention we lock only long enough to steal the events */
6475 events_count = AST_VECTOR_SIZE(&s->session->pending_events);
6478
6479 for (i = 0; i < events_count; i++) {
6480 struct eventqent *eqe = events[i];
6481
6482 if (eqe->category == EVENT_FLAG_SHUTDOWN) {
6483 ast_debug(3, "Received CloseSession event\n");
6484 ret = -1;
6485 /* We purposely don't break here so that we drop the reference on remaining events */
6486 }
6487
6488 if (!ret && ((s->session->send_events & eqe->category) == eqe->category) &&
6490 (send_string(s, ast_str_buffer(eqe->message)) < 0 || s->write_error)) {
6491 ret = -1; /* don't send more */
6492 }
6493
6494 ao2_ref(eqe, -1);
6495 }
6496
6497 ao2_unlock(s->session);
6498
6500
6501 return ret;
6502}
unsigned int write_error
Definition manager.c:319

References ao2_lock, ao2_ref, ao2_unlock, ast_debug, ast_free, ast_mutex_lock, ast_mutex_unlock, ast_str_buffer(), AST_VECTOR_SIZE, AST_VECTOR_STEAL_ELEMENTS, eventqent::category, EVENT_FLAG_SHUTDOWN, events, mansession_session::excludefilters, mansession_session::includefilters, eventqent::message, mansession_session::pending_events, mansession_session::pending_events_lock, mansession_session::send_events, send_string(), mansession::session, should_send_event(), mansession_session::stream, and mansession::write_error.

Referenced by get_input(), and process_message().

◆ process_message()

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

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

Definition at line 7089 of file manager.c.

7090{
7091 int ret = 0;
7092 struct manager_action *act_found;
7093 struct ast_manager_user *user = NULL;
7094 const char *username;
7095 const char *action;
7096
7097 action = __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY);
7098 if (ast_strlen_zero(action)) {
7099 report_req_bad_format(s, "NONE");
7100 mansession_lock(s);
7101 astman_send_error(s, m, "Missing action in request");
7103 return 0;
7104 }
7105
7106 log_action(m, action);
7107
7108 if (ast_shutting_down()) {
7109 ast_log(LOG_ERROR, "Unable to process manager action '%s'. Asterisk is shutting down.\n", action);
7110 mansession_lock(s);
7111 astman_send_error(s, m, "Asterisk is shutting down");
7113 return 0;
7114 }
7115
7116 if (!s->session->authenticated
7117 && strcasecmp(action, "Login")
7118 && strcasecmp(action, "Logoff")
7119 && strcasecmp(action, "Challenge")) {
7120 if (!s->session->authenticated) {
7121 report_req_not_allowed(s, action);
7122 }
7123 mansession_lock(s);
7124 astman_send_error(s, m, "Permission denied");
7126 return 0;
7127 }
7128
7129 if (!s->session->authenticated
7130 && (!strcasecmp(action, "Login")
7131 || !strcasecmp(action, "Challenge"))) {
7132 username = astman_get_header(m, "Username");
7133
7137 if (user && !user->allowmultiplelogin) {
7140 sleep(1);
7141 mansession_lock(s);
7142 astman_send_error(s, m, "Login Already In Use");
7144 return -1;
7145 }
7147 }
7148 }
7149
7150 act_found = action_find(action);
7151 if (act_found) {
7152 /* Found the requested AMI action. */
7153 int acted = 0;
7154
7155 if ((s->session->writeperm & act_found->authority)
7156 || act_found->authority == 0) {
7157 /* We have the authority to execute the action. */
7158 ret = -1;
7159 ao2_lock(act_found);
7160 if (act_found->registered && act_found->func) {
7161 struct ast_module *mod_ref = ast_module_running_ref(act_found->module);
7162
7163 ao2_unlock(act_found);
7164 if (mod_ref || !act_found->module) {
7165 ast_debug(1, "Running action '%s'\n", act_found->action);
7166 ret = act_found->func(s, m);
7167 acted = 1;
7168 ast_module_unref(mod_ref);
7169 }
7170 } else {
7171 ao2_unlock(act_found);
7172 }
7173 }
7174 if (!acted) {
7175 /*
7176 * We did not execute the action because access was denied, it
7177 * was no longer registered, or no action was really registered.
7178 * Complain about it and leave.
7179 */
7180 report_req_not_allowed(s, action);
7181 mansession_lock(s);
7182 astman_send_error(s, m, "Permission denied");
7184 }
7185 ao2_t_ref(act_found, -1, "done with found action object");
7186 } else {
7187 char buf[512];
7188
7189 report_req_bad_format(s, action);
7190 snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action);
7191 mansession_lock(s);
7192 astman_send_error(s, m, buf);
7194 }
7195 if (ret) {
7196 return ret;
7197 }
7198 /* Once done with our message, deliver any pending events unless the
7199 requester doesn't want them as part of this response.
7200 */
7201 if (ast_strlen_zero(astman_get_header(m, "SuppressEvents"))) {
7202 return process_events(s);
7203 } else {
7204 return ret;
7205 }
7206}
int ast_shutting_down(void)
Definition asterisk.c:1889
static void log_action(const struct message *m, const char *action)
Definition manager.c:7050
static int check_manager_session_inuse(const char *name)
Definition manager.c:996
static void report_req_not_allowed(const struct mansession *s, const char *action)
Definition manager.c:2148
static void report_session_limit(const struct mansession *s)
Definition manager.c:2236
static void report_req_bad_format(const struct mansession *s, const char *action)
Definition manager.c:2177
char username[80]
Definition manager.c:334

References __astman_get_header(), manager_action::action, action_find(), ao2_lock, ao2_t_ref, ao2_unlock, ast_debug, ast_log, ast_module_running_ref, ast_module_unref, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_shutting_down(), ast_strlen_zero(), astman_get_header(), astman_send_error(), mansession_session::authenticated, manager_action::authority, buf, check_manager_session_inuse(), manager_action::func, GET_HEADER_SKIP_EMPTY, get_manager_by_name_locked(), log_action(), LOG_ERROR, mansession_lock(), mansession_unlock(), NULL, process_events(), manager_action::registered, report_req_bad_format(), report_req_not_allowed(), report_session_limit(), mansession::session, and mansession_session::writeperm.

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

◆ purge_sessions()

static int purge_sessions ( int  n_max)
static

remove at most n_max stale session from the list.

Definition at line 7518 of file manager.c.

7519{
7520 struct ao2_container *sessions;
7522 time_t now = time(NULL);
7523 struct ao2_iterator i;
7524 int purged = 0;
7525
7526 sessions = ao2_global_obj_ref(mgr_sessions);
7527 if (!sessions) {
7528 return 0;
7529 }
7531 ao2_ref(sessions, -1);
7532
7533 /* The order of operations is significant */
7534 while (n_max > 0 && (session = ao2_iterator_next(&i))) {
7536 if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) {
7537 if (session->authenticated
7538 && VERBOSITY_ATLEAST(2)
7540 ast_verb(2, "HTTP Manager '%s' timed out from %s\n",
7541 session->username, ast_sockaddr_stringify_addr(&session->addr));
7542 }
7545 n_max--;
7546 purged++;
7547 } else {
7550 }
7551 }
7553 return purged;
7554}
static void session_destroy(struct mansession_session *s)
Definition manager.c:983
#define VERBOSITY_ATLEAST(level)

References ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_sockaddr_stringify_addr(), ast_verb, manager_displayconnects(), NULL, session, session_destroy(), sessions, unref_mansession(), and VERBOSITY_ATLEAST.

Referenced by purge_old_stuff().

◆ queue_match()

static int queue_match ( const char *  app,
const char *  data,
const char *  search 
)
static

Definition at line 5096 of file manager.c.

5097{
5098 char *parse;
5100 AST_APP_ARG(queuename);
5103 AST_APP_ARG(announceoverride);
5104 AST_APP_ARG(queuetimeoutstr);
5105 AST_APP_ARG(agi);
5106 AST_APP_ARG(gosub);
5108 AST_APP_ARG(position);
5109 );
5110
5111 if (!strcasestr(app, "queue") || ast_strlen_zero(data)) {
5112 return 0;
5113 }
5114
5115 parse = ast_strdupa(data);
5117
5118 /*
5119 * The Queue application is fine unless the AGI parameter is set.
5120 * If it is, we need to check the user's permissions.
5121 */
5122 return !ast_strlen_zero(args.agi);
5123}
static char url[512]

References app, args, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), options, strcasestr(), and url.

◆ queue_read_action_payload()

static int queue_read_action_payload ( struct ast_channel chan,
const unsigned char *  payload,
size_t  payload_size,
enum ast_frame_read_action  action 
)
static

Queue a given read action containing a payload onto a channel.

This queues a READ_ACTION control frame that contains a given "payload", or data to be triggered and handled on the channel's read side. This ensures the "action" is handled by the channel's media reading thread.

Parameters
chanThe channel to queue the action on
payloadThe read action's payload
payload_sizeThe size of the given payload
actionThe type of read action to queue
Return values
-1on error
0on success

Definition at line 3884 of file manager.c.

3886{
3888 size_t obj_size;
3889 int res;
3890
3891 obj_size = payload_size + sizeof(*obj);
3892
3893 obj = ast_malloc(obj_size);
3894 if (!obj) {
3895 return -1;
3896 }
3897
3898 obj->action = action;
3900 memcpy(obj->payload, payload, payload_size);
3901
3902 res = ast_queue_control_data(chan, AST_CONTROL_READ_ACTION, obj, obj_size);
3903
3904 ast_free(obj);
3905 return res;
3906}
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
Definition channel.c:1296
@ AST_CONTROL_READ_ACTION

References ast_control_read_action_payload::action, AST_CONTROL_READ_ACTION, ast_free, ast_malloc, ast_queue_control_data(), ast_control_read_action_payload::payload, and ast_control_read_action_payload::payload_size.

Referenced by queue_sendtext(), and queue_sendtext_data().

◆ queue_sendtext()

static int queue_sendtext ( struct ast_channel chan,
const char *  body 
)
static

Queue a read action to send a text message.

Parameters
chanThe channel to queue the action on
bodyThe body of the message
Return values
-1on error
0on success

Definition at line 3917 of file manager.c.

3918{
3919 return queue_read_action_payload(chan, (const unsigned char *)body,
3920 strlen(body) + 1, AST_FRAME_READ_ACTION_SEND_TEXT);
3921}
static int queue_read_action_payload(struct ast_channel *chan, const unsigned char *payload, size_t payload_size, enum ast_frame_read_action action)
Queue a given read action containing a payload onto a channel.
Definition manager.c:3884
@ AST_FRAME_READ_ACTION_SEND_TEXT

References AST_FRAME_READ_ACTION_SEND_TEXT, and queue_read_action_payload().

Referenced by action_sendtext().

◆ queue_sendtext_data()

static int queue_sendtext_data ( struct ast_channel chan,
const char *  body,
const char *  content_type 
)
static

Queue a read action to send a text data message.

Parameters
chanThe channel to queue the action on
bodyThe body of the message
content_typeThe message's content type
Return values
-1on error
0on success

Definition at line 3933 of file manager.c.

3935{
3936 int res;
3937 struct ast_msg_data *obj;
3938
3940 NULL, NULL, content_type, body);
3941 if (!obj) {
3942 return -1;
3943 }
3944
3945 res = queue_read_action_payload(chan, (const unsigned char *)obj,
3947
3948 ast_free(obj);
3949 return res;
3950}
struct ast_msg_data * ast_msg_data_alloc2(enum ast_msg_data_source_type source_type, const char *to, const char *from, const char *content_type, const char *body)
Allocates an ast_msg_data structure.
size_t ast_msg_data_get_length(struct ast_msg_data *msg)
Get length of the structure.
@ AST_MSG_DATA_SOURCE_TYPE_UNKNOWN
Definition message.h:447
@ AST_FRAME_READ_ACTION_SEND_TEXT_DATA
Structure used to transport a message through the frame core.

References AST_FRAME_READ_ACTION_SEND_TEXT_DATA, ast_free, ast_msg_data_alloc2(), ast_msg_data_get_length(), AST_MSG_DATA_SOURCE_TYPE_UNKNOWN, NULL, and queue_read_action_payload().

Referenced by action_sendtext().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 10185 of file manager.c.

10186{
10188}
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
Definition module.h:102
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70

References __init_manager(), AST_MODULE_LOAD_FAILURE, and AST_MODULE_LOAD_SUCCESS.

Referenced by handle_manager_reload().

◆ report_auth_success()

static void report_auth_success ( const struct mansession s)
static

Definition at line 2123 of file manager.c.

2124{
2125 char session_id[32];
2126 struct ast_security_event_successful_auth successful_auth = {
2129 .common.service = "AMI",
2130 .common.account_id = s->session->username,
2131 .common.session_tv = &s->session->sessionstart_tv,
2132 .common.local_addr = {
2133 .addr = &s->tcptls_session->parent->local_address,
2134 .transport = mansession_get_transport(s),
2135 },
2136 .common.remote_addr = {
2137 .addr = &s->session->addr,
2138 .transport = mansession_get_transport(s),
2139 },
2140 .common.session_id = session_id,
2141 };
2142
2143 snprintf(session_id, sizeof(session_id), "%p", s->session);
2144
2145 ast_security_event_report(AST_SEC_EVT(&successful_auth));
2146}
static enum ast_transport mansession_get_transport(const struct mansession *s)
Definition manager.c:2042
int ast_security_event_report(const struct ast_security_event_common *sec)
Report a security event.
@ AST_SECURITY_EVENT_SUCCESSFUL_AUTH
FYI FWIW, Successful authentication has occurred.
#define AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION
Event descriptor version.
#define AST_SEC_EVT(e)
enum ast_security_event_type event_type
The security event sub-type.
struct ast_security_event_common common
Common security event descriptor elements.
struct ast_sockaddr local_address
Definition tcptls.h:131

References mansession_session::addr, AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_SUCCESSFUL_AUTH, AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION, ast_security_event_successful_auth::common, ast_security_event_common::event_type, ast_tcptls_session_args::local_address, mansession_get_transport(), ast_tcptls_session_instance::parent, mansession::session, mansession_session::sessionstart_tv, mansession::tcptls_session, and mansession_session::username.

Referenced by authenticate().

◆ report_failed_acl()

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

Definition at line 2073 of file manager.c.

2074{
2075 char session_id[32];
2076 struct ast_security_event_failed_acl failed_acl_event = {
2078 .common.version = AST_SECURITY_EVENT_FAILED_ACL_VERSION,
2079 .common.service = "AMI",
2080 .common.account_id = username,
2081 .common.session_tv = &s->session->sessionstart_tv,
2082 .common.local_addr = {
2083 .addr = &s->tcptls_session->parent->local_address,
2084 .transport = mansession_get_transport(s),
2085 },
2086 .common.remote_addr = {
2087 .addr = &s->session->addr,
2088 .transport = mansession_get_transport(s),
2089 },
2090 .common.session_id = session_id,
2091 };
2092
2093 snprintf(session_id, sizeof(session_id), "%p", s->session);
2094
2095 ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
2096}
#define AST_SECURITY_EVENT_FAILED_ACL_VERSION
Event descriptor version.
@ AST_SECURITY_EVENT_FAILED_ACL
Failed ACL.
Checking against an IP access control list failed.
struct ast_security_event_common common
Common security event descriptor elements.

References mansession_session::addr, AST_SEC_EVT, AST_SECURITY_EVENT_FAILED_ACL, AST_SECURITY_EVENT_FAILED_ACL_VERSION, ast_security_event_report(), ast_security_event_failed_acl::common, ast_security_event_common::event_type, ast_tcptls_session_args::local_address, mansession_get_transport(), ast_tcptls_session_instance::parent, mansession::session, mansession_session::sessionstart_tv, and mansession::tcptls_session.

Referenced by authenticate().

◆ report_failed_challenge_response()

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

Definition at line 2206 of file manager.c.

2208{
2209 char session_id[32];
2210 struct ast_security_event_chal_resp_failed chal_resp_failed = {
2213 .common.service = "AMI",
2214 .common.account_id = s->session->username,
2215 .common.session_tv = &s->session->sessionstart_tv,
2216 .common.local_addr = {
2217 .addr = &s->tcptls_session->parent->local_address,
2218 .transport = mansession_get_transport(s),
2219 },
2220 .common.remote_addr = {
2221 .addr = &s->session->addr,
2222 .transport = mansession_get_transport(s),
2223 },
2224 .common.session_id = session_id,
2225
2226 .challenge = s->session->challenge,
2227 .response = response,
2228 .expected_response = expected_response,
2229 };
2230
2231 snprintf(session_id, sizeof(session_id), "%p", s->session);
2232
2233 ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
2234}
#define AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION
Event descriptor version.
@ AST_SECURITY_EVENT_CHAL_RESP_FAILED
An attempt at challenge/response authentication failed.
An attempt at challenge/response auth failed.
const char * response
Response received.
struct ast_security_event_common common
Common security event descriptor elements.
const char * expected_response
Response expected to be received.

References mansession_session::addr, AST_SEC_EVT, AST_SECURITY_EVENT_CHAL_RESP_FAILED, AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION, ast_security_event_report(), mansession_session::challenge, ast_security_event_chal_resp_failed::common, ast_security_event_common::event_type, ast_security_event_chal_resp_failed::expected_response, ast_tcptls_session_args::local_address, mansession_get_transport(), ast_tcptls_session_instance::parent, ast_security_event_chal_resp_failed::response, mansession::session, mansession_session::sessionstart_tv, mansession::tcptls_session, and mansession_session::username.

Referenced by authenticate().

◆ report_inval_password()

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

Definition at line 2098 of file manager.c.

2099{
2100 char session_id[32];
2101 struct ast_security_event_inval_password inval_password = {
2104 .common.service = "AMI",
2105 .common.account_id = username,
2106 .common.session_tv = &s->session->sessionstart_tv,
2107 .common.local_addr = {
2108 .addr = &s->tcptls_session->parent->local_address,
2109 .transport = mansession_get_transport(s),
2110 },
2111 .common.remote_addr = {
2112 .addr = &s->session->addr,
2113 .transport = mansession_get_transport(s),
2114 },
2115 .common.session_id = session_id,
2116 };
2117
2118 snprintf(session_id, sizeof(session_id), "%p", s->session);
2119
2120 ast_security_event_report(AST_SEC_EVT(&inval_password));
2121}
#define AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION
Event descriptor version.
@ AST_SECURITY_EVENT_INVAL_PASSWORD
An attempt at basic password authentication failed.
An attempt at basic password auth failed.
struct ast_security_event_common common
Common security event descriptor elements.

References mansession_session::addr, AST_SEC_EVT, AST_SECURITY_EVENT_INVAL_PASSWORD, AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION, ast_security_event_report(), ast_security_event_inval_password::common, ast_security_event_common::event_type, ast_tcptls_session_args::local_address, mansession_get_transport(), ast_tcptls_session_instance::parent, mansession::session, mansession_session::sessionstart_tv, and mansession::tcptls_session.

Referenced by authenticate().

◆ report_invalid_user()

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

Definition at line 2048 of file manager.c.

2049{
2050 char session_id[32];
2051 struct ast_security_event_inval_acct_id inval_acct_id = {
2054 .common.service = "AMI",
2055 .common.account_id = username,
2056 .common.session_tv = &s->session->sessionstart_tv,
2057 .common.local_addr = {
2058 .addr = &s->tcptls_session->parent->local_address,
2059 .transport = mansession_get_transport(s),
2060 },
2061 .common.remote_addr = {
2062 .addr = &s->session->addr,
2063 .transport = mansession_get_transport(s),
2064 },
2065 .common.session_id = session_id,
2066 };
2067
2068 snprintf(session_id, sizeof(session_id), "%p", s);
2069
2070 ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
2071}
#define AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION
Event descriptor version.
@ AST_SECURITY_EVENT_INVAL_ACCT_ID
Invalid Account ID.
Invalid account ID specified (invalid username, for example)
struct ast_security_event_common common
Common security event descriptor elements.

References mansession_session::addr, AST_SEC_EVT, AST_SECURITY_EVENT_INVAL_ACCT_ID, AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION, ast_security_event_report(), ast_security_event_inval_acct_id::common, ast_security_event_common::event_type, ast_tcptls_session_args::local_address, mansession_get_transport(), ast_tcptls_session_instance::parent, mansession::session, mansession_session::sessionstart_tv, and mansession::tcptls_session.

Referenced by authenticate().

◆ report_req_bad_format()

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

Definition at line 2177 of file manager.c.

2178{
2179 char session_id[32];
2180 char request_type[64];
2181 struct ast_security_event_req_bad_format req_bad_format = {
2184 .common.service = "AMI",
2185 .common.account_id = s->session->username,
2186 .common.session_tv = &s->session->sessionstart_tv,
2187 .common.local_addr = {
2188 .addr = &s->tcptls_session->parent->local_address,
2189 .transport = mansession_get_transport(s),
2190 },
2191 .common.remote_addr = {
2192 .addr = &s->session->addr,
2193 .transport = mansession_get_transport(s),
2194 },
2195 .common.session_id = session_id,
2196
2197 .request_type = request_type,
2198 };
2199
2200 snprintf(session_id, sizeof(session_id), "%p", s->session);
2201 snprintf(request_type, sizeof(request_type), "Action: %s", action);
2202
2203 ast_security_event_report(AST_SEC_EVT(&req_bad_format));
2204}
#define AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION
Event descriptor version.
@ AST_SECURITY_EVENT_REQ_BAD_FORMAT
Request received with bad formatting.
Invalid formatting of request.
struct ast_security_event_common common
Common security event descriptor elements.
const char * request_type
Request type that was made.

References mansession_session::addr, AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_REQ_BAD_FORMAT, AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION, ast_security_event_req_bad_format::common, ast_security_event_common::event_type, ast_tcptls_session_args::local_address, mansession_get_transport(), ast_tcptls_session_instance::parent, ast_security_event_req_not_allowed::request_type, ast_security_event_req_bad_format::request_type, mansession::session, mansession_session::sessionstart_tv, mansession::tcptls_session, and mansession_session::username.

Referenced by process_message().

◆ report_req_not_allowed()

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

Definition at line 2148 of file manager.c.

2149{
2150 char session_id[32];
2151 char request_type[64];
2152 struct ast_security_event_req_not_allowed req_not_allowed = {
2155 .common.service = "AMI",
2156 .common.account_id = s->session->username,
2157 .common.session_tv = &s->session->sessionstart_tv,
2158 .common.local_addr = {
2159 .addr = &s->tcptls_session->parent->local_address,
2160 .transport = mansession_get_transport(s),
2161 },
2162 .common.remote_addr = {
2163 .addr = &s->session->addr,
2164 .transport = mansession_get_transport(s),
2165 },
2166 .common.session_id = session_id,
2167
2168 .request_type = request_type,
2169 };
2170
2171 snprintf(session_id, sizeof(session_id), "%p", s->session);
2172 snprintf(request_type, sizeof(request_type), "Action: %s", action);
2173
2174 ast_security_event_report(AST_SEC_EVT(&req_not_allowed));
2175}
#define AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION
Event descriptor version.
@ AST_SECURITY_EVENT_REQ_NOT_ALLOWED
A request was made that is not allowed.
Request denied because it's not allowed.
struct ast_security_event_common common
Common security event descriptor elements.
const char * request_type
Request type that was made.

References mansession_session::addr, AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_REQ_NOT_ALLOWED, AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION, ast_security_event_req_not_allowed::common, ast_security_event_common::event_type, ast_tcptls_session_args::local_address, mansession_get_transport(), ast_tcptls_session_instance::parent, ast_security_event_req_not_allowed::request_type, mansession::session, mansession_session::sessionstart_tv, mansession::tcptls_session, and mansession_session::username.

Referenced by process_message().

◆ report_session_limit()

static void report_session_limit ( const struct mansession s)
static

Definition at line 2236 of file manager.c.

2237{
2238 char session_id[32];
2242 .common.service = "AMI",
2243 .common.account_id = s->session->username,
2244 .common.session_tv = &s->session->sessionstart_tv,
2245 .common.local_addr = {
2246 .addr = &s->tcptls_session->parent->local_address,
2247 .transport = mansession_get_transport(s),
2248 },
2249 .common.remote_addr = {
2250 .addr = &s->session->addr,
2251 .transport = mansession_get_transport(s),
2252 },
2253 .common.session_id = session_id,
2254 };
2255
2256 snprintf(session_id, sizeof(session_id), "%p", s->session);
2257
2259}
static int session_limit
Definition http.c:107
#define AST_SECURITY_EVENT_SESSION_LIMIT_VERSION
Event descriptor version.
@ AST_SECURITY_EVENT_SESSION_LIMIT
Session limit reached.
Request denied because of a session limit.
struct ast_security_event_common common
Common security event descriptor elements.

References mansession_session::addr, AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_SESSION_LIMIT, AST_SECURITY_EVENT_SESSION_LIMIT_VERSION, ast_security_event_session_limit::common, ast_security_event_common::event_type, ast_tcptls_session_args::local_address, mansession_get_transport(), ast_tcptls_session_instance::parent, mansession::session, session_limit, mansession_session::sessionstart_tv, mansession::tcptls_session, and mansession_session::username.

Referenced by process_message().

◆ send_string()

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

1788{
1789 struct ast_iostream *stream;
1790 int len, res;
1791
1792 /* It's a result from one of the hook's action invocation */
1793 if (s->hook) {
1794 /*
1795 * to send responses, we're using the same function
1796 * as for receiving events. We call the event "HookResponse"
1797 */
1798 s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string);
1799 return 0;
1800 }
1801
1802 stream = s->stream ? s->stream : s->session->stream;
1803
1804 len = strlen(string);
1806 res = ast_iostream_write(stream, string, len);
1808
1809 if (res < len) {
1810 s->write_error = 1;
1811 }
1812
1813 return res;
1814}
void ast_iostream_set_timeout_inactivity(struct ast_iostream *stream, int timeout)
Set the iostream inactivity timeout timer.
Definition iostream.c:127
ssize_t ast_iostream_write(struct ast_iostream *stream, const void *buffer, size_t count)
Write data to an iostream.
Definition iostream.c:390
void ast_iostream_set_timeout_disable(struct ast_iostream *stream)
Disable the iostream timeout timer.
Definition iostream.c:119
#define EVENT_FLAG_HOOKRESPONSE
Definition manager.h:89
struct timeval start
Definition iostream.c:41
struct ast_iostream * stream
Definition manager.c:316

References ast_iostream_set_timeout_disable(), ast_iostream_set_timeout_inactivity(), ast_iostream_write(), EVENT_FLAG_HOOKRESPONSE, manager_custom_hook::helper, mansession::hook, len(), mansession::session, ast_iostream::start, mansession_session::stream, mansession::stream, mansession::write_error, and mansession_session::writetimeout.

Referenced by astman_append(), astman_flush(), and process_events().

◆ session_destroy()

static void session_destroy ( struct mansession_session s)
static

Definition at line 983 of file manager.c.

984{
985 struct ao2_container *sessions;
986
987 sessions = ao2_global_obj_ref(mgr_sessions);
988 if (sessions) {
990 ao2_ref(sessions, -1);
991 }
993}
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition astobj2.h:1578

References ao2_global_obj_ref, ao2_ref, ao2_unlink, sessions, and unref_mansession().

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

◆ session_destructor()

static void session_destructor ( void *  obj)
static

Definition at line 901 of file manager.c.

902{
903 struct mansession_session *session = obj;
904 struct ast_datastore *datastore;
905
906 /* Get rid of each of the data stores on the session */
907 while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) {
908 /* Free the data store */
909 ast_datastore_free(datastore);
910 }
911
912 if (session->chanvars) {
914 }
915
916 if (session->includefilters) {
917 ao2_t_ref(session->includefilters, -1, "decrement ref for include container, should be last one");
918 }
919
920 if (session->excludefilters) {
921 ao2_t_ref(session->excludefilters, -1, "decrement ref for exclude container, should be last one");
922 }
923
925 AST_VECTOR_FREE(&session->pending_events);
926 ast_mutex_destroy(&session->http_thread_lock);
927 ast_mutex_destroy(&session->pending_events_lock);
928
929 /* On initialization the alert pipe is set to -1, ensuring it is safe to call close */
930 ast_alertpipe_close(session->alert_pipe);
931}
void ast_alertpipe_close(int alert_pipe[2])
Close an alert pipe.
Definition alertpipe.c:79
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition datastore.c:68
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define ast_mutex_destroy(a)
Definition lock.h:195
Structure for a data store object.
Definition datastore.h:64
struct ast_datastore::@224 entry
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition vector.h:185
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition vector.h:890

References ao2_cleanup, ao2_t_ref, ast_alertpipe_close(), ast_datastore_free(), AST_LIST_REMOVE_HEAD, ast_mutex_destroy, ast_variables_destroy(), AST_VECTOR_CALLBACK_VOID, AST_VECTOR_FREE, ast_datastore::entry, and session.

Referenced by build_mansession().

◆ session_do()

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

7431{
7432 struct ast_tcptls_session_instance *ser = data;
7434 struct mansession s = {
7435 .tcptls_session = data,
7436 };
7437 int res;
7438 int arg = 1;
7439
7440 /* If this session would exceed the auth limit, reject it immediately */
7443 goto done;
7444 }
7445
7447 if (!session) {
7449 goto done;
7450 }
7451
7452 /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
7453 * This is necessary to prevent delays (caused by buffering) as we
7454 * write to the socket in bits and pieces. */
7455 if (setsockopt(ast_iostream_get_fd(ser->stream), IPPROTO_TCP, TCP_NODELAY, (char *) &arg, sizeof(arg)) < 0) {
7456 ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on manager connection: %s\n", strerror(errno));
7457 }
7459
7461
7462 ast_mutex_init(&s.lock);
7463
7464 /* these fields duplicate those in the 'ser' structure */
7465 session->stream = s.stream = ser->stream;
7467 s.session = session;
7468
7469 if(time(&session->authstart) == -1) {
7470 ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
7474 goto done;
7475 }
7477
7478 /*
7479 * We cannot let the stream exclusively wait for data to arrive.
7480 * We have to wake up the task to send async events.
7481 */
7483
7485 ast_tvnow(), authtimeout * 1000);
7486
7487 astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */
7488 for (;;) {
7489 if ((res = do_message(&s)) < 0 || s.write_error || session->kicked) {
7490 break;
7491 }
7492 if (session->authenticated) {
7494 }
7495 }
7496 /* session is over, explain why and terminate */
7497 if (session->authenticated) {
7499 ast_verb(2, "Manager '%s' %s from %s\n", session->username, session->kicked ? "kicked" : "logged off", ast_sockaddr_stringify_addr(&session->addr));
7500 }
7501 } else {
7503 if (displayconnects) {
7504 ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_sockaddr_stringify_addr(&session->addr));
7505 }
7506 }
7507
7509
7511done:
7512 ao2_ref(ser, -1);
7513 ser = NULL;
7514 return NULL;
7515}
static int do_message(struct mansession *s)
Definition manager.c:7342
static int authlimit
Definition manager.c:159
static struct mansession_session * build_mansession(const struct ast_sockaddr *addr, unsigned int needs_alert_pipe)
Allocate manager session structure and add it to the list of sessions.
Definition manager.c:934
void ast_iostream_set_exclusive_input(struct ast_iostream *stream, int exclusive_input)
Set the iostream if it can exclusively depend upon the set timeouts.
Definition iostream.c:154
void ast_iostream_set_timeout_sequence(struct ast_iostream *stream, struct timeval start, int timeout)
Set the iostream I/O sequence timeout timer.
Definition iostream.c:145
void ast_iostream_nonblock(struct ast_iostream *stream)
Make an iostream non-blocking.
Definition iostream.c:104
describes a server instance
Definition tcptls.h:151
struct ast_sockaddr remote_address
Definition tcptls.h:153

References AMI_VERSION, ao2_lock, ao2_ref, ao2_unlock, ast_atomic_fetchadd_int(), ast_iostream_get_fd(), ast_iostream_nonblock(), ast_iostream_set_exclusive_input(), ast_iostream_set_timeout_disable(), ast_iostream_set_timeout_sequence(), ast_log, ast_mutex_destroy, ast_mutex_init, ast_sockaddr_copy(), ast_sockaddr_stringify_addr(), ast_tvnow(), ast_verb, astman_append(), authlimit, authtimeout, build_mansession(), displayconnects, do_message(), done, errno, mansession::lock, LOG_ERROR, LOG_WARNING, manager_displayconnects(), NULL, ast_tcptls_session_instance::remote_address, mansession::session, session, session_destroy(), ast_tcptls_session_instance::stream, mansession::stream, mansession::tcptls_session, unauth_sessions, and mansession::write_error.

◆ session_notify()

static void session_notify ( struct mansession_session session)
static

Definition at line 886 of file manager.c.

887{
888 if (!session->managerid) {
889 /* TCP based connections are easy and use an alert pipe, which requires no locking */
890 ast_alertpipe_write(session->alert_pipe);
891 } else {
892 /* HTTP based connections require locking as multiple HTTP connections can end up using the same session */
893 ast_mutex_lock(&session->http_thread_lock);
894 if (session->http_thread != AST_PTHREADT_NULL) {
895 pthread_kill(session->http_thread, SIGURG);
896 }
897 ast_mutex_unlock(&session->http_thread_lock);
898 }
899}
ssize_t ast_alertpipe_write(int alert_pipe[2])
Write an event to an alert pipe.
Definition alertpipe.c:120

References ast_alertpipe_write(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, and session.

Referenced by __manager_event_sessions_va(), and handle_kickmanconn().

◆ set_eventmask()

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

2029{
2030 int maskint = strings_to_mask(eventmask);
2031
2032 ao2_lock(s->session);
2033 /* Limit what event categories are sent to the client based on read permissions */
2034 if (maskint >= 0) {
2035 s->session->send_events = s->session->readperm & maskint;
2036 }
2037 ao2_unlock(s->session);
2038
2039 return maskint;
2040}
static int strings_to_mask(const char *string)
Definition manager.c:834

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

Referenced by action_events(), and authenticate().

◆ should_send_event()

static int should_send_event ( struct ao2_container includefilters,
struct ao2_container excludefilters,
struct eventqent eqe 
)
static

Definition at line 5696 of file manager.c.

5698{
5699 int result = 0;
5700
5701 if (manager_debug) {
5702 ast_verbose("<-- Examining AMI event (%u): -->\n%s\n", eqe->event_name_hash, ast_str_buffer(eqe->message));
5703 } else {
5704 ast_debug(4, "Examining AMI event (%u):\n%s\n", eqe->event_name_hash, ast_str_buffer(eqe->message));
5705 }
5706 if (!ao2_container_count(includefilters) && !ao2_container_count(excludefilters)) {
5707 return 1; /* no filtering means match all */
5708 } else if (ao2_container_count(includefilters) && !ao2_container_count(excludefilters)) {
5709 /* include filters only: implied exclude all filter processed first, then include filters */
5710 ao2_t_callback_data(includefilters, OBJ_NODATA, filter_cmp_fn, eqe, &result, "find filter in includefilters container");
5711 return result;
5712 } else if (!ao2_container_count(includefilters) && ao2_container_count(excludefilters)) {
5713 /* exclude filters only: implied include all filter processed first, then exclude filters */
5714 ao2_t_callback_data(excludefilters, OBJ_NODATA, filter_cmp_fn, eqe, &result, "find filter in excludefilters container");
5715 return !result;
5716 } else {
5717 /* include and exclude filters: implied exclude all filter processed first, then include filters, and lastly exclude filters */
5718 ao2_t_callback_data(includefilters, OBJ_NODATA, filter_cmp_fn, eqe, &result, "find filter in session filter container");
5719 if (result) {
5720 result = 0;
5721 ao2_t_callback_data(excludefilters, OBJ_NODATA, filter_cmp_fn, eqe, &result, "find filter in session filter container");
5722 return !result;
5723 }
5724 }
5725
5726 return result;
5727}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_t_callback_data(container, flags, cb_fn, arg, data, tag)
ao2_callback_data() is a generic function that applies cb_fn() to all objects in a container....
Definition astobj2.h:1721
@ OBJ_NODATA
Definition astobj2.h:1044
static int filter_cmp_fn(void *obj, void *arg, void *data, int flags)
Definition manager.c:5643

References ao2_container_count(), ao2_t_callback_data, ast_debug, ast_str_buffer(), ast_verbose, eventqent::event_name_hash, filter_cmp_fn(), manager_debug, eventqent::message, OBJ_NODATA, and result.

Referenced by action_waitevent_http(), action_waitevent_tcp(), and process_events().

◆ STASIS_MESSAGE_TYPE_DEFN()

STASIS_MESSAGE_TYPE_DEFN ( ast_manager_get_generic_type  )

Define AMI message types.

◆ strings_to_mask()

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

835{
836 const char *p;
837
838 if (ast_strlen_zero(string)) {
839 return -1;
840 }
841
842 for (p = string; *p; p++) {
843 if (*p < '0' || *p > '9') {
844 break;
845 }
846 }
847 if (!*p) { /* all digits */
848 return atoi(string);
849 }
850 if (ast_false(string)) {
851 return 0;
852 }
853 if (ast_true(string)) { /* all permissions */
854 int x, ret = 0;
855 for (x = 0; x < ARRAY_LEN(perms); x++) {
856 ret |= perms[x].num;
857 }
858 return ret;
859 }
860 return get_perm(string);
861}
static int get_perm(const char *instr)
Definition manager.c:813

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

Referenced by set_eventmask().

◆ unref_mansession()

static struct mansession_session * unref_mansession ( struct mansession_session s)
static

Unreference manager session object. If no more references, then go ahead and delete it.

Definition at line 865 of file manager.c.

866{
867 int refcount = ao2_ref(s, -1);
868 if (manager_debug) {
869 ast_debug(1, "Mansession: %p refcount now %d\n", s, refcount - 1);
870 }
871 return NULL;
872}

References ao2_ref, ast_debug, manager_debug, and NULL.

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

◆ user_authority_to_str()

static const char * user_authority_to_str ( int  authority,
struct ast_str **  res 
)
static

Convert authority code to a list of options for a user. This will only display those authority codes that have an explicit match on authority.

Definition at line 742 of file manager.c.

743{
744 int i;
745 char *sep = "";
746
747 ast_str_reset(*res);
748 for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
749 if ((authority & perms[i].num) == perms[i].num) {
750 ast_str_append(res, 0, "%s%s", sep, perms[i].label);
751 sep = ",";
752 }
753 }
754
755 if (ast_str_strlen(*res) == 0) {
756 /* replace empty string with something sensible */
757 ast_str_append(res, 0, "<none>");
758 }
759
760 return ast_str_buffer(*res);
761}

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

Referenced by handle_showmanager().

Variable Documentation

◆ acl_change_sub

struct stasis_subscription* acl_change_sub
static

Definition at line 167 of file manager.c.

Referenced by acl_change_stasis_subscribe(), and acl_change_stasis_unsubscribe().

◆ actions

◆ allowmultiplelogin

int allowmultiplelogin = 1
static

Definition at line 150 of file manager.c.

Referenced by __init_manager(), and handle_manager_show_settings().

◆ authlimit

int authlimit
static

Definition at line 159 of file manager.c.

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

◆ authtimeout

int authtimeout
static

Definition at line 158 of file manager.c.

Referenced by __init_manager(), do_message(), get_input(), manager_set_defaults(), and session_do().

◆ broken_events_action

int broken_events_action = 0
static

Definition at line 153 of file manager.c.

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

◆ [struct]

const struct { ... } command_blacklist[]
Initial value:
= {
{{ "module", "load", NULL }},
{{ "module", "unload", NULL }},
{{ "restart", "gracefully", NULL }},
}

Referenced by check_blacklist().

◆ displayconnects

int displayconnects = 1
static

◆ global_realm

char global_realm[MAXHOSTNAMELEN]
static

Default realm

Definition at line 164 of file manager.c.

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

◆ httptimeout

int httptimeout = 60
static

◆ live_dangerously

int live_dangerously
static

Set to true (non-zero) to globally allow all dangerous AMI actions to run.

Definition at line 184 of file manager.c.

Referenced by action_createconfig(), astman_live_dangerously(), file_in_modules_dir(), is_restricted_file(), and load_asterisk_conf().

◆ manager_channelvars

char* manager_channelvars
static

Definition at line 160 of file manager.c.

Referenced by handle_manager_show_settings(), load_channelvars(), and manager_shutdown().

◆ manager_debug

int manager_debug = 0
static

◆ manager_disabledevents

char* manager_disabledevents
static

◆ manager_enabled

int manager_enabled = 0
static

◆ manager_hooks

◆ manager_topic

struct stasis_topic* manager_topic
static

◆ match_type_names

char* match_type_names[]
static

Definition at line 385 of file manager.c.

385 {
386 [FILTER_MATCH_REGEX] = "regex",
387 [FILTER_MATCH_EXACT] = "exact",
388 [FILTER_MATCH_STARTS_WITH] = "starts_with",
389 [FILTER_MATCH_ENDS_WITH] = "ends_with",
390 [FILTER_MATCH_CONTAINS] = "contains",
391 [FILTER_MATCH_NONE] = "none",
392};

Referenced by manager_add_filter().

◆ originate_app_permissions

struct originate_permissions_entry originate_app_permissions[]
static

Definition at line 5133 of file manager.c.

5133 {
5134 /*
5135 * The app_match function checks if the search string is
5136 * anywhere in the app parameter. The check is case-insensitive.
5137 */
5138 { "agi", EVENT_FLAG_SYSTEM, app_match },
5139 { "dbdeltree", EVENT_FLAG_SYSTEM, app_match },
5140 { "exec", EVENT_FLAG_SYSTEM, app_match },
5141 { "externalivr", EVENT_FLAG_SYSTEM, app_match },
5142 { "mixmonitor", EVENT_FLAG_SYSTEM, app_match },
5143 { "originate", EVENT_FLAG_SYSTEM, app_match },
5144 { "reload", EVENT_FLAG_SYSTEM, app_match },
5145 { "system", EVENT_FLAG_SYSTEM, app_match },
5146 /*
5147 * Since the queue_match function specifically checks
5148 * for the presence of the AGI parameter, we'll allow
5149 * the call if the user has either the AGI or SYSTEM
5150 * permission.
5151 */
5153 /*
5154 * The appdata_match function checks if the search string is
5155 * anywhere in the appdata parameter. Unlike app_match,
5156 * the check is case-sensitive. These are generally
5157 * dialplan functions.
5158 */
5159 { "CURL", EVENT_FLAG_SYSTEM, appdata_match },
5161 { "EVAL", EVENT_FLAG_SYSTEM, appdata_match },
5162 { "FILE", EVENT_FLAG_SYSTEM, appdata_match },
5163 { "ODBC", EVENT_FLAG_SYSTEM, appdata_match },
5164 { "REALTIME", EVENT_FLAG_SYSTEM, appdata_match },
5165 { "SHELL", EVENT_FLAG_SYSTEM, appdata_match },
5166 { NULL, 0 },
5167};
static int app_match(const char *app, const char *data, const char *search)
Definition manager.c:5057
static int queue_match(const char *app, const char *data, const char *search)
Definition manager.c:5096
static int appdata_match(const char *app, const char *data, const char *search)
Definition manager.c:5076
#define EVENT_FLAG_AGI
Definition manager.h:88

Referenced by is_originate_app_permitted().

◆ perms

const struct permalias perms[]
static

◆ rtp_topic_forwarder

struct stasis_forward* rtp_topic_forwarder
static

The stasis_subscription for forwarding the RTP topic to the AMI topic.

Definition at line 176 of file manager.c.

Referenced by manager_shutdown(), and manager_subscriptions_init().

◆ security_topic_forwarder

struct stasis_forward* security_topic_forwarder
static

The stasis_subscription for forwarding the Security topic to the AMI topic.

Definition at line 179 of file manager.c.

Referenced by manager_shutdown(), and manager_subscriptions_init().

◆ stasis_router

struct stasis_message_router* stasis_router
static

◆ subscribed

int subscribed = 0
static

◆ timestampevents

int timestampevents
static

◆ unauth_sessions

int unauth_sessions = 0
static

Definition at line 166 of file manager.c.

Referenced by action_login(), and session_do().

◆ users

◆ webmanager_enabled

int webmanager_enabled = 0
static

◆ words

const char* words[AST_MAX_CMD_LEN]

Definition at line 210 of file manager.c.