#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"
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 |
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 | 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 | NEW_EVENT(m) (AST_LIST_NEXT(m->session->last_ev, eq_next)) |
#define | ROW_FMT "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n" |
#define | TEST_STRING "<form action=\"manager\">action: <input name=\"action\"> cmd <input name=\"command\"><br> \ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br> \ <input type=\"submit\"></form>" |
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 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_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 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 manager command with the manager interface. | |
void | ast_manager_register_hook (struct manager_custom_hook *hook) |
Add a custom hook to be called when an event is fired. | |
static int | ast_manager_register_struct (struct manager_action *act) |
int | ast_manager_unregister (char *action) |
Unregister a registered manager command. | |
void | ast_manager_unregister_hook (struct manager_custom_hook *hook) |
Delete a custom hook to be called when an event is fired. | |
void | astman_append (struct mansession *s, const char *fmt,...) |
const char * | astman_get_header (const struct message *m, char *var) |
Get header from mananger transaction. | |
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 () |
Check if AMI is enabled. | |
static int | check_manager_session_inuse (const char *name) |
int | check_webmanager_enabled () |
Check if AMI/HTTP is enabled. | |
static int | 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 *requestor, const char *uri, 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 char *uri, struct ast_variable *params, 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 char *uri, struct ast_variable *params, 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 char *uri, struct ast_variable *params, int *status, char **title, int *contentlength) |
static void | ref_event (struct eventqent *e) |
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 struct eventqent * | unref_event (struct eventqent *e) |
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 int | allowmultiplelogin = 1 |
static struct server_args | ami_desc |
ast_tls_config | ami_tls_cfg |
static struct server_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 | block_sockets |
static struct ast_cli_entry | cli_manager [] |
struct { | |
char * words [AST_MAX_CMD_LEN] | |
} | command_blacklist [] |
static char * | contenttype [] |
static int | displayconnects = 1 |
static int | httptimeout = 60 |
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 , } |
ast_http_uri | manageruri |
ast_http_uri | managerxmluri |
static char | mandescr_command [] |
static char | mandescr_coresettings [] |
static char | mandescr_coreshowchannels [] |
static char | mandescr_corestatus [] |
static char | mandescr_createconfig [] |
static char | mandescr_events [] |
static char | mandescr_extensionstate [] |
static char | mandescr_getconfig [] |
static char | mandescr_getconfigjson [] |
static char | mandescr_getvar [] |
static char | mandescr_hangup [] |
static char | mandescr_listcategories [] |
static char | mandescr_listcommands [] |
static char | mandescr_logoff [] |
static char | mandescr_mailboxcount [] |
static char | mandescr_mailboxstatus [] |
Help text for manager command mailboxstatus. | |
static char | mandescr_modulecheck [] |
static char | mandescr_moduleload [] |
static char | mandescr_originate [] |
static char | mandescr_ping [] |
Manager PING. | |
static char | mandescr_redirect [] |
static char | mandescr_reload [] |
static char | mandescr_sendtext [] |
static char | mandescr_setvar [] |
static char | mandescr_timeout [] |
static char | mandescr_updateconfig [] |
static char | mandescr_userevent [] |
static char | mandescr_waitevent [] |
Manager WAITEVENT. | |
static int | num_sessions |
static struct permalias | perms [] |
ast_http_uri | rawmanuri |
static int | registered = 0 |
static int | timestampevents |
static struct ast_threadstorage | userevent_buf = { .once = PTHREAD_ONCE_INIT, .key_init = __init_userevent_buf , .custom_init = NULL , } |
static int | webmanager_enabled = 0 |
static int | webregged = 0 |
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" |
#define TEST_STRING "<form action=\"manager\">action: <input name=\"action\"> cmd <input name=\"command\"><br> \ user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br> \ <input type=\"submit\"></form>" |
enum output_format |
END Doxygen group
Definition at line 3246 of file manager.c.
03246 { 03247 FORMAT_RAW, 03248 FORMAT_HTML, 03249 FORMAT_XML, 03250 };
static int __init_manager | ( | int | reload | ) | [static] |
Definition at line 3798 of file manager.c.
References 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(), AST_CERTFILE, ast_cli_register_multiple(), ast_config_load, ast_extension_state_add(), ast_free, ast_gethostbyname(), ast_log(), ast_manager_register, ast_manager_register2(), ast_strdup, ast_true(), ast_variable_browse(), ast_tls_config::certfile, ast_tls_config::cipher, cli_manager, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MANAGER_PORT, 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, hp, inet_aton(), LOG_NOTICE, LOG_WARNING, manager_modulecheck(), manager_moduleload(), manager_state_cb(), mandescr_createconfig, mandescr_getconfig, mandescr_getconfigjson, mandescr_listcategories, mandescr_ping, mandescr_updateconfig, mandescr_waitevent, server_args::sin, and var.
Referenced by init_manager(), and reload_manager().
03799 { 03800 struct ast_config *ucfg = NULL, *cfg = NULL; 03801 const char *val; 03802 char *cat = NULL; 03803 int newhttptimeout = 60; 03804 int have_sslbindaddr = 0; 03805 struct hostent *hp; 03806 struct ast_hostent ahp; 03807 struct ast_manager_user *user = NULL; 03808 struct ast_variable *var; 03809 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 03810 03811 manager_enabled = 0; 03812 03813 if (!registered) { 03814 /* Register default actions */ 03815 ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping); 03816 ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events); 03817 ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff); 03818 ast_manager_register2("Login", 0, action_login, "Login Manager", NULL); 03819 ast_manager_register2("Challenge", 0, action_challenge, "Generate Challenge for MD5 Auth", NULL); 03820 ast_manager_register2("Hangup", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup); 03821 ast_manager_register("Status", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_status, "Lists channel status" ); 03822 ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar ); 03823 ast_manager_register2("Getvar", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_getvar, "Gets a Channel Variable", mandescr_getvar ); 03824 ast_manager_register2("GetConfig", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig); 03825 ast_manager_register2("GetConfigJSON", EVENT_FLAG_SYSTEM | EVENT_FLAG_CONFIG, action_getconfigjson, "Retrieve configuration (JSON format)", mandescr_getconfigjson); 03826 ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig); 03827 ast_manager_register2("CreateConfig", EVENT_FLAG_CONFIG, action_createconfig, "Creates an empty file in the configuration directory", mandescr_createconfig); 03828 ast_manager_register2("ListCategories", EVENT_FLAG_CONFIG, action_listcategories, "List categories in configuration file", mandescr_listcategories); 03829 ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect ); 03830 ast_manager_register2("Originate", EVENT_FLAG_ORIGINATE, action_originate, "Originate Call", mandescr_originate); 03831 ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command ); 03832 ast_manager_register2("ExtensionState", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_extensionstate, "Check Extension Status", mandescr_extensionstate ); 03833 ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_SYSTEM | EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout ); 03834 ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus ); 03835 ast_manager_register2("MailboxCount", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount ); 03836 ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands); 03837 ast_manager_register2("SendText", EVENT_FLAG_CALL, action_sendtext, "Send text message to channel", mandescr_sendtext); 03838 ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent); 03839 ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent); 03840 ast_manager_register2("CoreSettings", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coresettings, "Show PBX core settings (version etc)", mandescr_coresettings); 03841 ast_manager_register2("CoreStatus", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_corestatus, "Show PBX core status variables", mandescr_corestatus); 03842 ast_manager_register2("Reload", EVENT_FLAG_CONFIG | EVENT_FLAG_SYSTEM, action_reload, "Send a reload event", mandescr_reload); 03843 ast_manager_register2("CoreShowChannels", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, action_coreshowchannels, "List currently active channels", mandescr_coreshowchannels); 03844 ast_manager_register2("ModuleLoad", EVENT_FLAG_SYSTEM, manager_moduleload, "Module management", mandescr_moduleload); 03845 ast_manager_register2("ModuleCheck", EVENT_FLAG_SYSTEM, manager_modulecheck, "Check if module is loaded", mandescr_modulecheck); 03846 03847 ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry)); 03848 ast_extension_state_add(NULL, NULL, manager_state_cb, NULL); 03849 registered = 1; 03850 /* Append placeholder event so master_eventq never runs dry */ 03851 append_event("Event: Placeholder\r\n\r\n", 0); 03852 } 03853 if ((cfg = ast_config_load("manager.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) 03854 return 0; 03855 03856 displayconnects = 1; 03857 if (!cfg) { 03858 ast_log(LOG_NOTICE, "Unable to open AMI configuration manager.conf. Asterisk management interface (AMI) disabled.\n"); 03859 return 0; 03860 } 03861 03862 /* default values */ 03863 memset(&ami_desc.sin, 0, sizeof(struct sockaddr_in)); 03864 memset(&amis_desc.sin, 0, sizeof(amis_desc.sin)); 03865 amis_desc.sin.sin_port = htons(5039); 03866 ami_desc.sin.sin_port = htons(DEFAULT_MANAGER_PORT); 03867 03868 ami_tls_cfg.enabled = 0; 03869 if (ami_tls_cfg.certfile) 03870 ast_free(ami_tls_cfg.certfile); 03871 ami_tls_cfg.certfile = ast_strdup(AST_CERTFILE); 03872 if (ami_tls_cfg.cipher) 03873 ast_free(ami_tls_cfg.cipher); 03874 ami_tls_cfg.cipher = ast_strdup(""); 03875 03876 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) { 03877 val = var->value; 03878 if (!strcasecmp(var->name, "sslenable")) 03879 ami_tls_cfg.enabled = ast_true(val); 03880 else if (!strcasecmp(var->name, "sslbindport")) 03881 amis_desc.sin.sin_port = htons(atoi(val)); 03882 else if (!strcasecmp(var->name, "sslbindaddr")) { 03883 if ((hp = ast_gethostbyname(val, &ahp))) { 03884 memcpy(&amis_desc.sin.sin_addr, hp->h_addr, sizeof(amis_desc.sin.sin_addr)); 03885 have_sslbindaddr = 1; 03886 } else { 03887 ast_log(LOG_WARNING, "Invalid bind address '%s'\n", val); 03888 } 03889 } else if (!strcasecmp(var->name, "sslcert")) { 03890 ast_free(ami_tls_cfg.certfile); 03891 ami_tls_cfg.certfile = ast_strdup(val); 03892 } else if (!strcasecmp(var->name, "sslcipher")) { 03893 ast_free(ami_tls_cfg.cipher); 03894 ami_tls_cfg.cipher = ast_strdup(val); 03895 } else if (!strcasecmp(var->name, "enabled")) { 03896 manager_enabled = ast_true(val); 03897 } else if (!strcasecmp(var->name, "block-sockets")) { 03898 block_sockets = ast_true(val); 03899 } else if (!strcasecmp(var->name, "webenabled")) { 03900 webmanager_enabled = ast_true(val); 03901 } else if (!strcasecmp(var->name, "port")) { 03902 ami_desc.sin.sin_port = htons(atoi(val)); 03903 } else if (!strcasecmp(var->name, "bindaddr")) { 03904 if (!inet_aton(val, &ami_desc.sin.sin_addr)) { 03905 ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val); 03906 memset(&ami_desc.sin.sin_addr, 0, sizeof(ami_desc.sin.sin_addr)); 03907 } 03908 } else if (!strcasecmp(var->name, "allowmultiplelogin")) { 03909 allowmultiplelogin = ast_true(val); 03910 } else if (!strcasecmp(var->name, "displayconnects")) { 03911 displayconnects = ast_true(val); 03912 } else if (!strcasecmp(var->name, "timestampevents")) { 03913 timestampevents = ast_true(val); 03914 } else if (!strcasecmp(var->name, "debug")) { 03915 manager_debug = ast_true(val); 03916 } else if (!strcasecmp(var->name, "httptimeout")) { 03917 newhttptimeout = atoi(val); 03918 } else { 03919 ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n", 03920 var->name, val); 03921 } 03922 } 03923 03924 if (manager_enabled) 03925 ami_desc.sin.sin_family = AF_INET; 03926 if (!have_sslbindaddr) 03927 amis_desc.sin.sin_addr = ami_desc.sin.sin_addr; 03928 if (ami_tls_cfg.enabled) 03929 amis_desc.sin.sin_family = AF_INET; 03930 03931 03932 AST_RWLIST_WRLOCK(&users); 03933 03934 /* First, get users from users.conf */ 03935 ucfg = ast_config_load("users.conf", config_flags); 03936 if (ucfg && (ucfg != CONFIG_STATUS_FILEUNCHANGED)) { 03937 const char *hasmanager; 03938 int genhasmanager = ast_true(ast_variable_retrieve(ucfg, "general", "hasmanager")); 03939 03940 while ((cat = ast_category_browse(ucfg, cat))) { 03941 if (!strcasecmp(cat, "general")) 03942 continue; 03943 03944 hasmanager = ast_variable_retrieve(ucfg, cat, "hasmanager"); 03945 if ((!hasmanager && genhasmanager) || ast_true(hasmanager)) { 03946 const char *user_secret = ast_variable_retrieve(ucfg, cat, "secret"); 03947 const char *user_read = ast_variable_retrieve(ucfg, cat, "read"); 03948 const char *user_write = ast_variable_retrieve(ucfg, cat, "write"); 03949 const char *user_displayconnects = ast_variable_retrieve(ucfg, cat, "displayconnects"); 03950 const char *user_writetimeout = ast_variable_retrieve(ucfg, cat, "writetimeout"); 03951 03952 /* Look for an existing entry, 03953 * if none found - create one and add it to the list 03954 */ 03955 if (!(user = get_manager_by_name_locked(cat))) { 03956 if (!(user = ast_calloc(1, sizeof(*user)))) 03957 break; 03958 03959 /* Copy name over */ 03960 ast_copy_string(user->username, cat, sizeof(user->username)); 03961 /* Insert into list */ 03962 AST_LIST_INSERT_TAIL(&users, user, list); 03963 user->ha = NULL; 03964 user->keep = 1; 03965 user->readperm = -1; 03966 user->writeperm = -1; 03967 /* Default displayconnect from [general] */ 03968 user->displayconnects = displayconnects; 03969 user->writetimeout = 100; 03970 } 03971 03972 if (!user_secret) 03973 user_secret = ast_variable_retrieve(ucfg, "general", "secret"); 03974 if (!user_read) 03975 user_read = ast_variable_retrieve(ucfg, "general", "read"); 03976 if (!user_write) 03977 user_write = ast_variable_retrieve(ucfg, "general", "write"); 03978 if (!user_displayconnects) 03979 user_displayconnects = ast_variable_retrieve(ucfg, "general", "displayconnects"); 03980 if (!user_writetimeout) 03981 user_writetimeout = ast_variable_retrieve(ucfg, "general", "writetimeout"); 03982 03983 if (!ast_strlen_zero(user_secret)) { 03984 if (user->secret) 03985 ast_free(user->secret); 03986 user->secret = ast_strdup(user_secret); 03987 } 03988 03989 if (user_read) 03990 user->readperm = get_perm(user_read); 03991 if (user_write) 03992 user->writeperm = get_perm(user_write); 03993 if (user_displayconnects) 03994 user->displayconnects = ast_true(user_displayconnects); 03995 03996 if (user_writetimeout) { 03997 int val = atoi(user_writetimeout); 03998 if (val < 100) 03999 ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at users.conf line %d\n", var->value, var->lineno); 04000 else 04001 user->writetimeout = val; 04002 } 04003 } 04004 } 04005 ast_config_destroy(ucfg); 04006 } 04007 04008 /* cat is NULL here in any case */ 04009 04010 while ((cat = ast_category_browse(cfg, cat))) { 04011 struct ast_ha *oldha; 04012 04013 if (!strcasecmp(cat, "general")) 04014 continue; 04015 04016 /* Look for an existing entry, if none found - create one and add it to the list */ 04017 if (!(user = get_manager_by_name_locked(cat))) { 04018 if (!(user = ast_calloc(1, sizeof(*user)))) 04019 break; 04020 /* Copy name over */ 04021 ast_copy_string(user->username, cat, sizeof(user->username)); 04022 04023 user->ha = NULL; 04024 user->readperm = 0; 04025 user->writeperm = 0; 04026 /* Default displayconnect from [general] */ 04027 user->displayconnects = displayconnects; 04028 user->writetimeout = 100; 04029 04030 /* Insert into list */ 04031 AST_RWLIST_INSERT_TAIL(&users, user, list); 04032 } 04033 04034 /* Make sure we keep this user and don't destroy it during cleanup */ 04035 user->keep = 1; 04036 oldha = user->ha; 04037 user->ha = NULL; 04038 04039 var = ast_variable_browse(cfg, cat); 04040 for (; var; var = var->next) { 04041 if (!strcasecmp(var->name, "secret")) { 04042 if (user->secret) 04043 ast_free(user->secret); 04044 user->secret = ast_strdup(var->value); 04045 } else if (!strcasecmp(var->name, "deny") || 04046 !strcasecmp(var->name, "permit")) { 04047 user->ha = ast_append_ha(var->name, var->value, user->ha, NULL); 04048 } else if (!strcasecmp(var->name, "read") ) { 04049 user->readperm = get_perm(var->value); 04050 } else if (!strcasecmp(var->name, "write") ) { 04051 user->writeperm = get_perm(var->value); 04052 } else if (!strcasecmp(var->name, "displayconnects") ) { 04053 user->displayconnects = ast_true(var->value); 04054 } else if (!strcasecmp(var->name, "writetimeout")) { 04055 int val = atoi(var->value); 04056 if (val < 100) 04057 ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", var->value, var->lineno); 04058 else 04059 user->writetimeout = val; 04060 } else 04061 ast_debug(1, "%s is an unknown option.\n", var->name); 04062 } 04063 ast_free_ha(oldha); 04064 } 04065 ast_config_destroy(cfg); 04066 04067 /* Perform cleanup - essentially prune out old users that no longer exist */ 04068 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&users, user, list) { 04069 if (user->keep) { /* valid record. clear flag for the next round */ 04070 user->keep = 0; 04071 continue; 04072 } 04073 /* We do not need to keep this user so take them out of the list */ 04074 AST_RWLIST_REMOVE_CURRENT(list); 04075 /* Free their memory now */ 04076 if (user->secret) 04077 ast_free(user->secret); 04078 ast_free_ha(user->ha); 04079 ast_free(user); 04080 } 04081 AST_RWLIST_TRAVERSE_SAFE_END; 04082 04083 AST_RWLIST_UNLOCK(&users); 04084 04085 if (webmanager_enabled && manager_enabled) { 04086 if (!webregged) { 04087 ast_http_uri_link(&rawmanuri); 04088 ast_http_uri_link(&manageruri); 04089 ast_http_uri_link(&managerxmluri); 04090 webregged = 1; 04091 } 04092 } else { 04093 if (webregged) { 04094 ast_http_uri_unlink(&rawmanuri); 04095 ast_http_uri_unlink(&manageruri); 04096 ast_http_uri_unlink(&managerxmluri); 04097 webregged = 0; 04098 } 04099 } 04100 04101 if (newhttptimeout > 0) 04102 httptimeout = newhttptimeout; 04103 04104 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Module: Manager\r\nStatus: %s\r\nMessage: Manager reload Requested\r\n", manager_enabled ? "Enabled" : "Disabled"); 04105 04106 ast_tcptls_server_start(&ami_desc); 04107 if (ast_ssl_setup(amis_desc.tls_cfg)) 04108 ast_tcptls_server_start(&amis_desc); 04109 return 0; 04110 }
int astman_is_authed | ( | uint32_t | ident | ) |
Determinie if a manager session ident is authenticated.
Definition at line 3284 of file manager.c.
References mansession_session::__lock, ast_mutex_unlock(), mansession_session::authenticated, and find_session().
Referenced by static_callback().
03285 { 03286 int authed; 03287 struct mansession_session *session; 03288 03289 if (!(session = find_session(ident, 0))) 03290 return 0; 03291 03292 authed = (session->authenticated != 0); 03293 03294 ast_mutex_unlock(&session->__lock); 03295 03296 return authed; 03297 }
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 3299 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.
03300 { 03301 int result = 0; 03302 struct mansession_session *session; 03303 03304 AST_LIST_LOCK(&sessions); 03305 AST_LIST_TRAVERSE(&sessions, session, list) { 03306 ast_mutex_lock(&session->__lock); 03307 if ((session->managerid == ident) && (session->readperm & perm)) { 03308 result = 1; 03309 ast_mutex_unlock(&session->__lock); 03310 break; 03311 } 03312 ast_mutex_unlock(&session->__lock); 03313 } 03314 AST_LIST_UNLOCK(&sessions); 03315 return result; 03316 }
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 3318 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.
03319 { 03320 int result = 0; 03321 struct mansession_session *session; 03322 03323 AST_LIST_LOCK(&sessions); 03324 AST_LIST_TRAVERSE(&sessions, session, list) { 03325 ast_mutex_lock(&session->__lock); 03326 if ((session->managerid == ident) && (session->writeperm & perm)) { 03327 result = 1; 03328 ast_mutex_unlock(&session->__lock); 03329 break; 03330 } 03331 ast_mutex_unlock(&session->__lock); 03332 } 03333 AST_LIST_UNLOCK(&sessions); 03334 return result; 03335 }
static int compress_char | ( | char | c | ) | [static] |
Definition at line 3403 of file manager.c.
Referenced by member_hash_fn(), and variable_count_hash_fn().
03404 { 03405 c &= 0x7f; 03406 if (c < 32) 03407 return 0; 03408 else if (c >= 'a' && c <= 'z') 03409 return c - 64; 03410 else if (c > 'z') 03411 return '_'; 03412 else 03413 return c - 32; 03414 }
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 3263 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().
03264 { 03265 struct mansession_session *session; 03266 03267 if (ident == 0) 03268 return NULL; 03269 03270 AST_LIST_LOCK(&sessions); 03271 AST_LIST_TRAVERSE(&sessions, session, list) { 03272 ast_mutex_lock(&session->__lock); 03273 if (session->managerid == ident && !session->needdestroy) { 03274 ast_atomic_fetchadd_int(&session->inuse, incinuse ? 1 : 0); 03275 break; 03276 } 03277 ast_mutex_unlock(&session->__lock); 03278 } 03279 AST_LIST_UNLOCK(&sessions); 03280 03281 return session; 03282 }
static struct ast_str* generic_http_callback | ( | enum output_format | format, | |
struct sockaddr_in * | requestor, | |||
const char * | uri, | |||
struct ast_variable * | params, | |||
int * | status, | |||
char ** | title, | |||
int * | contentlength | |||
) | [static] |
Definition at line 3567 of file manager.c.
References ast_variable::name, ast_variable::next, s, and ast_variable::value.
Referenced by manager_http_callback(), mxml_http_callback(), and rawman_http_callback().
03571 { 03572 struct mansession s = {.session = NULL, }; 03573 struct mansession_session *session = NULL; 03574 uint32_t ident = 0; 03575 int blastaway = 0; 03576 struct ast_variable *v; 03577 char template[] = "/tmp/ast-http-XXXXXX"; /* template for temporary file */ 03578 struct ast_str *out = NULL; 03579 struct message m = { 0 }; 03580 unsigned int x; 03581 size_t hdrlen; 03582 03583 for (v = params; v; v = v->next) { 03584 if (!strcasecmp(v->name, "mansession_id")) { 03585 sscanf(v->value, "%x", &ident); 03586 break; 03587 } 03588 } 03589 03590 if (!(session = find_session(ident, 1))) { 03591 /* Create new session. 03592 * While it is not in the list we don't need any locking 03593 */ 03594 if (!(session = ast_calloc(1, sizeof(*session)))) { 03595 *status = 500; 03596 goto generic_callback_out; 03597 } 03598 session->sin = *requestor; 03599 session->fd = -1; 03600 session->waiting_thread = AST_PTHREADT_NULL; 03601 session->send_events = 0; 03602 ast_mutex_init(&session->__lock); 03603 ast_mutex_lock(&session->__lock); 03604 session->inuse = 1; 03605 /*!\note There is approximately a 1 in 1.8E19 chance that the following 03606 * calculation will produce 0, which is an invalid ID, but due to the 03607 * properties of the rand() function (and the constantcy of s), that 03608 * won't happen twice in a row. 03609 */ 03610 while ((session->managerid = ast_random() ^ (unsigned long) session) == 0); 03611 session->last_ev = grab_last(); 03612 AST_LIST_LOCK(&sessions); 03613 AST_LIST_INSERT_HEAD(&sessions, session, list); 03614 ast_atomic_fetchadd_int(&num_sessions, 1); 03615 AST_LIST_UNLOCK(&sessions); 03616 } 03617 03618 s.session = session; 03619 03620 ast_mutex_unlock(&session->__lock); 03621 03622 if (!(out = ast_str_create(1024))) { 03623 *status = 500; 03624 goto generic_callback_out; 03625 } 03626 03627 s.fd = mkstemp(template); /* create a temporary file for command output */ 03628 unlink(template); 03629 s.f = fdopen(s.fd, "w+"); 03630 03631 for (x = 0, v = params; v && (x < AST_MAX_MANHEADERS); x++, v = v->next) { 03632 hdrlen = strlen(v->name) + strlen(v->value) + 3; 03633 m.headers[m.hdrcount] = alloca(hdrlen); 03634 snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value); 03635 m.hdrcount = x + 1; 03636 } 03637 03638 if (process_message(&s, &m)) { 03639 if (session->authenticated) { 03640 if (manager_displayconnects(session)) 03641 ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 03642 ast_log(LOG_EVENT, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 03643 } else { 03644 if (displayconnects) 03645 ast_verb(2, "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr)); 03646 ast_log(LOG_EVENT, "HTTP Failed attempt from %s\n", ast_inet_ntoa(session->sin.sin_addr)); 03647 } 03648 session->needdestroy = 1; 03649 } 03650 03651 ast_str_append(&out, 0, 03652 "Content-type: text/%s\r\n" 03653 "Cache-Control: no-cache;\r\n" 03654 "Set-Cookie: mansession_id=\"%08x\"; Version=\"1\"; Max-Age=%d\r\n" 03655 "\r\n", 03656 contenttype[format], 03657 session->managerid, httptimeout); 03658 03659 if (format == FORMAT_XML) { 03660 ast_str_append(&out, 0, "<ajax-response>\n"); 03661 } else if (format == FORMAT_HTML) { 03662 03663 #define ROW_FMT "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n" 03664 #define TEST_STRING \ 03665 "<form action=\"manager\">action: <input name=\"action\"> cmd <input name=\"command\"><br> \ 03666 user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br> \ 03667 <input type=\"submit\"></form>" 03668 03669 ast_str_append(&out, 0, "<title>Asterisk™ Manager Interface</title>"); 03670 ast_str_append(&out, 0, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n"); 03671 ast_str_append(&out, 0, ROW_FMT, "<h1>Manager Tester</h1>"); 03672 ast_str_append(&out, 0, ROW_FMT, TEST_STRING); 03673 } 03674 03675 if (s.f != NULL) { /* have temporary output */ 03676 char *buf; 03677 size_t l = ftell(s.f); 03678 03679 if (l) { 03680 if (MAP_FAILED == (buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, s.fd, 0))) { 03681 ast_log(LOG_WARNING, "mmap failed. Manager output was not processed\n"); 03682 } else { 03683 if (format == FORMAT_XML || format == FORMAT_HTML) 03684 xml_translate(&out, buf, params, format); 03685 else 03686 ast_str_append(&out, 0, "%s", buf); 03687 munmap(buf, l); 03688 } 03689 } else if (format == FORMAT_XML || format == FORMAT_HTML) { 03690 xml_translate(&out, "", params, format); 03691 } 03692 fclose(s.f); 03693 s.f = NULL; 03694 s.fd = -1; 03695 } 03696 03697 if (format == FORMAT_XML) { 03698 ast_str_append(&out, 0, "</ajax-response>\n"); 03699 } else if (format == FORMAT_HTML) 03700 ast_str_append(&out, 0, "</table></body>\r\n"); 03701 03702 ast_mutex_lock(&session->__lock); 03703 /* Reset HTTP timeout. If we're not authenticated, keep it extremely short */ 03704 session->sessiontimeout = time(NULL) + ((session->authenticated || httptimeout < 5) ? httptimeout : 5); 03705 03706 if (session->needdestroy) { 03707 if (session->inuse == 1) { 03708 ast_debug(1, "Need destroy, doing it now!\n"); 03709 blastaway = 1; 03710 } else { 03711 ast_debug(1, "Need destroy, but can't do it yet!\n"); 03712 if (session->waiting_thread != AST_PTHREADT_NULL) 03713 pthread_kill(session->waiting_thread, SIGURG); 03714 session->inuse--; 03715 } 03716 } else 03717 session->inuse--; 03718 ast_mutex_unlock(&session->__lock); 03719 03720 if (blastaway) 03721 destroy_session(session); 03722 generic_callback_out: 03723 if (*status != 200) 03724 return ast_http_error(500, "Server Error", NULL, "Internal Server Error (out of memory)\n"); 03725 return out; 03726 }
int init_manager | ( | void | ) |
Called by Asterisk initialization.
Definition at line 4112 of file manager.c.
References __init_manager().
Referenced by main().
04113 { 04114 return __init_manager(0); 04115 }
static struct ast_str* manager_http_callback | ( | struct ast_tcptls_session_instance * | ser, | |
const char * | uri, | |||
struct ast_variable * | params, | |||
int * | status, | |||
char ** | title, | |||
int * | contentlength | |||
) | [static] |
Definition at line 3728 of file manager.c.
References FORMAT_HTML, generic_http_callback(), and ast_tcptls_session_instance::requestor.
03729 { 03730 return generic_http_callback(FORMAT_HTML, &ser->requestor, uri, params, status, title, contentlength); 03731 }
static struct ast_str* mxml_http_callback | ( | struct ast_tcptls_session_instance * | ser, | |
const char * | uri, | |||
struct ast_variable * | params, | |||
int * | status, | |||
char ** | title, | |||
int * | contentlength | |||
) | [static] |
Definition at line 3733 of file manager.c.
References FORMAT_XML, generic_http_callback(), and ast_tcptls_session_instance::requestor.
03734 { 03735 return generic_http_callback(FORMAT_XML, &ser->requestor, uri, params, status, title, contentlength); 03736 }
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 3770 of file manager.c.
References purge_events(), and purge_sessions().
03771 { 03772 purge_sessions(1); 03773 purge_events(); 03774 }
static struct ast_str* rawman_http_callback | ( | struct ast_tcptls_session_instance * | ser, | |
const char * | uri, | |||
struct ast_variable * | params, | |||
int * | status, | |||
char ** | title, | |||
int * | contentlength | |||
) | [static] |
Definition at line 3738 of file manager.c.
References FORMAT_RAW, generic_http_callback(), and ast_tcptls_session_instance::requestor.
03739 { 03740 return generic_http_callback(FORMAT_RAW, &ser->requestor, uri, params, status, title, contentlength); 03741 }
int reload_manager | ( | void | ) |
Called by Asterisk module functions and the CLI command.
Definition at line 4117 of file manager.c.
References __init_manager().
Referenced by handle_manager_reload().
04118 { 04119 return __init_manager(1); 04120 }
static int variable_count_cmp_fn | ( | void * | obj, | |
void * | vstr, | |||
int | flags | |||
) | [static] |
Definition at line 3428 of file manager.c.
References CMP_MATCH, str, and variable_count::varname.
Referenced by xml_translate().
03429 { 03430 /* Due to the simplicity of struct variable_count, it makes no difference 03431 * if you pass in objects or strings, the same operation applies. This is 03432 * due to the fact that the hash occurs on the first element, which means 03433 * the address of both the struct and the string are exactly the same. */ 03434 struct variable_count *vc = obj; 03435 char *str = vstr; 03436 return !strcmp(vc->varname, str) ? CMP_MATCH : 0; 03437 }
static int variable_count_hash_fn | ( | const void * | vvc, | |
const int | flags | |||
) | [static] |
Definition at line 3416 of file manager.c.
References compress_char(), and variable_count::varname.
Referenced by xml_translate().
03417 { 03418 const struct variable_count *vc = vvc; 03419 int res = 0, i; 03420 for (i = 0; i < 5; i++) { 03421 if (vc->varname[i] == '\0') 03422 break; 03423 res += compress_char(vc->varname[i]) << (i * 6); 03424 } 03425 return res; 03426 }
static void xml_copy_escape | ( | struct ast_str ** | out, | |
const char * | src, | |||
int | mode | |||
) | [static] |
Definition at line 3342 of file manager.c.
References ast_str_append(), and buf.
Referenced by xml_translate().
03343 { 03344 /* store in a local buffer to avoid calling ast_str_append too often */ 03345 char buf[256]; 03346 char *dst = buf; 03347 int space = sizeof(buf); 03348 /* repeat until done and nothing to flush */ 03349 for ( ; *src || dst != buf ; src++) { 03350 if (*src == '\0' || space < 10) { /* flush */ 03351 *dst++ = '\0'; 03352 ast_str_append(out, 0, "%s", buf); 03353 dst = buf; 03354 space = sizeof(buf); 03355 if (*src == '\0') 03356 break; 03357 } 03358 03359 if ( (mode & 2) && !isalnum(*src)) { 03360 *dst++ = '_'; 03361 space--; 03362 continue; 03363 } 03364 switch (*src) { 03365 case '<': 03366 strcpy(dst, "<"); 03367 dst += 4; 03368 space -= 4; 03369 break; 03370 case '>': 03371 strcpy(dst, ">"); 03372 dst += 4; 03373 space -= 4; 03374 break; 03375 case '\"': 03376 strcpy(dst, """); 03377 dst += 6; 03378 space -= 6; 03379 break; 03380 case '\'': 03381 strcpy(dst, "'"); 03382 dst += 6; 03383 space -= 6; 03384 break; 03385 case '&': 03386 strcpy(dst, "&"); 03387 dst += 5; 03388 space -= 5; 03389 break; 03390 03391 default: 03392 *dst++ = mode ? tolower(*src) : *src; 03393 space--; 03394 } 03395 } 03396 }
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 3467 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(), ast_variable::value, var, variable_count_cmp_fn(), variable_count_hash_fn(), and xml_copy_escape().
03468 { 03469 struct ast_variable *v; 03470 const char *dest = NULL; 03471 char *var, *val; 03472 const char *objtype = NULL; 03473 int in_data = 0; /* parsing data */ 03474 int inobj = 0; 03475 int xml = (format == FORMAT_XML); 03476 struct variable_count *vc = NULL; 03477 struct ao2_container *vco = NULL; 03478 03479 for (v = vars; v; v = v->next) { 03480 if (!dest && !strcasecmp(v->name, "ajaxdest")) 03481 dest = v->value; 03482 else if (!objtype && !strcasecmp(v->name, "ajaxobjtype")) 03483 objtype = v->value; 03484 } 03485 if (!dest) 03486 dest = "unknown"; 03487 if (!objtype) 03488 objtype = "generic"; 03489 03490 /* we want to stop when we find an empty line */ 03491 while (in && *in) { 03492 val = strsep(&in, "\r\n"); /* mark start and end of line */ 03493 if (in && *in == '\n') /* remove trailing \n if any */ 03494 in++; 03495 ast_trim_blanks(val); 03496 ast_debug(5, "inobj %d in_data %d line <%s>\n", inobj, in_data, val); 03497 if (ast_strlen_zero(val)) { 03498 if (in_data) { /* close data */ 03499 ast_str_append(out, 0, xml ? "'" : "</td></tr>\n"); 03500 in_data = 0; 03501 } 03502 if (inobj) { 03503 ast_str_append(out, 0, xml ? " /></response>\n" : 03504 "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 03505 inobj = 0; 03506 ao2_ref(vco, -1); 03507 vco = NULL; 03508 } 03509 continue; 03510 } 03511 03512 /* we expect Name: value lines */ 03513 if (in_data) { 03514 var = NULL; 03515 } else { 03516 var = strsep(&val, ":"); 03517 if (val) { /* found the field name */ 03518 val = ast_skip_blanks(val); 03519 ast_trim_blanks(var); 03520 } else { /* field name not found, move to opaque mode */ 03521 val = var; 03522 var = "Opaque-data"; 03523 } 03524 } 03525 03526 if (!inobj) { 03527 if (xml) 03528 ast_str_append(out, 0, "<response type='object' id='%s'><%s", dest, objtype); 03529 else 03530 ast_str_append(out, 0, "<body>\n"); 03531 vco = ao2_container_alloc(37, variable_count_hash_fn, variable_count_cmp_fn); 03532 inobj = 1; 03533 } 03534 03535 if (!in_data) { /* build appropriate line start */ 03536 ast_str_append(out, 0, xml ? " " : "<tr><td>"); 03537 if ((vc = ao2_find(vco, var, 0))) 03538 vc->count++; 03539 else { 03540 /* Create a new entry for this one */ 03541 vc = ao2_alloc(sizeof(*vc), NULL); 03542 vc->varname = var; 03543 vc->count = 1; 03544 ao2_link(vco, vc); 03545 } 03546 xml_copy_escape(out, var, xml ? 1 | 2 : 0); 03547 if (vc->count > 1) 03548 ast_str_append(out, 0, "-%d", vc->count); 03549 ao2_ref(vc, -1); 03550 ast_str_append(out, 0, xml ? "='" : "</td><td>"); 03551 if (!strcmp(var, "Opaque-data")) 03552 in_data = 1; 03553 } 03554 xml_copy_escape(out, val, 0); /* data field */ 03555 if (!in_data) 03556 ast_str_append(out, 0, xml ? "'" : "</td></tr>\n"); 03557 else 03558 ast_str_append(out, 0, xml ? "\n" : "<br>\n"); 03559 } 03560 if (inobj) { 03561 ast_str_append(out, 0, xml ? " /></response>\n" : 03562 "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 03563 ao2_ref(vco, -1); 03564 } 03565 }
struct server_args ami_desc [static] |
struct ast_tls_config ami_tls_cfg |
struct server_args amis_desc [static] |
char* contenttype[] [static] |
Initial value:
{ [FORMAT_RAW] = "plain", [FORMAT_HTML] = "html", [FORMAT_XML] = "xml", }
struct ast_http_uri manageruri |
struct ast_http_uri managerxmluri |
struct ast_http_uri rawmanuri |
int registered = 0 [static] |
char* words[AST_MAX_CMD_LEN] |