Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Macros | Enumerations | Functions | Variables
manager.c File Reference

The Asterisk Management Interface - AMI. More...

#include "asterisk.h"
#include "asterisk/paths.h"
#include <ctype.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <regex.h>
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/manager.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/callerid.h"
#include "asterisk/core_local.h"
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/mwi.h"
#include "asterisk/pbx.h"
#include "asterisk/md5.h"
#include "asterisk/acl.h"
#include "asterisk/utils.h"
#include "asterisk/tcptls.h"
#include "asterisk/http.h"
#include "asterisk/ast_version.h"
#include "asterisk/threadstorage.h"
#include "asterisk/linkedlists.h"
#include "asterisk/term.h"
#include "asterisk/astobj2.h"
#include "asterisk/features.h"
#include "asterisk/security_events.h"
#include "asterisk/aoc.h"
#include "asterisk/strings.h"
#include "asterisk/stringfields.h"
#include "asterisk/presencestate.h"
#include "asterisk/stasis_message_router.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/test.h"
#include "asterisk/json.h"
#include "asterisk/bridge.h"
#include "asterisk/features_config.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/format_cache.h"
#include "asterisk/translate.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/message.h"

Go to the source code of this file.

Data Structures

struct  actions
 list of actions registered More...
 
struct  all_events
 
struct  ast_manager_user
 user descriptor, as read from the config file. More...
 
struct  eventqent
 
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::mansession_datastores
 
struct  mansession_session
 
struct  permalias
 
struct  users
 list of users found in the config file More...
 
struct  variable_count
 

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 FORMAT   " %-25.25s %-15.55s\n"
 
#define FORMAT2   " %-25.25s %-15d\n"
 
#define FORMAT3   " %-25.25s %s\n"
 
#define GET_HEADER_FIRST_MATCH   0
 
#define GET_HEADER_LAST_MATCH   1
 
#define GET_HEADER_SKIP_EMPTY   2
 
#define HSMC_FORMAT   " %-*.*s %-.*s\n"
 
#define HSMCONN_FORMAT1   " %-15.15s %-55.55s %-10.10s %-10.10s %-8.8s %-8.8s %-10.10s %-10.10s\n"
 
#define HSMCONN_FORMAT2   " %-15.15s %-55.55s %-10d %-10d %-8d %-8d %-10.10d %-10.10d\n"
 
#define MANAGER_EVENT_BUF_INITSIZE   256
 
#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. More...
 
#define MAX_VARS   128
 
#define MGR_SHOW_TERMINAL_WIDTH   80
 
#define MSG_MOREDATA   ((char *)astman_send_response)
 
#define ROW_FMT   "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
 
#define TEST_STRING   "<form action=\"manager\" method=\"post\">\n\ Action: <select name=\"action\">\n\ <option value=\"\">-----&gt;</option>\n\ <option value=\"login\">login</option>\n\ <option value=\"command\">Command</option>\n\ <option value=\"waitevent\">waitevent</option>\n\ <option value=\"listcommands\">listcommands</option>\n\ </select>\n\ or <input name=\"action\"><br/>\n\ CLI Command <input name=\"command\"><br>\n\ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br>\n\ <input type=\"submit\">\n</form>\n"
 

Enumerations

enum  add_filter_result { FILTER_SUCCESS, FILTER_ALLOC_FAILED, FILTER_COMPILE_FAIL }
 
enum  error_type {
  UNKNOWN_ACTION = 1, UNKNOWN_CATEGORY, UNSPECIFIED_CATEGORY, UNSPECIFIED_ARGUMENT,
  FAILURE_ALLOCATION, FAILURE_NEWCAT, FAILURE_DELCAT, FAILURE_EMPTYCAT,
  FAILURE_UPDATE, FAILURE_DELETE, FAILURE_APPEND, FAILURE_TEMPLATE
}
 
enum  mansession_message_parsing { MESSAGE_OKAY, MESSAGE_LINE_TOO_LONG }
 
enum  output_format { FORMAT_RAW, FORMAT_HTML, FORMAT_XML }
 

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. More...
 
static void __init_astman_append_buf (void)
 thread local buffer for astman_append More...
 
static int __init_manager (int reload, int by_external_config)
 
static void __init_manager_event_buf (void)
 
static void __init_userevent_buf (void)
 
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, int chancount, struct ast_channel **chans, const char *file, int line, const char *func, const char *fmt, va_list ap)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
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. More...
 
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 struct eventqentadvance_event (struct eventqent *e)
 
static AO2_GLOBAL_OBJ_STATIC (mgr_sessions)
 
static AO2_GLOBAL_OBJ_STATIC (event_docs)
 A container of event documentation nodes.
 
static int aocmessage_get_unit_entry (const struct message *m, struct ast_aoc_unit_entry *entry, unsigned int entry_num)
 
static void append_channel_vars (struct ast_str **pbuf, struct ast_channel *chan)
 
static int append_event (const char *str, int category)
 events are appended to a queue from where they can be dispatched to clients.
 
int ast_hook_send_action (struct manager_custom_hook *hook, const char *msg)
 access for hooks to send action messages to ami More...
 
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 ast_manager_event_blobast_manager_event_blob_create (int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
 Construct a ast_manager_event_blob. More...
 
struct stasis_message_routerast_manager_get_message_router (void)
 Get the stasis_message_router for AMI. More...
 
struct stasis_topicast_manager_get_topic (void)
 Get the Stasis Message Bus API topic for AMI. More...
 
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. More...
 
void ast_manager_publish_event (const char *type, int class_type, struct ast_json *obj)
 Publish an event to AMI. More...
 
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 More...
 
void ast_manager_register_hook (struct manager_custom_hook *hook)
 Add a custom hook to be called when an event is fired. More...
 
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. More...
 
int ast_manager_unregister (const char *action)
 support functions to register/unregister AMI action handlers, More...
 
void ast_manager_unregister_hook (struct manager_custom_hook *hook)
 Delete a custom hook to be called when an event is fired. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
int ast_str_append_event_header (struct ast_str **fields_string, const char *header, const char *value)
 append an event header to an ast string More...
 
int ast_webmanager_check_enabled (void)
 Check if AMI/HTTP is enabled.
 
static int ast_xml_doc_item_cmp_fn (const void *a, const void *b)
 
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. More...
 
static void astman_append_json (struct mansession *s, const char *str)
 
int astman_datastore_add (struct mansession *s, struct ast_datastore *datastore)
 Add a datastore to a session. More...
 
struct ast_datastoreastman_datastore_find (struct mansession *s, const struct ast_datastore_info *info, const char *uid)
 Find a datastore on a session. More...
 
int astman_datastore_remove (struct mansession *s, struct ast_datastore *datastore)
 Remove a datastore from a session. More...
 
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. More...
 
struct ast_variableastman_get_variables (const struct message *m)
 Get a linked list of the Variable: headers. More...
 
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.
 
int astman_is_authed (uint32_t ident)
 Determine if a manager session ident is authenticated.
 
void astman_live_dangerously (int new_live_dangerously)
 Enable/disable the inclusion of 'dangerous' configurations outside of the ast_config_AST_CONFIG_DIR. More...
 
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. More...
 
void astman_send_list_complete_start (struct mansession *s, const struct message *m, const char *event_name, int count)
 Start the list complete event. More...
 
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. More...
 
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. More...
 
static void astman_start_ack (struct mansession *s, const struct message *m)
 
int astman_verify_session_readpermissions (uint32_t ident, int perm)
 Verify a session's read permissions against a permission mask. More...
 
int astman_verify_session_writepermissions (uint32_t ident, int perm)
 Verify a session's write permissions against a permission mask. More...
 
static int auth_http_callback (struct ast_tcptls_session_instance *ser, enum ast_http_method method, enum output_format format, const struct ast_sockaddr *remote_address, const char *uri, struct ast_variable *get_params, struct ast_variable *headers)
 
static int auth_manager_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
 
static int auth_mxml_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
 
static int auth_rawman_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
 
static int authenticate (struct mansession *s, const struct message *m)
 
static const char * authority_to_str (int authority, struct ast_str **res)
 Convert authority code to a list of options. Note that the EVENT_FLAG_ALL authority will always be returned.
 
static int blackfilter_cmp_fn (void *obj, void *arg, void *data, int flags)
 
static struct mansession_sessionbuild_mansession (const struct ast_sockaddr *addr)
 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 void close_mansession_file (struct mansession *s)
 
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 void * fast_originate (void *data)
 
static struct mansession_sessionfind_session (uint32_t ident, int incinuse)
 
static struct mansession_sessionfind_session_by_nonce (const char *username, unsigned long nonce, int *stale)
 
static int function_amiclient (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 ${AMI_CLIENT()} Dialplan function - reads manager client data
 
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 generic_http_callback (struct ast_tcptls_session_instance *ser, enum ast_http_method method, enum output_format format, const struct ast_sockaddr *remote_address, const char *uri, struct ast_variable *get_params, struct ast_variable *headers)
 
static int get_input (struct mansession *s, char *output)
 
static struct ast_manager_userget_manager_by_name_locked (const char *name)
 
static int get_manager_sessions_cb (void *obj, void *arg, void *data, int flags)
 Get number of logged in sessions for a login name.
 
static int get_perm (const char *instr)
 
static struct eventqentgrab_last (void)
 
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_manager_show_event (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_manager_show_events (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_manager_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager show settings.
 
static char * handle_mandebug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void handle_parse_error (struct mansession *s, struct message *m, char *error)
 
static char * handle_showmanager (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_showmanagers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_showmancmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_showmancmds (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list commands.
 
static char * handle_showmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list connected.
 
static char * handle_showmaneventq (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 CLI command manager list eventq.
 
static enum error_type handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn)
 helper function for action_updateconfig
 
static void json_escape (char *out, const char *in)
 
static void load_channelvars (struct ast_variable *var)
 
static void load_disabledevents (struct ast_variable *var)
 
static int load_module (void)
 
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 *filter_pattern, struct ao2_container *whitefilters, struct ao2_container *blackfilters)
 Add an event filter to a manager session. More...
 
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. More...
 
static void manager_event_blob_dtor (void *obj)
 
static void manager_free_user (struct ast_manager_user *user)
 
static void manager_generic_msg_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static int manager_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
 
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 void manager_set_defaults (void)
 
static void manager_shutdown (void)
 
static int manager_state_cb (const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
 
static int manager_subscriptions_init (void)
 Initialize all Stasis Message Bus API topics and routers used by the various sub-components of AMI.
 
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_filter (struct mansession *s, char *eventdata)
 
static int mxml_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
 
static void print_event_instance (struct ast_cli_args *a, struct ast_xml_doc_item *instance)
 
static int process_events (struct mansession *s)
 
static int process_message (struct mansession *s, const struct message *m)
 Process an AMI message, performing desired action. Return 0 on success, -1 on error that require the session to be destroyed.
 
static void process_output (struct mansession *s, struct ast_str **out, struct ast_variable *params, enum output_format format)
 
static void purge_events (void)
 
static void purge_old_stuff (void *data)
 cleanup code called at each iteration of server_root, guaranteed to happen every 5 seconds at most
 
static int purge_sessions (int n_max)
 remove at most n_max stale session from the list.
 
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. More...
 
static int queue_sendtext (struct ast_channel *chan, const char *body)
 Queue a read action to send a text message. More...
 
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. More...
 
static int rawman_http_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
 
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 restrictedFile (const char *filename)
 Check if a file is restricted or not. More...
 
static int send_string (struct mansession *s, char *string)
 
static void session_destroy (struct mansession_session *s)
 
static void session_destructor (void *obj)
 
static void * session_do (void *data)
 The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). )
 
static int set_eventmask (struct mansession *s, const char *eventmask)
 Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm.
 
static int strings_to_mask (const char *string)
 
static int subscribe_all (void)
 
static int unload_module (void)
 
static struct mansession_sessionunref_mansession (struct mansession_session *s)
 Unreference manager session object. If no more references, then go ahead and delete it.
 
static const char * user_authority_to_str (int authority, struct ast_str **res)
 Convert authority code to a list of options for a user. This will only display those authority codes that have an explicit match on authority.
 
static int variable_count_cmp_fn (void *obj, void *vstr, int flags)
 
static int variable_count_hash_fn (const void *vvc, const int flags)
 
static int whitefilter_cmp_fn (void *obj, void *arg, void *data, int flags)
 
static void xml_copy_escape (struct ast_str **out, const char *src, int mode)
 
static void xml_translate (struct ast_str **out, char *in, struct ast_variable *get_vars, enum output_format format)
 Convert the input into XML or HTML. The input is supposed to be a sequence of lines of the form Name: value optionally followed by a blob of unformatted text. A blank line is a section separator. Basically, this is a mixture of the format of Manager Interface and CLI commands. The unformatted text is considered as a single value of a field named 'Opaque-data'. More...
 
 STASIS_MESSAGE_TYPE_DEFN (ast_manager_get_generic_type)
 Define AMI message types.
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Asterisk Manager Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "da6642af068ee5e6490c5b1d2cc1d238" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CORE, .requires = "extconfig,acl,http", }
 
static struct stasis_subscriptionacl_change_sub
 
static struct actions actions = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static struct all_events all_events = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static int allowmultiplelogin = 1
 
static struct ast_http_uri amanageruri
 
static struct ast_http_uri amanagerxmluri
 
static struct ast_tcptls_session_args ami_desc
 
static struct ast_tls_config ami_tls_cfg
 
static struct ast_tcptls_session_args amis_desc
 
static struct ast_http_uri arawmanuri
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_threadstorage astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , }
 
static int authlimit
 
static int authtimeout
 
static int broken_events_action = 0
 
static struct ast_cli_entry cli_manager []
 
struct {
   const char *   words [AST_MAX_CMD_LEN]
 
command_blacklist []
 
static const char *const contenttype []
 
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 ast_threadstorage manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , }
 
static struct manager_hooks manager_hooks = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static struct stasis_topicmanager_topic
 A stasis_topic that all topics AMI cares about will be forwarded to.
 
static struct ast_custom_function managerclient_function
 description of AMI_CLIENT dialplan function More...
 
static struct ast_http_uri manageruri
 
static struct ast_http_uri managerxmluri
 
static const struct permalias perms []
 
static struct ast_http_uri rawmanuri
 
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 ast_threadstorage userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , }
 
static struct users users = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static int webmanager_enabled = 0
 
static int webregged = 0
 

Detailed Description

The Asterisk Management Interface - AMI.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

OpenSSL http://www.openssl.org - for AMI/SSL

At the moment this file contains a number of functions, namely:

manager.conf

Definition in file manager.c.

Function Documentation

struct ast_manager_event_blob* ast_manager_event_blob_create ( int  event_flags,
const char *  manager_event,
const char *  extra_fields_fmt,
  ... 
)

Construct a ast_manager_event_blob.

Since
12 The returned object is AO2 managed, so clean up with ao2_cleanup().
Parameters
event_flagsFlags the event should be raised with.
manager_eventThe event to be raised, should be a string literal.
extra_fields_fmtFormat string for extra fields to include. Or NO_EXTRA_FIELDS for no extra fields.
Returns
New ast_manager_event_blob object.
Return values
NULLon error.

Definition at line 10563 of file manager.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_ref, ast_string_field_init, ast_string_field_ptr_build_va, ast_manager_event_blob::event_flags, ast_manager_event_blob::extra_fields, manager_event, and ast_manager_event_blob::manager_event.

Referenced by bridge_create(), bridge_destroy(), bridge_video_update(), and channel_state_change().

10569 {
10570  struct ast_manager_event_blob *ev;
10571  va_list argp;
10572 
10573  ast_assert(extra_fields_fmt != NULL);
10574  ast_assert(manager_event != NULL);
10575 
10576  ev = ao2_alloc_options(sizeof(*ev), manager_event_blob_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);
10577  if (!ev) {
10578  return NULL;
10579  }
10580 
10581  if (ast_string_field_init(ev, 20)) {
10582  ao2_ref(ev, -1);
10583  return NULL;
10584  }
10585 
10587  ev->event_flags = event_flags;
10588 
10589  va_start(argp, extra_fields_fmt);
10590  ast_string_field_ptr_build_va(ev, &ev->extra_fields, extra_fields_fmt, argp);
10591  va_end(argp);
10592 
10593  return ev;
Struct containing info for an AMI event to send out.
Definition: manager.h:502
const ast_string_field extra_fields
Definition: manager.h:507
#define ast_string_field_ptr_build_va(x, ptr, fmt, args)
Set a field to a complex (built) value with prebuilt va_lists.
Definition: stringfields.h:573
const char * manager_event
Definition: manager.h:504
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:253
int ast_str_append_event_header ( struct ast_str **  fields_string,
const char *  header,
const char *  value 
)

append an event header to an ast string

Since
12
Parameters
fields_stringpointer to an ast_string pointer. It may be a pointer to a NULL ast_str pointer, in which case the ast_str will be initialized.
headerThe header being applied
valuethe value of the header
Return values
0if successful
non-zeroon failure

Definition at line 10541 of file manager.c.

References ast_str_append(), and ast_str_create.

10544 {
10545  if (!*fields_string) {
10546  *fields_string = ast_str_create(128);
10547  if (!*fields_string) {
10548  return -1;
10549  }
10550  }
10551 
10552  return (ast_str_append(fields_string, 0, "%s: %s\r\n", header, value) < 0) ? -1 : 0;
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_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int astman_datastore_add ( struct mansession s,
struct ast_datastore datastore 
)

Add a datastore to a session.

Return values
0success
non-zerofailure
Since
1.6.1

Definition at line 10502 of file manager.c.

References AST_LIST_INSERT_HEAD, and mansession_session::datastores.

10504 {
10505  AST_LIST_INSERT_HEAD(&s->session->datastores, datastore, entry);
10506 
10507  return 0;
struct mansession_session::mansession_datastores datastores
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
Definition: search.h:40
struct ast_datastore* astman_datastore_find ( struct mansession s,
const struct ast_datastore_info info,
const char *  uid 
)

Find a datastore on a session.

Returns
pointer to the datastore if found
Return values
NULLif not found
Since
1.6.1

Definition at line 10514 of file manager.c.

References AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, mansession_session::datastores, ast_datastore::info, and ast_datastore::uid.

10516 {
10517  struct ast_datastore *datastore = NULL;
10518 
10519  if (info == NULL)
10520  return NULL;
10521 
10522  AST_LIST_TRAVERSE_SAFE_BEGIN(&s->session->datastores, datastore, entry) {
10523  if (datastore->info != info) {
10524  continue;
10525  }
10526 
10527  if (uid == NULL) {
10528  /* matched by type only */
10529  break;
10530  }
10531 
10532  if ((datastore->uid != NULL) && !strcasecmp(uid, datastore->uid)) {
10533  /* Matched by type AND uid */
10534  break;
10535  }
10536  }
10538 
10539  return datastore;
struct mansession_session::mansession_datastores datastores
Structure for a data store object.
Definition: datastore.h:64
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
const char * uid
Definition: datastore.h:65
const struct ast_datastore_info * info
Definition: datastore.h:67
Definition: search.h:40
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
int astman_datastore_remove ( struct mansession s,
struct ast_datastore datastore 
)

Remove a datastore from a session.

Return values
0success
non-zerofailure
Since
1.6.1

Definition at line 10509 of file manager.c.

References AST_LIST_REMOVE, and mansession_session::datastores.

10511 {
10512  return AST_LIST_REMOVE(&s->session->datastores, datastore, entry) ? 0 : -1;
struct mansession_session::mansession_datastores datastores
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:856
Definition: search.h:40
int astman_verify_session_readpermissions ( uint32_t  ident,
int  perm 
)

Verify a session's read permissions against a permission mask.

Parameters
identsession identity
permpermission mask to verify
Return values
1if the session has the permission mask capabilities
0otherwise

Definition at line 8364 of file manager.c.

References ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_ref, mansession_session::managerid, mansession_session::readperm, and unref_mansession().

8366 {
8367  int result = 0;
8368  struct mansession_session *session;
8369  struct ao2_container *sessions;
8370  struct ao2_iterator i;
8371 
8372  if (ident == 0) {
8373  return 0;
8374  }
8375 
8376  sessions = ao2_global_obj_ref(mgr_sessions);
8377  if (!sessions) {
8378  return 0;
8379  }
8380  i = ao2_iterator_init(sessions, 0);
8381  ao2_ref(sessions, -1);
8382  while ((session = ao2_iterator_next(&i))) {
8383  ao2_lock(session);
8384  if ((session->managerid == ident) && (session->readperm & perm)) {
8385  result = 1;
8386  ao2_unlock(session);
8387  unref_mansession(session);
8388  break;
8389  }
8390  ao2_unlock(session);
8391  unref_mansession(session);
8392  }
8394 
8395  return result;
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
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:2343
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
uint32_t managerid
Definition: manager.c:1747
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Generic container type.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
int astman_verify_session_writepermissions ( uint32_t  ident,
int  perm 
)

Verify a session's write permissions against a permission mask.

Parameters
identsession identity
permpermission mask to verify
Return values
1if the session has the permission mask capabilities, otherwise 0
0otherwise

Definition at line 8397 of file manager.c.

References ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_ref, mansession_session::managerid, unref_mansession(), and mansession_session::writeperm.

8399 {
8400  int result = 0;
8401  struct mansession_session *session;
8402  struct ao2_container *sessions;
8403  struct ao2_iterator i;
8404 
8405  if (ident == 0) {
8406  return 0;
8407  }
8408 
8409  sessions = ao2_global_obj_ref(mgr_sessions);
8410  if (!sessions) {
8411  return 0;
8412  }
8413  i = ao2_iterator_init(sessions, 0);
8414  ao2_ref(sessions, -1);
8415  while ((session = ao2_iterator_next(&i))) {
8416  ao2_lock(session);
8417  if ((session->managerid == ident) && (session->writeperm & perm)) {
8418  result = 1;
8419  ao2_unlock(session);
8420  unref_mansession(session);
8421  break;
8422  }
8423  ao2_unlock(session);
8424  unref_mansession(session);
8425  }
8427 
8428  return result;
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
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:2343
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
uint32_t managerid
Definition: manager.c:1747
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Generic container type.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
static struct mansession_session* find_session ( uint32_t  ident,
int  incinuse 
)
static

locate an http session in the list. The search key (ident) is the value of the mansession_id cookie (0 is not valid and means a session on the AMI socket).

Definition at line 8276 of file manager.c.

References ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_ref, ast_atomic_fetchadd_int(), mansession_session::inuse, mansession_session::managerid, mansession_session::needdestroy, and unref_mansession().

Referenced by astman_is_authed(), and generic_http_callback().

8278 {
8279  struct ao2_container *sessions;
8280  struct mansession_session *session;
8281  struct ao2_iterator i;
8282 
8283  if (ident == 0) {
8284  return NULL;
8285  }
8286 
8287  sessions = ao2_global_obj_ref(mgr_sessions);
8288  if (!sessions) {
8289  return NULL;
8290  }
8291  i = ao2_iterator_init(sessions, 0);
8292  ao2_ref(sessions, -1);
8293  while ((session = ao2_iterator_next(&i))) {
8294  ao2_lock(session);
8295  if (session->managerid == ident && !session->needdestroy) {
8296  ast_atomic_fetchadd_int(&session->inuse, incinuse ? 1 : 0);
8297  break;
8298  }
8299  ao2_unlock(session);
8300  unref_mansession(session);
8301  }
8303 
8304  return session;
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
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:2343
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:757
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
uint32_t managerid
Definition: manager.c:1747
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Generic container type.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
static struct mansession_session* find_session_by_nonce ( const char *  username,
unsigned long  nonce,
int *  stale 
)
static

locate an http session in the list. The search keys (nonce) and (username) is value from received "Authorization" http header. As well as in find_session() function, the value of the nonce can't be zero. (0 meansi, that the session used for AMI socket connection). Flag (stale) is set, if client used valid, but old, nonce value.

Definition at line 8315 of file manager.c.

References ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_ref, mansession_session::managerid, mansession_session::oldnonce, unref_mansession(), and mansession_session::username.

8317 {
8318  struct mansession_session *session;
8319  struct ao2_container *sessions;
8320  struct ao2_iterator i;
8321 
8322  if (nonce == 0 || username == NULL || stale == NULL) {
8323  return NULL;
8324  }
8325 
8326  sessions = ao2_global_obj_ref(mgr_sessions);
8327  if (!sessions) {
8328  return NULL;
8329  }
8330  i = ao2_iterator_init(sessions, 0);
8331  ao2_ref(sessions, -1);
8332  while ((session = ao2_iterator_next(&i))) {
8333  ao2_lock(session);
8334  if (!strcasecmp(session->username, username) && session->managerid == nonce) {
8335  *stale = 0;
8336  break;
8337  } else if (!strcasecmp(session->username, username) && session->oldnonce == nonce) {
8338  *stale = 1;
8339  break;
8340  }
8341  ao2_unlock(session);
8342  unref_mansession(session);
8343  }
8345 
8346  return session;
char username[80]
Definition: manager.c:1751
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
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:2343
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
uint32_t managerid
Definition: manager.c:1747
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Generic container type.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
unsigned long oldnonce
Definition: manager.c:1767
static int generic_http_callback ( struct ast_tcptls_session_instance ser,
enum ast_http_method  method,
enum output_format  format,
const struct ast_sockaddr remote_address,
const char *  uri,
struct ast_variable get_params,
struct ast_variable headers 
)
static
Note
There is approximately a 1 in 1.8E19 chance that the following calculation will produce 0, which is an invalid ID, but due to the properties of the rand() function (and the constancy of s), that won't happen twice in a row.

Definition at line 8714 of file manager.c.

References mansession_session::addr, ast_debug, ast_http_error(), ast_http_get_post_vars(), ast_http_manid_from_vars(), ast_http_request_close_on_completion(), ast_http_send(), ast_iostream_close(), ast_iostream_from_fd(), AST_LIST_HEAD_INIT_NOLOCK, ast_sockaddr_stringify_addr(), ast_str_append(), ast_str_create, ast_variables_destroy(), astman_append_headers(), astman_free_headers(), mansession_session::authenticated, build_mansession(), find_session(), grab_last(), mansession_session::inuse, manager_displayconnects(), mansession_session::managerid, mansession_session::needdestroy, mansession_session::notify_lock, process_message(), mansession_session::send_events, mansession_session::sessiontimeout, mansession_session::stream, unref_mansession(), mansession_session::username, and mansession_session::waiting_thread.

8721 {
8722  struct mansession s = { .session = NULL, .tcptls_session = ser };
8723  struct mansession_session *session = NULL;
8724  uint32_t ident;
8725  int fd;
8726  int blastaway = 0;
8727  struct ast_variable *params = get_params;
8728  char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */
8729  struct ast_str *http_header = NULL, *out = NULL;
8730  struct message m = { 0 };
8731 
8732  if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) {
8733  ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
8734  return 0;
8735  }
8736 
8737  ident = ast_http_manid_from_vars(headers);
8738 
8739  if (!(session = find_session(ident, 1))) {
8740 
8741  /**/
8742  /* Create new session.
8743  * While it is not in the list we don't need any locking
8744  */
8745  if (!(session = build_mansession(remote_address))) {
8747  ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)");
8748  return 0;
8749  }
8750  ao2_lock(session);
8751  session->send_events = 0;
8752  session->inuse = 1;
8753  /*!
8754  * \note There is approximately a 1 in 1.8E19 chance that the following
8755  * calculation will produce 0, which is an invalid ID, but due to the
8756  * properties of the rand() function (and the constancy of s), that
8757  * won't happen twice in a row.
8758  */
8759  while ((session->managerid = ast_random() ^ (unsigned long) session) == 0) {
8760  }
8761  session->last_ev = grab_last();
8762  AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
8763  }
8764  ao2_unlock(session);
8765 
8766  http_header = ast_str_create(128);
8767  out = ast_str_create(2048);
8768 
8769  ast_mutex_init(&s.lock);
8770 
8771  if (http_header == NULL || out == NULL) {
8773  ast_http_error(ser, 500, "Server Error", "Internal Server Error (ast_str_create() out of memory)");
8774  goto generic_callback_out;
8775  }
8776 
8777  s.session = session;
8778  fd = mkstemp(template); /* create a temporary file for command output */
8779  unlink(template);
8780  if (fd <= -1) {
8781  ast_http_error(ser, 500, "Server Error", "Internal Server Error (mkstemp failed)");
8782  goto generic_callback_out;
8783  }
8784  s.stream = ast_iostream_from_fd(&fd);
8785  if (!s.stream) {
8786  ast_log(LOG_WARNING, "HTTP Manager, fdopen failed: %s!\n", strerror(errno));
8787  ast_http_error(ser, 500, "Server Error", "Internal Server Error (fdopen failed)");
8788  close(fd);
8789  goto generic_callback_out;
8790  }
8791 
8792  if (method == AST_HTTP_POST) {
8793  params = ast_http_get_post_vars(ser, headers);
8794  if (!params) {
8795  switch (errno) {
8796  case EFBIG:
8797  ast_http_error(ser, 413, "Request Entity Too Large", "Body too large");
8798  close_mansession_file(&s);
8799  goto generic_callback_out;
8800  case ENOMEM:
8802  ast_http_error(ser, 500, "Server Error", "Out of memory");
8803  close_mansession_file(&s);
8804  goto generic_callback_out;
8805  case EIO:
8806  ast_http_error(ser, 400, "Bad Request", "Error parsing request body");
8807  close_mansession_file(&s);
8808  goto generic_callback_out;
8809  }
8810  }
8811  }
8812 
8813  astman_append_headers(&m, params);
8814 
8815  if (process_message(&s, &m)) {
8816  if (session->authenticated) {
8817  if (manager_displayconnects(session)) {
8818  ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_sockaddr_stringify_addr(&session->addr));
8819  }
8820  } else {
8821  if (displayconnects) {
8822  ast_verb(2, "HTTP Connect attempt from '%s' unable to authenticate\n", ast_sockaddr_stringify_addr(&session->addr));
8823  }
8824  }
8825  session->needdestroy = 1;
8826  }
8827 
8828  astman_free_headers(&m);
8829 
8830  ast_str_append(&http_header, 0,
8831  "Content-type: text/%s\r\n"
8832  "Set-Cookie: mansession_id=\"%08x\"; Version=1; Max-Age=%d\r\n"
8833  "Pragma: SuppressEvents\r\n",
8834  contenttype[format],
8835  session->managerid, httptimeout);
8836 
8837  if (format == FORMAT_XML) {
8838  ast_str_append(&out, 0, "<ajax-response>\n");
8839  } else if (format == FORMAT_HTML) {
8840  /*
8841  * When handling AMI-over-HTTP in HTML format, we provide a simple form for
8842  * debugging purposes. This HTML code should not be here, we
8843  * should read from some config file...
8844  */
8845 
8846 #define ROW_FMT "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
8847 #define TEST_STRING \
8848  "<form action=\"manager\" method=\"post\">\n\
8849  Action: <select name=\"action\">\n\
8850  <option value=\"\">-----&gt;</option>\n\
8851  <option value=\"login\">login</option>\n\
8852  <option value=\"command\">Command</option>\n\
8853  <option value=\"waitevent\">waitevent</option>\n\
8854  <option value=\"listcommands\">listcommands</option>\n\
8855  </select>\n\
8856  or <input name=\"action\"><br/>\n\
8857  CLI Command <input name=\"command\"><br>\n\
8858  user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br>\n\
8859  <input type=\"submit\">\n</form>\n"
8860 
8861  ast_str_append(&out, 0, "<title>Asterisk&trade; Manager Interface</title>");
8862  ast_str_append(&out, 0, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n");
8863  ast_str_append(&out, 0, ROW_FMT, "<h1>Manager Tester</h1>");
8864  ast_str_append(&out, 0, ROW_FMT, TEST_STRING);
8865  }
8866 
8867  process_output(&s, &out, params, format);
8868 
8869  if (format == FORMAT_XML) {
8870  ast_str_append(&out, 0, "</ajax-response>\n");
8871  } else if (format == FORMAT_HTML) {
8872  ast_str_append(&out, 0, "</table></body>\r\n");
8873  }
8874 
8875  ao2_lock(session);
8876  /* Reset HTTP timeout. If we're not authenticated, keep it extremely short */
8877  session->sessiontimeout = time(NULL) + ((session->authenticated || httptimeout < 5) ? httptimeout : 5);
8878 
8879  if (session->needdestroy) {
8880  if (session->inuse == 1) {
8881  ast_debug(1, "Need destroy, doing it now!\n");
8882  blastaway = 1;
8883  } else {
8884  ast_debug(1, "Need destroy, but can't do it yet!\n");
8885  ast_mutex_lock(&session->notify_lock);
8886  if (session->waiting_thread != AST_PTHREADT_NULL) {
8887  pthread_kill(session->waiting_thread, SIGURG);
8888  }
8889  ast_mutex_unlock(&session->notify_lock);
8890  session->inuse--;
8891  }
8892  } else {
8893  session->inuse--;
8894  }
8895  ao2_unlock(session);
8896 
8897  ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0);
8898  http_header = NULL;
8899  out = NULL;
8900 
8901 generic_callback_out:
8902  ast_mutex_destroy(&s.lock);
8903 
8904  /* Clear resource */
8905 
8906  if (method == AST_HTTP_POST && params) {
8907  ast_variables_destroy(params);
8908  }
8909  ast_free(http_header);
8910  ast_free(out);
8911 
8912  if (session) {
8913  if (blastaway) {
8914  session_destroy(session);
8915  } else {
8916  if (session->stream) {
8917  ast_iostream_close(session->stream);
8918  session->stream = NULL;
8919  }
8920  unref_mansession(session);
8921  }
8922  }
8923 
8924  return 0;
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
char username[80]
Definition: manager.c:1751
void ast_http_error(struct ast_tcptls_session_instance *ser, int status, const char *title, const char *text)
Send HTTP error message and close socket.
Definition: http.c:651
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
static void astman_append_headers(struct message *m, const struct ast_variable *params)
Append additional headers into the message structure from params.
Definition: manager.c:3060
pthread_t waiting_thread
Definition: manager.c:1746
Structure for variables, used for configurations and for channel variables.
struct ast_iostream * ast_iostream_from_fd(int *fd)
Create an iostream from a file descriptor.
Definition: iostream.c:611
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
uint32_t ast_http_manid_from_vars(struct ast_variable *headers) attribute_pure
Return manager id, if exist, from request headers.
Definition: http.c:220
struct ast_sockaddr addr
Definition: manager.c:1742
void ast_http_send(struct ast_tcptls_session_instance *ser, enum ast_http_method method, int status_code, const char *status_title, struct ast_str *http_header, struct ast_str *out, int fd, unsigned int static_content)
Generic function for sending HTTP/1.1 response.
Definition: http.c:459
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:2343
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:7391
static struct mansession_session * find_session(uint32_t ident, int incinuse)
Definition: manager.c:8276
time_t sessiontimeout
Definition: manager.c:1750
ast_mutex_t notify_lock
Definition: manager.c:1770
int ast_iostream_close(struct ast_iostream *stream)
Close an iostream.
Definition: iostream.c:539
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.
Definition: manager.c:1785
#define ast_debug(level,...)
Log a DEBUG message.
Support for dynamic strings.
Definition: strings.h:623
struct ast_iostream * stream
Definition: manager.c:1743
static void astman_free_headers(struct message *m)
Free headers inside message structure, but not the message structure itself.
Definition: manager.c:3074
uint32_t managerid
Definition: manager.c:1747
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
static struct mansession_session * build_mansession(const struct ast_sockaddr *addr)
Allocate manager session structure and add it to the list of sessions.
Definition: manager.c:2389
static struct eventqent * grab_last(void)
Definition: manager.c:2123
struct ast_variable * ast_http_get_post_vars(struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
Get post variables from client Request Entity-Body, if content type is application/x-www-form-urlenco...
Definition: http.c:1356
static int manager_displayconnects(struct mansession_session *session)
Get displayconnects config option.
Definition: manager.c:2482
void ast_http_request_close_on_completion(struct ast_tcptls_session_instance *ser)
Request the HTTP connection be closed after this HTTP request.
Definition: http.c:840
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
static void xml_translate ( struct ast_str **  out,
char *  in,
struct ast_variable get_vars,
enum output_format  format 
)
static

Convert the input into XML or HTML. The input is supposed to be a sequence of lines of the form Name: value optionally followed by a blob of unformatted text. A blank line is a section separator. Basically, this is a mixture of the format of Manager Interface and CLI commands. The unformatted text is considered as a single value of a field named 'Opaque-data'.

At the moment the output format is the following (but it may change depending on future requirements so don't count too much on it when writing applications):

General: the unformatted text is used as a value of XML output: to be completed

*   Each section is within <response type="object" id="xxx">
*   where xxx is taken from ajaxdest variable or defaults to unknown
*   Each row is reported as an attribute Name="value" of an XML
*   entity named from the variable ajaxobjtype, default to "generic"
* 

HTML output: each Name-value pair is output as a single row of a two-column table. Sections (blank lines in the input) are separated by a


Definition at line 8553 of file manager.c.

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_link, ao2_ref, ast_debug, ast_skip_blanks(), ast_str_append(), ast_trim_blanks(), ast_variable::name, ast_variable::next, and ast_variable::value.

8555 {
8556  struct ast_variable *v;
8557  const char *dest = NULL;
8558  char *var, *val;
8559  const char *objtype = NULL;
8560  int in_data = 0; /* parsing data */
8561  int inobj = 0;
8562  int xml = (format == FORMAT_XML);
8563  struct variable_count *vc = NULL;
8564  struct ao2_container *vco = NULL;
8565 
8566  if (xml) {
8567  /* dest and objtype need only for XML format */
8568  for (v = get_vars; v; v = v->next) {
8569  if (!strcasecmp(v->name, "ajaxdest")) {
8570  dest = v->value;
8571  } else if (!strcasecmp(v->name, "ajaxobjtype")) {
8572  objtype = v->value;
8573  }
8574  }
8575  if (ast_strlen_zero(dest)) {
8576  dest = "unknown";
8577  }
8578  if (ast_strlen_zero(objtype)) {
8579  objtype = "generic";
8580  }
8581  }
8582 
8583  /* we want to stop when we find an empty line */
8584  while (in && *in) {
8585  val = strsep(&in, "\r\n"); /* mark start and end of line */
8586  if (in && *in == '\n') { /* remove trailing \n if any */
8587  in++;
8588  }
8589  ast_trim_blanks(val);
8590  ast_debug(5, "inobj %d in_data %d line <%s>\n", inobj, in_data, val);
8591  if (ast_strlen_zero(val)) {
8592  /* empty line */
8593  if (in_data) {
8594  /* close data in Opaque mode */
8595  ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
8596  in_data = 0;
8597  }
8598 
8599  if (inobj) {
8600  /* close block */
8601  ast_str_append(out, 0, xml ? " /></response>\n" :
8602  "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
8603  inobj = 0;
8604  ao2_ref(vco, -1);
8605  vco = NULL;
8606  }
8607  continue;
8608  }
8609 
8610  if (!inobj) {
8611  /* start new block */
8612  if (xml) {
8613  ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype);
8614  }
8616  variable_count_hash_fn, NULL, variable_count_cmp_fn);
8617  inobj = 1;
8618  }
8619 
8620  if (in_data) {
8621  /* Process data field in Opaque mode. This is a
8622  * followup, so we re-add line feeds. */
8623  ast_str_append(out, 0, xml ? "\n" : "<br>\n");
8624  xml_copy_escape(out, val, 0); /* data field */
8625  continue;
8626  }
8627 
8628  /* We expect "Name: value" line here */
8629  var = strsep(&val, ":");
8630  if (val) {
8631  /* found the field name */
8632  val = ast_skip_blanks(val);
8633  ast_trim_blanks(var);
8634  } else {
8635  /* field name not found, switch to opaque mode */
8636  val = var;
8637  var = "Opaque-data";
8638  in_data = 1;
8639  }
8640 
8641 
8642  ast_str_append(out, 0, xml ? " " : "<tr><td>");
8643  if ((vc = ao2_find(vco, var, 0))) {
8644  vc->count++;
8645  } else {
8646  /* Create a new entry for this one */
8647  vc = ao2_alloc(sizeof(*vc), NULL);
8648  vc->varname = var;
8649  vc->count = 1;
8650  ao2_link(vco, vc);
8651  }
8652 
8653  xml_copy_escape(out, var, xml ? 1 | 2 : 0); /* data name */
8654  if (vc->count > 1) {
8655  ast_str_append(out, 0, "-%d", vc->count);
8656  }
8657  ao2_ref(vc, -1);
8658  ast_str_append(out, 0, xml ? "='" : "</td><td>");
8659  xml_copy_escape(out, val, 0); /* data field */
8660  if (!in_data || !*in) {
8661  ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
8662  }
8663  }
8664 
8665  if (inobj) {
8666  ast_str_append(out, 0, xml ? " /></response>\n" :
8667  "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
8668  ao2_ref(vco, -1);
8669  }
struct ast_variable * next
Structure for variables, used for configurations and for channel variables.
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 ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ast_debug(level,...)
Log a DEBUG message.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: strings.h:186
Generic container type.
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532

Variable Documentation

const char* const contenttype[]
static
Initial value:
= {
[FORMAT_RAW] = "plain",
[FORMAT_HTML] = "html",
[FORMAT_XML] = "xml",
}

Definition at line 8265 of file manager.c.

struct ast_custom_function managerclient_function
static
Initial value:
= {
.name = "AMI_CLIENT",
.read_max = 12,
}
static int function_amiclient(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
${AMI_CLIENT()} Dialplan function - reads manager client data
Definition: manager.c:9384

description of AMI_CLIENT dialplan function

Definition at line 9431 of file manager.c.