The Asterisk Management Interface - AMI. More...
#include "asterisk.h"#include "asterisk/_private.h"#include "asterisk/paths.h"#include <ctype.h>#include <sys/time.h>#include <signal.h>#include <sys/mman.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/lock.h"#include "asterisk/cli.h"#include "asterisk/app.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/version.h"#include "asterisk/term.h"#include "asterisk/astobj2.h"#include "asterisk/features.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 |
| struct | mansession_session::mansession_datastores |
| struct | mansession_session |
| struct | permalias |
| struct | sessions |
| struct | users |
| list of users found in the config file More... | |
| struct | variable_count |
Defines | |
| #define | ASTMAN_APPEND_BUF_INITSIZE 256 |
| initial allocated size for the astman_append_buf | |
| #define | GET_HEADER_FIRST_MATCH 0 |
| #define | GET_HEADER_LAST_MATCH 1 |
| #define | GET_HEADER_SKIP_EMPTY 2 |
| #define | HSMC_FORMAT " %-15.15s %-15.15s %-55.55s\n" |
| #define | HSMCONN_FORMAT1 " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n" |
| #define | HSMCONN_FORMAT2 " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n" |
| #define | MANAGER_EVENT_BUF_INITSIZE 256 |
| #define | MAX_BLACKLIST_CMD_LEN 2 |
| Descriptor for a manager session, either on the AMI socket or over HTTP. | |
| #define | MSG_MOREDATA ((char *)astman_send_response) |
| send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field. | |
| #define | ROW_FMT "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n" |
| #define | TEST_STRING "<form action=\"manager\">\n\ Action: <select name=\"action\">\n\ <option value=\"\">-----></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 | 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 } |
| enum | output_format { FORMAT_RAW, FORMAT_HTML, FORMAT_XML } |
Functions | |
| static const char * | __astman_get_header (const struct message *m, char *var, int mode) |
| static void | __init_astman_append_buf (void) |
| thread local buffer for astman_append | |
| static int | __init_manager (int reload) |
| static void | __init_manager_event_buf (void) |
| static void | __init_userevent_buf (void) |
| int | __manager_event (int category, const char *event, const char *file, int line, const char *func, const char *fmt,...) |
| manager_event: Send AMI event to client | |
| static int | action_atxfer (struct mansession *s, const struct message *m) |
| static int | action_challenge (struct mansession *s, const struct message *m) |
| static int | action_command (struct mansession *s, const struct message *m) |
| Manager command "command" - execute CLI command. | |
| static int | action_coresettings (struct mansession *s, const struct message *m) |
| Show PBX core settings information. | |
| static int | action_coreshowchannels (struct mansession *s, const struct message *m) |
| Manager command "CoreShowChannels" - List currently defined channels and some information about them. | |
| static int | action_corestatus (struct mansession *s, const struct message *m) |
| Show PBX core status information. | |
| static int | action_createconfig (struct mansession *s, const struct message *m) |
| static int | action_events (struct mansession *s, const struct message *m) |
| static int | action_extensionstate (struct mansession *s, const struct message *m) |
| static int | action_getconfig (struct mansession *s, const struct message *m) |
| static int | action_getconfigjson (struct mansession *s, const struct message *m) |
| static int | action_getvar (struct mansession *s, const struct message *m) |
| static int | action_hangup (struct mansession *s, const struct message *m) |
| static int | action_listcategories (struct mansession *s, const struct message *m) |
| static int | action_listcommands (struct mansession *s, const struct message *m) |
| static int | action_login (struct mansession *s, const struct message *m) |
| static int | action_logoff (struct mansession *s, const struct message *m) |
| static int | action_mailboxcount (struct mansession *s, const struct message *m) |
| static int | action_mailboxstatus (struct mansession *s, const struct message *m) |
| static int | action_originate (struct mansession *s, const struct message *m) |
| static int | action_ping (struct mansession *s, const struct message *m) |
| static int | action_redirect (struct mansession *s, const struct message *m) |
| action_redirect: The redirect manager command | |
| static int | action_reload (struct mansession *s, const struct message *m) |
| Send a reload event. | |
| static int | action_sendtext (struct mansession *s, const struct message *m) |
| static int | action_setvar (struct mansession *s, const struct message *m) |
| static int | action_status (struct mansession *s, const struct message *m) |
| Manager "status" command to show channels. | |
| static int | action_timeout (struct mansession *s, const struct message *m) |
| static int | action_updateconfig (struct mansession *s, const struct message *m) |
| static int | action_userevent (struct mansession *s, const struct message *m) |
| static int | action_waitevent (struct mansession *s, const struct message *m) |
| static struct eventqent * | advance_event (struct eventqent *e) |
| static int | append_event (const char *str, int category) |
| static int | ast_instring (const char *bigstr, const char *smallstr, const char delim) |
| int | ast_manager_register2 (const char *action, int auth, int(*func)(struct mansession *s, const struct message *m), const char *synopsis, const char *description) |
| register a new command with manager, including online help. This is the preferred way to register a manager command | |
| void | ast_manager_register_hook (struct manager_custom_hook *hook) |
| Add a custom hook to be called when an event is fired. | |
| static int | ast_manager_register_struct (struct manager_action *act) |
| int | ast_manager_unregister (char *action) |
| Unregister a registered manager command. | |
| void | ast_manager_unregister_hook (struct manager_custom_hook *hook) |
| Delete a custom hook to be called when an event is fired. | |
| void | astman_append (struct mansession *s, const char *fmt,...) |
| int | astman_datastore_add (struct mansession *s, struct ast_datastore *datastore) |
| Add a datastore to a session. | |
| struct ast_datastore * | astman_datastore_find (struct mansession *s, const struct ast_datastore_info *info, const char *uid) |
| Find a datastore on a session. | |
| int | astman_datastore_remove (struct mansession *s, struct ast_datastore *datastore) |
| Remove a datastore from a session. | |
| const char * | astman_get_header (const struct message *m, char *var) |
| Get header from mananger transaction. | |
| struct ast_variable * | astman_get_variables (const struct message *m) |
| Get a linked list of the Variable: headers. | |
| int | astman_is_authed (uint32_t ident) |
| Determinie if a manager session ident is authenticated. | |
| void | astman_send_ack (struct mansession *s, const struct message *m, char *msg) |
| Send ack in manager transaction. | |
| void | astman_send_error (struct mansession *s, const struct message *m, char *error) |
| Send error in manager transaction. | |
| void | astman_send_listack (struct mansession *s, const struct message *m, char *msg, char *listflag) |
| Send ack in manager list transaction. | |
| void | astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg) |
| Send response in manager transaction. | |
| static void | astman_send_response_full (struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag) |
| static void | astman_start_ack (struct mansession *s, const struct message *m) |
| int | astman_verify_session_readpermissions (uint32_t ident, int perm) |
| Verify a session's read permissions against a permission mask. | |
| int | astman_verify_session_writepermissions (uint32_t ident, int perm) |
| Verify a session's write permissions against a permission mask. | |
| static int | authenticate (struct mansession *s, const struct message *m) |
| static char * | authority_to_str (int authority, struct ast_str **res) |
| Convert authority code to a list of options. | |
| static int | check_blacklist (const char *cmd) |
| int | check_manager_enabled () |
| Event list management functions. We assume that the event list always has at least one element, and the delete code will not remove the last entry even if the. | |
| static int | check_manager_session_inuse (const char *name) |
| int | check_webmanager_enabled () |
| Check if AMI/HTTP is enabled. | |
| static int | compress_char (char c) |
| static void | destroy_session (struct mansession_session *session) |
| static int | do_message (struct mansession *s) |
| static void * | fast_originate (void *data) |
| static struct mansession_session * | find_session (uint32_t ident, int incinuse) |
| static void | free_session (struct mansession_session *session) |
| static struct ast_str * | generic_http_callback (enum output_format format, struct sockaddr_in *remote_address, const char *uri, enum ast_http_method method, struct ast_variable *params, int *status, char **title, int *contentlength) |
| static int | get_input (struct mansession *s, char *output) |
| static struct ast_manager_user * | get_manager_by_name_locked (const char *name) |
| static int | get_perm (const char *instr) |
| static struct eventqent * | grab_last (void) |
| static char * | handle_manager_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command manager reload. | |
| static char * | handle_mandebug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_showmanager (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_showmanagers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_showmancmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_showmancmds (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command manager list commands. | |
| static char * | handle_showmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command manager list connected. | |
| static char * | handle_showmaneventq (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| CLI command manager list eventq. | |
| static enum error_type | handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn) |
| int | init_manager (void) |
| Called by Asterisk initialization. | |
| static void | json_escape (char *out, const char *in) |
| static int | manager_displayconnects (struct mansession_session *session) |
| Get displayconnects config option. | |
| static struct ast_str * | 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 *params, struct ast_variable *headers, int *status, char **title, int *contentlength) |
| static int | manager_modulecheck (struct mansession *s, const struct message *m) |
| static int | manager_moduleload (struct mansession *s, const struct message *m) |
| static int | manager_state_cb (char *context, char *exten, int state, void *data) |
| static struct ast_str * | 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 *params, struct ast_variable *headers, int *status, char **title, int *contentlength) |
| static int | process_events (struct mansession *s) |
| static int | process_message (struct mansession *s, const struct message *m) |
| static void | purge_events (void) |
| static void | purge_old_stuff (void *data) |
| cleanup code called at each iteration of server_root, guaranteed to happen every 5 seconds at most | |
| static void | purge_sessions (int n_max) |
| remove at most n_max stale session from the list. | |
| static struct ast_str * | 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 *params, struct ast_variable *headers, int *status, char **title, int *contentlength) |
| int | reload_manager (void) |
| Called by Asterisk module functions and the CLI command. | |
| static int | send_string (struct mansession *s, char *string) |
| 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 | variable_count_cmp_fn (void *obj, void *vstr, int flags) |
| static int | variable_count_hash_fn (const void *vvc, const 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 *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'. | |
Variables | |
| static struct actions | actions |
| static struct all_events | all_events |
| static int | allowmultiplelogin = 1 |
| static struct ast_tcptls_session_args | ami_desc |
| struct ast_tls_config | ami_tls_cfg |
| static struct ast_tcptls_session_args | amis_desc |
| static struct ast_threadstorage | astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , } |
| static int | authlimit |
| static int | authtimeout |
| static int | block_sockets |
| static int | broken_events_action |
| static struct ast_cli_entry | cli_manager [] |
| struct { | |
| char * words [AST_MAX_CMD_LEN] | |
| } | command_blacklist [] |
| static char * | contenttype [] |
| static const int | DEFAULT_AUTHLIMIT = 50 |
| static const int | DEFAULT_AUTHTIMEOUT = 30 |
| static const int | DEFAULT_BLOCKSOCKETS = 0 |
| static const int | DEFAULT_BROKENEVENTSACTION = 0 |
| static const int | DEFAULT_DISPLAYCONNECTS = 1 |
| static const int | DEFAULT_ENABLED = 0 |
| static const int | DEFAULT_HTTPTIMEOUT = 60 |
| static const int | DEFAULT_TIMESTAMPEVENTS = 0 |
| static const int | DEFAULT_WEBENABLED = 0 |
| static int | displayconnects |
| static int | httptimeout |
| static int | manager_debug |
| static int | manager_enabled = 0 |
| static struct ast_threadstorage | manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , } |
| static struct manager_hooks | manager_hooks |
| struct ast_http_uri | manageruri |
| struct ast_http_uri | managerxmluri |
| static char | mandescr_atxfer [] = " ActionID: Optional Action id for message matching.\n" |
| static char | mandescr_command [] = " ActionID: Optional Action id for message matching.\n" |
| static char | mandescr_coresettings [] = " *ActionID: ActionID of this transaction\n" |
| static char | mandescr_coreshowchannels [] = " ActionID: Optional Action id for message matching.\n" |
| static char | mandescr_corestatus [] = " *ActionID: ActionID of this transaction\n" |
| static char | mandescr_createconfig [] = " Filename: The configuration filename to create (e.g. foo.conf)\n" |
| static char | mandescr_events [] = " 'system,call,log' to select which flags events should have to be sent.\n" |
| static char | mandescr_extensionstate [] = "The response will include the hint for the extension and the status.\n" |
| static char | mandescr_getconfig [] = " Category: Category in configuration file\n" |
| static char | mandescr_getconfigjson [] = " Filename: Configuration filename (e.g. foo.conf)\n" |
| static char | mandescr_getvar [] = " ActionID: Optional Action id for message matching.\n" |
| static char | mandescr_hangup [] = " Channel: The channel name to be hungup\n" |
| static char | mandescr_listcategories [] = " Filename: Configuration filename (e.g. foo.conf)\n" |
| static char | mandescr_listcommands [] = "Variables: NONE\n" |
| static char | mandescr_logoff [] = "Variables: NONE\n" |
| static char | mandescr_mailboxcount [] = "\n" |
| static char | mandescr_mailboxstatus [] = "\n" |
| Help text for manager command mailboxstatus. | |
| static char | mandescr_modulecheck [] = "For success returns, the module revision number is included.\n" |
| static char | mandescr_moduleload [] = " If no module is specified for a reload loadtype, all modules are reloaded" |
| static char | mandescr_originate [] = " Async: Set to 'true' for fast origination\n" |
| static char | mandescr_ping [] = "Variables: NONE\n" |
| Manager PING. | |
| static char | mandescr_redirect [] = " ActionID: Optional Action id for message matching.\n" |
| static char | mandescr_reload [] = " *Module: Name of the module to reload\n" |
| static char | mandescr_sendtext [] = " ActionID: Optional Action id for message matching.\n" |
| static char | mandescr_setvar [] = " *Value: Value\n" |
| static char | mandescr_status [] = "value for the specified channel variables.\n" |
| static char | mandescr_timeout [] = "Acknowledges set time with 'Timeout Set' message\n" |
| static char | mandescr_updateconfig [] = " Line-XXXXXX: Line in category to operate on (used with delete and insert actions)\n" |
| static char | mandescr_userevent [] = " HeaderN: ContentN\n" |
| static char | mandescr_waitevent [] = " Timeout: Maximum time (in seconds) to wait for events, -1 means forever.\n" |
| Manager WAITEVENT. | |
| static int | num_sessions |
| static struct permalias | perms [] |
| struct ast_http_uri | rawmanuri |
| static int | registered = 0 |
| static struct sessions | sessions |
| static int | timestampevents |
| static int | unauth_sessions = 0 |
| static struct ast_threadstorage | userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , } |
| static struct users | users |
| static int | webmanager_enabled = 0 |
| static int | webregged = 0 |
The Asterisk Management Interface - AMI.
At the moment this file contains a number of functions, namely:
Definition in file manager.c.
| #define HSMC_FORMAT " %-15.15s %-15.15s %-55.55s\n" |
Referenced by handle_showmancmds().
| #define HSMCONN_FORMAT1 " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n" |
Referenced by handle_showmanconn().
| #define HSMCONN_FORMAT2 " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n" |
Referenced by handle_showmanconn().
| #define ROW_FMT "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n" |
Referenced by generic_http_callback().
| #define TEST_STRING "<form action=\"manager\">\n\ Action: <select name=\"action\">\n\ <option value=\"\">-----></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" |
Referenced by generic_http_callback().
| enum output_format |
END Doxygen group
Definition at line 3602 of file manager.c.
{
FORMAT_RAW,
FORMAT_HTML,
FORMAT_XML,
};
| static int __init_manager | ( | int | reload | ) | [static] |
Definition at line 4186 of file manager.c.
References action_atxfer(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_createconfig(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_listcommands(), action_login(), action_logoff(), action_mailboxcount(), action_mailboxstatus(), action_originate(), action_ping(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_updateconfig(), action_userevent(), action_waitevent(), ahp, ami_desc, ami_tls_cfg, amis_desc, append_event(), ARRAY_LEN, ast_append_ha(), ast_calloc, ast_category_browse(), AST_CERTFILE, ast_cli_register_multiple(), ast_config_destroy(), ast_config_load2(), ast_copy_string(), ast_debug, ast_extension_state_add(), ast_free, ast_free_ha(), ast_gethostbyname(), ast_http_uri_link(), ast_http_uri_unlink(), AST_LIST_INSERT_TAIL, ast_log(), ast_manager_register2(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_ssl_setup(), ast_strdup, ast_strlen_zero(), ast_tcptls_server_start(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_tls_config::certfile, ast_tls_config::cipher, cli_manager, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_AUTHLIMIT, DEFAULT_AUTHTIMEOUT, DEFAULT_BLOCKSOCKETS, DEFAULT_BROKENEVENTSACTION, DEFAULT_DISPLAYCONNECTS, DEFAULT_ENABLED, DEFAULT_HTTPTIMEOUT, DEFAULT_MANAGER_PORT, DEFAULT_TIMESTAMPEVENTS, DEFAULT_WEBENABLED, displayconnects, ast_manager_user::displayconnects, ast_tls_config::enabled, EVENT_FLAG_CALL, EVENT_FLAG_COMMAND, EVENT_FLAG_CONFIG, EVENT_FLAG_ORIGINATE, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, EVENT_FLAG_USER, get_manager_by_name_locked(), get_perm(), ast_manager_user::ha, hp, inet_aton(), ast_manager_user::keep, ast_variable::lineno, ast_tcptls_session_args::local_address, LOG_NOTICE, LOG_WARNING, manager_event, manager_modulecheck(), manager_moduleload(), manager_state_cb(), manageruri, managerxmluri, mandescr_atxfer, mandescr_command, mandescr_coresettings, mandescr_coreshowchannels, mandescr_corestatus, mandescr_createconfig, mandescr_events, mandescr_extensionstate, mandescr_getconfig, mandescr_getconfigjson, mandescr_getvar, mandescr_hangup, mandescr_listcategories, mandescr_listcommands, mandescr_logoff, mandescr_mailboxcount, mandescr_mailboxstatus, mandescr_modulecheck, mandescr_moduleload, mandescr_originate, mandescr_ping, mandescr_redirect, mandescr_reload, mandescr_sendtext, mandescr_setvar, mandescr_status, mandescr_timeout, mandescr_updateconfig, mandescr_userevent, mandescr_waitevent, ast_variable::name, ast_variable::next, rawmanuri, ast_manager_user::readperm, registered, ast_manager_user::secret, ast_tcptls_session_args::tls_cfg, ast_manager_user::username, val, ast_variable::value, var, webregged, ast_manager_user::writeperm, and ast_manager_user::writetimeout.
Referenced by init_manager(), and reload_manager().
{
struct ast_config *ucfg = NULL, *cfg = NULL;
const char *val;
char *cat = NULL;
int newhttptimeout = DEFAULT_HTTPTIMEOUT;
int have_sslbindaddr = 0;
struct hostent *hp;
struct ast_hostent ahp;
struct ast_manager_user *user = NULL;
struct ast_variable *var;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
if (!registered) {
/* Register default actions */
ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping);
ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
ast_manager_register2("Login", 0, action_login, "Login Manager", NULL);
ast_manager_register2("Challenge", 0, action_challenge, "Generate Challenge for MD5 Auth", NULL);
ast_manager_register2("Hangup", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
ast_manager_register2("Status", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_status, "Lists channel status", mandescr_status);
ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar);
ast_manager_register2("Getvar", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_getvar, "Gets a Channel Variable", mandescr_getvar);
ast_manager_register2("GetConfig", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig);
ast_manager_register2("GetConfigJSON", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfigjson, "Retrieve configuration (JSON format)", mandescr_getconfigjson);
ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig);
ast_manager_register2("CreateConfig", EVENT_FLAG_CONFIG, action_createconfig, "Creates an empty file in the configuration directory", mandescr_createconfig);
ast_manager_register2("ListCategories", EVENT_FLAG_CONFIG, action_listcategories, "List categories in configuration file", mandescr_listcategories);
ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect );
ast_manager_register2("Atxfer", EVENT_FLAG_CALL, action_atxfer, "Attended transfer", mandescr_atxfer);
ast_manager_register2("Originate", EVENT_FLAG_ORIGINATE, action_originate, "Originate Call", mandescr_originate);
ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command );
ast_manager_register2("ExtensionState", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_extensionstate, "Check Extension Status", mandescr_extensionstate );
ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout );
ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus );
ast_manager_register2("MailboxCount", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount );
ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands);
ast_manager_register2("SendText", EVENT_FLAG_CALL, action_sendtext, "Send text message to channel", mandescr_sendtext);
ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent);
ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent);
ast_manager_register2("CoreSettings", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coresettings, "Show PBX core settings (version etc)", mandescr_coresettings);
ast_manager_register2("CoreStatus", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_corestatus, "Show PBX core status variables", mandescr_corestatus);
ast_manager_register2("Reload", EVENT_FLAG_CONFIG | EVENT_FLAG_SYSTEM, action_reload, "Send a reload event", mandescr_reload);
ast_manager_register2("CoreShowChannels", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coreshowchannels, "List currently active channels", mandescr_coreshowchannels);
ast_manager_register2("ModuleLoad", EVENT_FLAG_SYSTEM, manager_moduleload, "Module management", mandescr_moduleload);
ast_manager_register2("ModuleCheck", EVENT_FLAG_SYSTEM, manager_modulecheck, "Check if module is loaded", mandescr_modulecheck);
ast_cli_register_multiple(cli_manager, ARRAY_LEN(cli_manager));
ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
registered = 1;
/* Append placeholder event so master_eventq never runs dry */
append_event("Event: Placeholder\r\n\r\n", 0);
}
if ((cfg = ast_config_load2("manager.conf", "manager", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
return 0;
manager_enabled = DEFAULT_ENABLED;
webmanager_enabled = DEFAULT_WEBENABLED;
displayconnects = DEFAULT_DISPLAYCONNECTS;
broken_events_action = DEFAULT_BROKENEVENTSACTION;
block_sockets = DEFAULT_BLOCKSOCKETS;
timestampevents = DEFAULT_TIMESTAMPEVENTS;
httptimeout = DEFAULT_HTTPTIMEOUT;
authtimeout = DEFAULT_AUTHTIMEOUT;
authlimit = DEFAULT_AUTHLIMIT;
if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf, or configuration is invalid. Asterisk management interface (AMI) disabled.\n");
return 0;
}
/* default values */
memset(&ami_desc.local_address, 0, sizeof(struct sockaddr_in));
memset(&amis_desc.local_address, 0, sizeof(amis_desc.local_address));
amis_desc.local_address.sin_port = htons(5039);
ami_desc.local_address.sin_port = htons(DEFAULT_MANAGER_PORT);
ami_tls_cfg.enabled = 0;
if (ami_tls_cfg.certfile)
ast_free(ami_tls_cfg.certfile);
ami_tls_cfg.certfile = ast_strdup(AST_CERTFILE);
if (ami_tls_cfg.cipher)
ast_free(ami_tls_cfg.cipher);
ami_tls_cfg.cipher = ast_strdup("");
for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
val = var->value;
if (!strcasecmp(var->name, "sslenable"))
ami_tls_cfg.enabled = ast_true(val);
else if (!strcasecmp(var->name, "sslbindport"))
amis_desc.local_address.sin_port = htons(atoi(val));
else if (!strcasecmp(var->name, "sslbindaddr")) {
if ((hp = ast_gethostbyname(val, &ahp))) {
memcpy(&amis_desc.local_address.sin_addr, hp->h_addr, sizeof(amis_desc.local_address.sin_addr));
have_sslbindaddr = 1;
} else {
ast_log(LOG_WARNING, "Invalid bind address '%s'\n", val);
}
} else if (!strcasecmp(var->name, "sslcert")) {
ast_free(ami_tls_cfg.certfile);
ami_tls_cfg.certfile = ast_strdup(val);
} else if (!strcasecmp(var->name, "sslcipher")) {
ast_free(ami_tls_cfg.cipher);
ami_tls_cfg.cipher = ast_strdup(val);
} else if (!strcasecmp(var->name, "enabled")) {
manager_enabled = ast_true(val);
} else if (!strcasecmp(var->name, "block-sockets")) {
block_sockets = ast_true(val);
} else if (!strcasecmp(var->name, "webenabled")) {
webmanager_enabled = ast_true(val);
} else if (!strcasecmp(var->name, "port")) {
ami_desc.local_address.sin_port = htons(atoi(val));
} else if (!strcasecmp(var->name, "bindaddr")) {
if (!inet_aton(val, &ami_desc.local_address.sin_addr)) {
ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
memset(&ami_desc.local_address.sin_addr, 0, sizeof(ami_desc.local_address.sin_addr));
}
} else if (!strcasecmp(var->name, "brokeneventsaction")) {
broken_events_action = ast_true(val);
} else if (!strcasecmp(var->name, "allowmultiplelogin")) {
allowmultiplelogin = ast_true(val);
} else if (!strcasecmp(var->name, "displayconnects")) {
displayconnects = ast_true(val);
} else if (!strcasecmp(var->name, "timestampevents")) {
timestampevents = ast_true(val);
} else if (!strcasecmp(var->name, "debug")) {
manager_debug = ast_true(val);
} else if (!strcasecmp(var->name, "httptimeout")) {
newhttptimeout = atoi(val);
} else if (!strcasecmp(var->name, "authtimeout")) {
int timeout = atoi(var->value);
if (timeout < 1) {
ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", var->value);
} else {
authtimeout = timeout;
}
} else if (!strcasecmp(var->name, "authlimit")) {
int limit = atoi(var->value);
if (limit < 1) {
ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", var->value);
} else {
authlimit = limit;
}
} else {
ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n",
var->name, val);
}
}
if (manager_enabled)
ami_desc.local_address.sin_family = AF_INET;
if (!have_sslbindaddr)
amis_desc.local_address.sin_addr = ami_desc.local_address.sin_addr;
if (ami_tls_cfg.enabled)
amis_desc.local_address.sin_family = AF_INET;
AST_RWLIST_WRLOCK(&users);
/* First, get users from users.conf */
ucfg = ast_config_load2("users.conf", "manager", config_flags);
if (ucfg && (ucfg != CONFIG_STATUS_FILEUNCHANGED) && ucfg != CONFIG_STATUS_FILEINVALID) {
const char *hasmanager;
int genhasmanager = ast_true(ast_variable_retrieve(ucfg, "general", "hasmanager"));
while ((cat = ast_category_browse(ucfg, cat))) {
if (!strcasecmp(cat, "general"))
continue;
hasmanager = ast_variable_retrieve(ucfg, cat, "hasmanager");
if ((!hasmanager && genhasmanager) || ast_true(hasmanager)) {
const char *user_secret = ast_variable_retrieve(ucfg, cat, "secret");
const char *user_read = ast_variable_retrieve(ucfg, cat, "read");
const char *user_write = ast_variable_retrieve(ucfg, cat, "write");
const char *user_displayconnects = ast_variable_retrieve(ucfg, cat, "displayconnects");
const char *user_writetimeout = ast_variable_retrieve(ucfg, cat, "writetimeout");
/* Look for an existing entry,
* if none found - create one and add it to the list
*/
if (!(user = get_manager_by_name_locked(cat))) {
if (!(user = ast_calloc(1, sizeof(*user))))
break;
/* Copy name over */
ast_copy_string(user->username, cat, sizeof(user->username));
/* Insert into list */
AST_LIST_INSERT_TAIL(&users, user, list);
user->ha = NULL;
user->keep = 1;
user->readperm = -1;
user->writeperm = -1;
/* Default displayconnect from [general] */
user->displayconnects = displayconnects;
user->writetimeout = 100;
}
if (!user_secret)
user_secret = ast_variable_retrieve(ucfg, "general", "secret");
if (!user_read)
user_read = ast_variable_retrieve(ucfg, "general", "read");
if (!user_write)
user_write = ast_variable_retrieve(ucfg, "general", "write");
if (!user_displayconnects)
user_displayconnects = ast_variable_retrieve(ucfg, "general", "displayconnects");
if (!user_writetimeout)
user_writetimeout = ast_variable_retrieve(ucfg, "general", "writetimeout");
if (!ast_strlen_zero(user_secret)) {
if (user->secret)
ast_free(user->secret);
user->secret = ast_strdup(user_secret);
}
if (user_read)
user->readperm = get_perm(user_read);
if (user_write)
user->writeperm = get_perm(user_write);
if (user_displayconnects)
user->displayconnects = ast_true(user_displayconnects);
if (user_writetimeout) {
int value = atoi(user_writetimeout);
if (value < 100)
ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at users.conf line %d\n", var->value, var->lineno);
else
user->writetimeout = value;
}
}
}
ast_config_destroy(ucfg);
}
/* cat is NULL here in any case */
while ((cat = ast_category_browse(cfg, cat))) {
struct ast_ha *oldha;
if (!strcasecmp(cat, "general"))
continue;
/* Look for an existing entry, if none found - create one and add it to the list */
if (!(user = get_manager_by_name_locked(cat))) {
if (!(user = ast_calloc(1, sizeof(*user))))
break;
/* Copy name over */
ast_copy_string(user->username, cat, sizeof(user->username));
user->ha = NULL;
user->readperm = 0;
user->writeperm = 0;
/* Default displayconnect from [general] */
user->displayconnects = displayconnects;
user->writetimeout = 100;
/* Insert into list */
AST_RWLIST_INSERT_TAIL(&users, user, list);
}
/* Make sure we keep this user and don't destroy it during cleanup */
user->keep = 1;
oldha = user->ha;
user->ha = NULL;
var = ast_variable_browse(cfg, cat);
for (; var; var = var->next) {
if (!strcasecmp(var->name, "secret")) {
if (user->secret)
ast_free(user->secret);
user->secret = ast_strdup(var->value);
} else if (!strcasecmp(var->name, "deny") ||
!strcasecmp(var->name, "permit")) {
user->ha = ast_append_ha(var->name, var->value, user->ha, NULL);
} else if (!strcasecmp(var->name, "read") ) {
user->readperm = get_perm(var->value);
} else if (!strcasecmp(var->name, "write") ) {
user->writeperm = get_perm(var->value);
} else if (!strcasecmp(var->name, "displayconnects") ) {
user->displayconnects = ast_true(var->value);
} else if (!strcasecmp(var->name, "writetimeout")) {
int value = atoi(var->value);
if (value < 100)
ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", var->value, var->lineno);
else
user->writetimeout = value;
} else
ast_debug(1, "%s is an unknown option.\n", var->name);
}
ast_free_ha(oldha);
}
ast_config_destroy(cfg);
/* Perform cleanup - essentially prune out old users that no longer exist */
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
if (user->keep) { /* valid record. clear flag for the next round */
user->keep = 0;
continue;
}
/* We do not need to keep this user so take them out of the list */
AST_RWLIST_REMOVE_CURRENT(list);
/* Free their memory now */
if (user->secret)
ast_free(user->secret);
ast_free_ha(user->ha);
ast_free(user);
}
AST_RWLIST_TRAVERSE_SAFE_END;
AST_RWLIST_UNLOCK(&users);
if (webmanager_enabled && manager_enabled) {
if (!webregged) {
ast_http_uri_link(&rawmanuri);
ast_http_uri_link(&manageruri);
ast_http_uri_link(&managerxmluri);
webregged = 1;
}
} else {
if (webregged) {
ast_http_uri_unlink(&rawmanuri);
ast_http_uri_unlink(&manageruri);
ast_http_uri_unlink(&managerxmluri);
webregged = 0;
}
}
if (newhttptimeout > 0)
httptimeout = newhttptimeout;
manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: Manager\r\nStatus: %s\r\nMessage: Manager reload Requested\r\n", manager_enabled ? "Enabled" : "Disabled");
ast_tcptls_server_start(&ami_desc);
if (ast_ssl_setup(amis_desc.tls_cfg))
ast_tcptls_server_start(&amis_desc);
return 0;
}
| int astman_datastore_add | ( | struct mansession * | s, |
| struct ast_datastore * | datastore | ||
| ) |
Add a datastore to a session.
| 0 | success |
| non-zero | failure |
Definition at line 4536 of file manager.c.
References AST_LIST_INSERT_HEAD, mansession_session::datastores, and mansession::session.
{
AST_LIST_INSERT_HEAD(&s->session->datastores, datastore, entry);
return 0;
}
| struct ast_datastore* astman_datastore_find | ( | struct mansession * | s, |
| const struct ast_datastore_info * | info, | ||
| const char * | uid | ||
| ) | [read] |
Find a datastore on a session.
| pointer | to the datastore if found |
| NULL | if not found |
Definition at line 4548 of file manager.c.
References AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, mansession_session::datastores, ast_datastore::info, mansession::session, and ast_datastore::uid.
{
struct ast_datastore *datastore = NULL;
if (info == NULL)
return NULL;
AST_LIST_TRAVERSE_SAFE_BEGIN(&s->session->datastores, datastore, entry) {
if (datastore->info != info) {
continue;
}
if (uid == NULL) {
/* matched by type only */
break;
}
if ((datastore->uid != NULL) && !strcasecmp(uid, datastore->uid)) {
/* Matched by type AND uid */
break;
}
}
AST_LIST_TRAVERSE_SAFE_END;
return datastore;
}
| int astman_datastore_remove | ( | struct mansession * | s, |
| struct ast_datastore * | datastore | ||
| ) |
Remove a datastore from a session.
| 0 | success |
| non-zero | failure |
Definition at line 4543 of file manager.c.
References AST_LIST_REMOVE, mansession_session::datastores, and mansession::session.
{
return AST_LIST_REMOVE(&s->session->datastores, datastore, entry) ? 0 : -1;
}
| int astman_is_authed | ( | uint32_t | ident | ) |
Determinie if a manager session ident is authenticated.
Definition at line 3640 of file manager.c.
References mansession_session::__lock, ast_mutex_unlock(), mansession_session::authenticated, and find_session().
Referenced by handle_uri(), and static_callback().
{
int authed;
struct mansession_session *session;
if (!(session = find_session(ident, 0)))
return 0;
authed = (session->authenticated != 0);
ast_mutex_unlock(&session->__lock);
return authed;
}
| int astman_verify_session_readpermissions | ( | uint32_t | ident, |
| int | perm | ||
| ) |
Verify a session's read permissions against a permission mask.
| ident | session identity |
| perm | permission mask to verify |
| 1 | if the session has the permission mask capabilities |
| 0 | otherwise |
Definition at line 3655 of file manager.c.
References mansession_session::__lock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession_session::managerid, and mansession_session::readperm.
{
int result = 0;
struct mansession_session *session;
AST_LIST_LOCK(&sessions);
AST_LIST_TRAVERSE(&sessions, session, list) {
ast_mutex_lock(&session->__lock);
if ((session->managerid == ident) && (session->readperm & perm)) {
result = 1;
ast_mutex_unlock(&session->__lock);
break;
}
ast_mutex_unlock(&session->__lock);
}
AST_LIST_UNLOCK(&sessions);
return result;
}
| int astman_verify_session_writepermissions | ( | uint32_t | ident, |
| int | perm | ||
| ) |
Verify a session's write permissions against a permission mask.
| ident | session identity |
| perm | permission mask to verify |
| 1 | if the session has the permission mask capabilities, otherwise 0 |
| 0 | otherwise |
Definition at line 3674 of file manager.c.
References mansession_session::__lock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession_session::managerid, and mansession_session::writeperm.
Referenced by http_post_callback().
{
int result = 0;
struct mansession_session *session;
AST_LIST_LOCK(&sessions);
AST_LIST_TRAVERSE(&sessions, session, list) {
ast_mutex_lock(&session->__lock);
if ((session->managerid == ident) && (session->writeperm & perm)) {
result = 1;
ast_mutex_unlock(&session->__lock);
break;
}
ast_mutex_unlock(&session->__lock);
}
AST_LIST_UNLOCK(&sessions);
return result;
}
| static int compress_char | ( | char | c | ) | [static] |
Definition at line 3759 of file manager.c.
Referenced by variable_count_hash_fn().
{
c &= 0x7f;
if (c < 32)
return 0;
else if (c >= 'a' && c <= 'z')
return c - 64;
else if (c > 'z')
return '_';
else
return c - 32;
}
| static struct mansession_session* find_session | ( | uint32_t | ident, |
| int | incinuse | ||
| ) | [static, read] |
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 3619 of file manager.c.
References mansession_session::__lock, ast_atomic_fetchadd_int(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession_session::inuse, mansession_session::managerid, and mansession_session::needdestroy.
Referenced by astman_is_authed(), and generic_http_callback().
{
struct mansession_session *session;
if (ident == 0)
return NULL;
AST_LIST_LOCK(&sessions);
AST_LIST_TRAVERSE(&sessions, session, list) {
ast_mutex_lock(&session->__lock);
if (session->managerid == ident && !session->needdestroy) {
ast_atomic_fetchadd_int(&session->inuse, incinuse ? 1 : 0);
break;
}
ast_mutex_unlock(&session->__lock);
}
AST_LIST_UNLOCK(&sessions);
return session;
}
| static struct ast_str* generic_http_callback | ( | enum output_format | format, |
| struct sockaddr_in * | remote_address, | ||
| const char * | uri, | ||
| enum ast_http_method | method, | ||
| struct ast_variable * | params, | ||
| int * | status, | ||
| char ** | title, | ||
| int * | contentlength | ||
| ) | [static, read] |
Definition at line 3923 of file manager.c.
References mansession_session::__lock, ast_atomic_fetchadd_int(), ast_calloc, ast_debug, ast_http_error(), ast_inet_ntoa(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_MAX_MANHEADERS, ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, ast_random(), ast_str_append(), ast_str_create(), ast_verb, mansession_session::authenticated, buf, contenttype, destroy_session(), mansession::f, mansession::fd, mansession_session::fd, find_session(), FORMAT_HTML, FORMAT_XML, grab_last(), message::hdrcount, message::headers, mansession_session::inuse, LOG_EVENT, LOG_WARNING, manager_displayconnects(), mansession_session::managerid, ast_variable::name, mansession_session::needdestroy, ast_variable::next, process_message(), ROW_FMT, s, mansession_session::send_events, mansession::session, mansession_session::sessiontimeout, mansession_session::sin, TEST_STRING, mansession_session::username, ast_variable::value, mansession_session::waiting_thread, and xml_translate().
Referenced by manager_http_callback(), mxml_http_callback(), and rawman_http_callback().
{
struct mansession s = {.session = NULL, };
struct mansession_session *session = NULL;
uint32_t ident = 0;
int blastaway = 0;
struct ast_variable *v;
char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */
struct ast_str *out = NULL;
struct message m = { 0 };
unsigned int x;
size_t hdrlen;
for (v = params; v; v = v->next) {
if (!strcasecmp(v->name, "mansession_id")) {
sscanf(v->value, "%30x", &ident);
break;
}
}
if (!(session = find_session(ident, 1))) {
/* Create new session.
* While it is not in the list we don't need any locking
*/
if (!(session = ast_calloc(1, sizeof(*session)))) {
*status = 500;
goto generic_callback_out;
}
session->sin = *remote_address;
session->fd = -1;
session->waiting_thread = AST_PTHREADT_NULL;
session->send_events = 0;
ast_mutex_init(&session->__lock);
ast_mutex_lock(&session->__lock);
session->inuse = 1;
/*!\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 constantcy of s), that
* won't happen twice in a row.
*/
while ((session->managerid = ast_random() ^ (unsigned long) session) == 0);
session->last_ev = grab_last();
AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
AST_LIST_LOCK(&sessions);
AST_LIST_INSERT_HEAD(&sessions, session, list);
ast_atomic_fetchadd_int(&num_sessions, 1);
AST_LIST_UNLOCK(&sessions);
}
s.session = session;
ast_mutex_unlock(&session->__lock);
if (!(out = ast_str_create(1024))) {
*status = 500;
goto generic_callback_out;
}
s.fd = mkstemp(template); /* create a temporary file for command output */
unlink(template);
s.f = fdopen(s.fd, "w+");
for (x = 0, v = params; v && (x < AST_MAX_MANHEADERS); x++, v = v->next) {
hdrlen = strlen(v->name) + strlen(v->value) + 3;
m.headers[m.hdrcount] = alloca(hdrlen);
snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value);
ast_debug(1, "HTTP Manager add header %s\n", m.headers[m.hdrcount]);
m.hdrcount = x + 1;
}
if (process_message(&s, &m)) {
if (session->authenticated) {
if (manager_displayconnects(session)) {
ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
}
ast_log(LOG_EVENT, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
} else {
if (displayconnects) {
ast_verb(2, "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
}
ast_log(LOG_EVENT, "HTTP Failed attempt from %s\n", ast_inet_ntoa(session->sin.sin_addr));
}
session->needdestroy = 1;
}
ast_str_append(&out, 0,
"Content-type: text/%s\r\n"
"Cache-Control: no-cache;\r\n"
"Set-Cookie: mansession_id=\"%08x\"; Version=1; Max-Age=%d\r\n"
"Pragma: SuppressEvents\r\n"
"\r\n",
contenttype[format],
session->managerid, httptimeout);
if (format == FORMAT_XML) {
ast_str_append(&out, 0, "<ajax-response>\n");
} else if (format == FORMAT_HTML) {
/*
* When handling AMI-over-HTTP in HTML format, we provide a simple form for
* debugging purposes. This HTML code should not be here, we
* should read from some config file...
*/
#define ROW_FMT "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
#define TEST_STRING \
"<form action=\"manager\">\n\
Action: <select name=\"action\">\n\
<option value=\"\">-----></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"
ast_str_append(&out, 0, "<title>Asterisk™ Manager Interface</title>");
ast_str_append(&out, 0, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n");
ast_str_append(&out, 0, ROW_FMT, "<h1>Manager Tester</h1>");
ast_str_append(&out, 0, ROW_FMT, TEST_STRING);
}
if (s.f != NULL) { /* have temporary output */
char *buf;
size_t l;
/* Ensure buffer is NULL-terminated */
fprintf(s.f, "%c", 0);
fflush(s.f);
if ((l = ftell(s.f))) {
if (MAP_FAILED == (buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, s.fd, 0))) {
ast_log(LOG_WARNING, "mmap failed. Manager output was not processed\n");
} else {
buf[l] = '\0';
if (format == FORMAT_XML || format == FORMAT_HTML) {
xml_translate(&out, buf, params, format);
} else {
ast_str_append(&out, 0, "%s", buf);
}
munmap(buf, l);
}
} else if (format == FORMAT_XML || format == FORMAT_HTML) {
xml_translate(&out, "", params, format);
}
fclose(s.f);
s.f = NULL;
close(s.fd);
s.fd = -1;
}
if (format == FORMAT_XML) {
ast_str_append(&out, 0, "</ajax-response>\n");
} else if (format == FORMAT_HTML)
ast_str_append(&out, 0, "</table></body>\r\n");
ast_mutex_lock(&session->__lock);
/* Reset HTTP timeout. If we're not authenticated, keep it extremely short */
session->sessiontimeout = time(NULL) + ((session->authenticated || httptimeout < 5) ? httptimeout : 5);
if (session->needdestroy) {
if (session->inuse == 1) {
ast_debug(1, "Need destroy, doing it now!\n");
blastaway = 1;
} else {
ast_debug(1, "Need destroy, but can't do it yet!\n");
if (session->waiting_thread != AST_PTHREADT_NULL)
pthread_kill(session->waiting_thread, SIGURG);
session->inuse--;
}
} else
session->inuse--;
ast_mutex_unlock(&session->__lock);
if (blastaway)
destroy_session(session);
generic_callback_out:
if (*status != 200)
return ast_http_error(500, "Server Error", NULL, "Internal Server Error (out of memory)\n");
return out;
}
| int init_manager | ( | void | ) |
Called by Asterisk initialization.
Definition at line 4526 of file manager.c.
References __init_manager().
Referenced by main().
{
return __init_manager(0);
}
| static struct ast_str* 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 * | params, | ||
| struct ast_variable * | headers, | ||
| int * | status, | ||
| char ** | title, | ||
| int * | contentlength | ||
| ) | [static, read] |
Definition at line 4110 of file manager.c.
References FORMAT_HTML, generic_http_callback(), and ast_tcptls_session_instance::remote_address.
{
return generic_http_callback(FORMAT_HTML, &ser->remote_address, uri, method, params, status, title, contentlength);
}
| static struct ast_str* 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 * | params, | ||
| struct ast_variable * | headers, | ||
| int * | status, | ||
| char ** | title, | ||
| int * | contentlength | ||
| ) | [static, read] |
Definition at line 4115 of file manager.c.
References FORMAT_XML, generic_http_callback(), and ast_tcptls_session_instance::remote_address.
{
return generic_http_callback(FORMAT_XML, &ser->remote_address, uri, method, params, status, title, contentlength);
}
| static void purge_old_stuff | ( | void * | data | ) | [static] |
cleanup code called at each iteration of server_root, guaranteed to happen every 5 seconds at most
Definition at line 4158 of file manager.c.
References purge_events(), and purge_sessions().
{
purge_sessions(1);
purge_events();
}
| static struct ast_str* 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 * | params, | ||
| struct ast_variable * | headers, | ||
| int * | status, | ||
| char ** | title, | ||
| int * | contentlength | ||
| ) | [static, read] |
Definition at line 4120 of file manager.c.
References FORMAT_RAW, generic_http_callback(), and ast_tcptls_session_instance::remote_address.
{
return generic_http_callback(FORMAT_RAW, &ser->remote_address, uri, method, params, status, title, contentlength);
}
| int reload_manager | ( | void | ) |
Called by Asterisk module functions and the CLI command.
Definition at line 4531 of file manager.c.
References __init_manager().
Referenced by handle_manager_reload().
{
return __init_manager(1);
}
| static int variable_count_cmp_fn | ( | void * | obj, |
| void * | vstr, | ||
| int | flags | ||
| ) | [static] |
Definition at line 3784 of file manager.c.
References CMP_MATCH, CMP_STOP, str, and variable_count::varname.
Referenced by xml_translate().
{
/* Due to the simplicity of struct variable_count, it makes no difference
* if you pass in objects or strings, the same operation applies. This is
* due to the fact that the hash occurs on the first element, which means
* the address of both the struct and the string are exactly the same. */
struct variable_count *vc = obj;
char *str = vstr;
return !strcmp(vc->varname, str) ? CMP_MATCH | CMP_STOP : 0;
}
| static int variable_count_hash_fn | ( | const void * | vvc, |
| const int | flags | ||
| ) | [static] |
Definition at line 3772 of file manager.c.
References compress_char(), and variable_count::varname.
Referenced by xml_translate().
{
const struct variable_count *vc = vvc;
int res = 0, i;
for (i = 0; i < 5; i++) {
if (vc->varname[i] == '\0')
break;
res += compress_char(vc->varname[i]) << (i * 6);
}
return res;
}
| static void xml_copy_escape | ( | struct ast_str ** | out, |
| const char * | src, | ||
| int | mode | ||
| ) | [static] |
Definition at line 3698 of file manager.c.
References ast_str_append(), buf, and ast_frame::src.
Referenced by xml_translate().
{
/* store in a local buffer to avoid calling ast_str_append too often */
char buf[256];
char *dst = buf;
int space = sizeof(buf);
/* repeat until done and nothing to flush */
for ( ; *src || dst != buf ; src++) {
if (*src == '\0' || space < 10) { /* flush */
*dst++ = '\0';
ast_str_append(out, 0, "%s", buf);
dst = buf;
space = sizeof(buf);
if (*src == '\0')
break;
}
if ( (mode & 2) && !isalnum(*src)) {
*dst++ = '_';
space--;
continue;
}
switch (*src) {
case '<':
strcpy(dst, "<");
dst += 4;
space -= 4;
break;
case '>':
strcpy(dst, ">");
dst += 4;
space -= 4;
break;
case '\"':
strcpy(dst, """);
dst += 6;
space -= 6;
break;
case '\'':
strcpy(dst, "'");
dst += 6;
space -= 6;
break;
case '&':
strcpy(dst, "&");
dst += 5;
space -= 5;
break;
default:
*dst++ = mode ? tolower(*src) : *src;
space--;
}
}
}
| static void xml_translate | ( | struct ast_str ** | out, |
| char * | in, | ||
| struct ast_variable * | 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 3823 of file manager.c.
References ao2_alloc, ao2_container_alloc, ao2_find, ao2_link, ao2_ref, ast_debug, ast_skip_blanks(), ast_str_append(), ast_strlen_zero(), ast_trim_blanks(), variable_count::count, FORMAT_XML, ast_variable::name, ast_variable::next, strsep(), val, ast_variable::value, var, variable_count_cmp_fn(), variable_count_hash_fn(), variable_count::varname, and xml_copy_escape().
Referenced by generic_http_callback().
{
struct ast_variable *v;
const char *dest = NULL;
char *var, *val;
const char *objtype = NULL;
int in_data = 0; /* parsing data */
int inobj = 0;
int xml = (format == FORMAT_XML);
struct variable_count *vc = NULL;
struct ao2_container *vco = NULL;
for (v = vars; v; v = v->next) {
if (!dest && !strcasecmp(v->name, "ajaxdest"))
dest = v->value;
else if (!objtype && !strcasecmp(v->name, "ajaxobjtype"))
objtype = v->value;
}
if (!dest)
dest = "unknown";
if (!objtype)
objtype = "generic";
/* we want to stop when we find an empty line */
while (in && *in) {
val = strsep(&in, "\r\n"); /* mark start and end of line */
if (in && *in == '\n') /* remove trailing \n if any */
in++;
ast_trim_blanks(val);
ast_debug(5, "inobj %d in_data %d line <%s>\n", inobj, in_data, val);
if (ast_strlen_zero(val)) {
if (in_data) { /* close data */
ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
in_data = 0;
}
if (inobj) {
ast_str_append(out, 0, xml ? " /></response>\n" :
"<tr><td colspan=\"2\"><hr></td></tr>\r\n");
inobj = 0;
ao2_ref(vco, -1);
vco = NULL;
}
continue;
}
/* we expect Name: value lines */
if (in_data) {
var = NULL;
} else {
var = strsep(&val, ":");
if (val) { /* found the field name */
val = ast_skip_blanks(val);
ast_trim_blanks(var);
} else { /* field name not found, move to opaque mode */
val = var;
var = "Opaque-data";
}
}
if (!inobj) {
if (xml)
ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype);
else
ast_str_append(out, 0, "<body>\n");
vco = ao2_container_alloc(37, variable_count_hash_fn, variable_count_cmp_fn);
inobj = 1;
}
if (!in_data) { /* build appropriate line start */
ast_str_append(out, 0, xml ? " " : "<tr><td>");
if ((vc = ao2_find(vco, var, 0)))
vc->count++;
else {
/* Create a new entry for this one */
vc = ao2_alloc(sizeof(*vc), NULL);
vc->varname = var;
vc->count = 1;
ao2_link(vco, vc);
}
xml_copy_escape(out, var, xml ? 1 | 2 : 0);
if (vc->count > 1)
ast_str_append(out, 0, "-%d", vc->count);
ao2_ref(vc, -1);
ast_str_append(out, 0, xml ? "='" : "</td><td>");
if (!strcmp(var, "Opaque-data"))
in_data = 1;
}
xml_copy_escape(out, val, 0); /* data field */
if (!in_data)
ast_str_append(out, 0, xml ? "'" : "</td></tr>\n");
else
ast_str_append(out, 0, xml ? "\n" : "<br>\n");
}
if (inobj) {
ast_str_append(out, 0, xml ? " /></response>\n" :
"<tr><td colspan=\"2\"><hr></td></tr>\r\n");
ao2_ref(vco, -1);
}
}
struct ast_tcptls_session_args ami_desc [static] |
Definition at line 4165 of file manager.c.
Referenced by __init_manager().
| struct ast_tls_config ami_tls_cfg |
Definition at line 4164 of file manager.c.
Referenced by __init_manager().
struct ast_tcptls_session_args amis_desc [static] |
Definition at line 4176 of file manager.c.
Referenced by __init_manager().
char* contenttype[] [static] |
{
[FORMAT_RAW] = "plain",
[FORMAT_HTML] = "html",
[FORMAT_XML] = "xml",
}
Definition at line 3608 of file manager.c.
Referenced by generic_http_callback().
| struct ast_http_uri manageruri |
Definition at line 4134 of file manager.c.
Referenced by __init_manager().
| struct ast_http_uri managerxmluri |
Definition at line 4143 of file manager.c.
Referenced by __init_manager().
| struct ast_http_uri rawmanuri |
Definition at line 4125 of file manager.c.
Referenced by __init_manager().
int registered = 0 [static] |
Definition at line 4152 of file manager.c.
Referenced by __init_manager().
int webregged = 0 [static] |
Definition at line 4153 of file manager.c.
Referenced by __init_manager().
| char* words[AST_MAX_CMD_LEN] |
Definition at line 160 of file manager.c.
Referenced by check_blacklist().