#include <stdarg.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "asterisk/lock.h"
Go to the source code of this file.
Data Structures | |
struct | manager_action |
struct | message |
Defines | |
#define | AMI_VERSION "1.0" |
#define | ast_manager_register(a, b, c, d) ast_manager_register2(a, b, c, d, NULL) |
#define | AST_MAX_MANHEADERS 128 |
#define | DEFAULT_MANAGER_PORT 5038 |
#define | EVENT_FLAG_AGENT (1 << 5) |
#define | EVENT_FLAG_CALL (1 << 1) |
#define | EVENT_FLAG_COMMAND (1 << 4) |
#define | EVENT_FLAG_CONFIG (1 << 7) |
#define | EVENT_FLAG_LOG (1 << 2) |
#define | EVENT_FLAG_SYSTEM (1 << 0) |
#define | EVENT_FLAG_USER (1 << 6) |
#define | EVENT_FLAG_VERBOSE (1 << 3) |
Functions | |
void | __attribute__ ((format(printf, 2, 3))) astman_append(struct mansession *s |
int | __attribute__ ((format(printf, 3, 4))) manager_event(int category |
int | ast_manager_register2 (const char *action, int authority, 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 | |
int | ast_manager_unregister (char *action) |
int const char const char const char * | astman_get_header (const struct message *m, char *var) |
ast_variable * | astman_get_variables (const struct message *m) |
void | astman_send_ack (struct mansession *s, const struct message *m, char *msg) |
void | astman_send_error (struct mansession *s, const struct message *m, char *error) |
void | astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg) |
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. | |
int | check_manager_enabled (void) |
Check if AMI is enabled. | |
int | check_webmanager_enabled (void) |
Check if AMI/HTTP is enabled. | |
void const char int | init_manager (void) |
int | reload_manager (void) |
Variables | |
int const char const char * | contents |
int const char * | event |
void const char * | fmt |
Manager protocol packages are text fields of the form a: b. There is always exactly one space after the colon.
The first header type is the "Event" header. Other headers vary from event to event. Headers end with standard
termination. The last line of the manager response or event is an empty line. (
)
Please try to re-use existing headers to simplify manager message parsing in clients. Don't re-use an existing header with a new meaning, please. You can find a reference of standard headers in doc/manager.txt
Definition in file manager.h.
#define AMI_VERSION "1.0" |
#define ast_manager_register | ( | a, | |||
b, | |||||
c, | |||||
d | ) | ast_manager_register2(a, b, c, d, NULL) |
Definition at line 92 of file manager.h.
Referenced by astdb_init(), init_manager(), and load_module().
#define AST_MAX_MANHEADERS 128 |
#define DEFAULT_MANAGER_PORT 5038 |
#define EVENT_FLAG_AGENT (1 << 5) |
Definition at line 56 of file manager.h.
Referenced by __login_exec(), action_agent_callback_login(), add_to_queue(), agent_logoff_maintenance(), load_module(), record_abandoned(), remove_from_queue(), ring_entry(), set_member_paused(), try_calling(), and update_status().
#define EVENT_FLAG_CALL (1 << 1) |
Definition at line 52 of file manager.h.
Referenced by change_hold_state(), conf_run(), fast_originate(), init_manager(), join_queue(), leave_queue(), load_module(), manager_log(), manager_state_cb(), notify_new_message(), park_call_full(), park_exec(), pbx_extension_helper(), post_manager_event(), realtime_exec(), senddialevent(), socket_process(), and vm_execmain().
#define EVENT_FLAG_COMMAND (1 << 4) |
#define EVENT_FLAG_CONFIG (1 << 7) |
#define EVENT_FLAG_SYSTEM (1 << 0) |
Definition at line 51 of file manager.h.
Referenced by __expire_registry(), __iax2_poke_noanswer(), ast_log(), astdb_init(), expire_register(), handle_init_event(), handle_response_peerpoke(), handle_response_register(), iax2_ack_registry(), init_manager(), load_module(), parse_register_contact(), quit_handler(), register_verify(), reload_logger(), reload_manager(), sip_poke_noanswer(), sip_reg_timeout(), socket_process(), ss_thread(), update_registry(), and zt_handle_event().
#define EVENT_FLAG_USER (1 << 6) |
Definition at line 57 of file manager.h.
Referenced by action_userevent(), aji_log_hook(), init_manager(), and userevent_exec().
void __attribute__ | ( | (format(printf, 2, 3)) | ) |
int __attribute__ | ( | (format(printf, 3, 4)) | ) |
category | Event category, matches manager authorization | |
event | Event name | |
contents | Contents of event |
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 |
Definition at line 2780 of file manager.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), s, and sessions.
02781 { 02782 int result = 0; 02783 struct mansession *s; 02784 02785 AST_LIST_LOCK(&sessions); 02786 AST_LIST_TRAVERSE(&sessions, s, list) { 02787 ast_mutex_lock(&s->__lock); 02788 if ((s->managerid == ident) && (s->readperm & perm)) { 02789 result = 1; 02790 ast_mutex_unlock(&s->__lock); 02791 break; 02792 } 02793 ast_mutex_unlock(&s->__lock); 02794 } 02795 AST_LIST_UNLOCK(&sessions); 02796 return result; 02797 }
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 |
Definition at line 2799 of file manager.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), s, and sessions.
02800 { 02801 int result = 0; 02802 struct mansession *s; 02803 02804 AST_LIST_LOCK(&sessions); 02805 AST_LIST_TRAVERSE(&sessions, s, list) { 02806 ast_mutex_lock(&s->__lock); 02807 if ((s->managerid == ident) && (s->writeperm & perm)) { 02808 result = 1; 02809 ast_mutex_unlock(&s->__lock); 02810 break; 02811 } 02812 ast_mutex_unlock(&s->__lock); 02813 } 02814 AST_LIST_UNLOCK(&sessions); 02815 return result; 02816 }
void const char int init_manager | ( | void | ) |
Called by Asterisk initialization
Definition at line 3018 of file manager.c.
References action_atxfer(), action_command(), action_coresettings(), action_corestatus(), action_events(), action_extensionstate(), action_getconfig(), action_getvar(), action_hangup(), action_listcommands(), action_logoff(), action_mailboxcount(), action_mailboxstatus(), action_originate(), action_ping(), action_redirect(), action_setvar(), action_status(), action_timeout(), action_updateconfig(), action_userevent(), action_waitevent(), append_event(), asock, ast_calloc, ast_category_browse(), ast_cli_register_multiple(), ast_config_load(), ast_extension_state_add(), ast_get_manager_by_name_locked(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, ast_log(), ast_manager_register, ast_manager_register2(), ast_strdup, ast_true(), ast_variable_browse(), ast_variable_retrieve(), block_sockets, cli_manager, DEFAULT_MANAGER_PORT, ast_manager_user::deny, ast_manager_user::displayconnects, displayconnects, EVENT_FLAG_CALL, EVENT_FLAG_COMMAND, EVENT_FLAG_CONFIG, EVENT_FLAG_SYSTEM, EVENT_FLAG_USER, ast_channel::flags, free, ast_manager_user::keep, LOG_DEBUG, LOG_WARNING, manager_enabled, manager_state_cb(), ast_manager_user::permit, portno, ast_manager_user::read, ast_manager_user::secret, timestampevents, users, var, webmanager_enabled, and ast_manager_user::write.
Referenced by main(), and reload_manager().
03019 { 03020 struct ast_config *cfg = NULL, *ucfg = NULL; 03021 const char *val; 03022 char *cat = NULL; 03023 int oldportno = portno; 03024 static struct sockaddr_in ba; 03025 int x = 1; 03026 int flags; 03027 int newhttptimeout = 60; 03028 struct ast_manager_user *user = NULL; 03029 03030 if (!registered) { 03031 /* Register default actions */ 03032 ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping); 03033 ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events); 03034 ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff); 03035 ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup); 03036 ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" ); 03037 ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar ); 03038 ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar ); 03039 ast_manager_register2("GetConfig", EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig); 03040 ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig); 03041 ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect ); 03042 ast_manager_register2("Atxfer", EVENT_FLAG_CALL, action_atxfer, "Attended transfer", mandescr_atxfer ); 03043 ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate); 03044 ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command ); 03045 ast_manager_register2("ExtensionState", EVENT_FLAG_CALL, action_extensionstate, "Check Extension Status", mandescr_extensionstate ); 03046 ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout ); 03047 ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus ); 03048 ast_manager_register2("MailboxCount", EVENT_FLAG_CALL, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount ); 03049 ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands); 03050 ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent); 03051 ast_manager_register2("CoreSettings", EVENT_FLAG_SYSTEM, action_coresettings, "Show PBX core settings (version etc)", mandescr_coresettings); 03052 ast_manager_register2("CoreStatus", EVENT_FLAG_SYSTEM, action_corestatus, "Show PBX core status variables", mandescr_corestatus); 03053 ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent); 03054 03055 ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry)); 03056 ast_extension_state_add(NULL, NULL, manager_state_cb, NULL); 03057 registered = 1; 03058 /* Append placeholder event so master_eventq never runs dry */ 03059 append_event("Event: Placeholder\r\n\r\n", 0); 03060 } 03061 portno = DEFAULT_MANAGER_PORT; 03062 displayconnects = 1; 03063 cfg = ast_config_load("manager.conf"); 03064 if (!cfg) { 03065 ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf. Call management disabled.\n"); 03066 return 0; 03067 } 03068 if ((val = ast_variable_retrieve(cfg, "general", "enabled"))) { 03069 manager_enabled = ast_true(val); 03070 } 03071 if ((val = ast_variable_retrieve(cfg, "general", "block-sockets"))) { 03072 block_sockets = ast_true(val); 03073 } 03074 if((val = ast_variable_retrieve(cfg, "general", "webenabled"))) { 03075 webmanager_enabled = ast_true(val); 03076 } 03077 if ((val = ast_variable_retrieve(cfg, "general", "port"))) { 03078 if (sscanf(val, "%d", &portno) != 1) { 03079 ast_log(LOG_WARNING, "Invalid port number '%s'\n", val); 03080 portno = DEFAULT_MANAGER_PORT; 03081 } 03082 } 03083 if ((val = ast_variable_retrieve(cfg, "general", "displayconnects"))) { 03084 displayconnects = ast_true(val); 03085 } 03086 if ((val = ast_variable_retrieve(cfg, "general", "timestampevents"))) { 03087 timestampevents = ast_true(val); 03088 } 03089 if ((val = ast_variable_retrieve(cfg, "general", "httptimeout"))) { 03090 newhttptimeout = atoi(val); 03091 } 03092 03093 memset(&ba, 0, sizeof(ba)); 03094 ba.sin_family = AF_INET; 03095 ba.sin_port = htons(portno); 03096 03097 if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) { 03098 if (!inet_aton(val, &ba.sin_addr)) { 03099 ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val); 03100 memset(&ba.sin_addr, 0, sizeof(ba.sin_addr)); 03101 } 03102 } 03103 03104 03105 if ((asock > -1) && ((portno != oldportno) || !manager_enabled)) { 03106 #if 0 03107 /* Can't be done yet */ 03108 close(asock); 03109 asock = -1; 03110 #else 03111 ast_log(LOG_WARNING, "Unable to change management port / enabled\n"); 03112 #endif 03113 } 03114 03115 AST_LIST_LOCK(&users); 03116 03117 if ((ucfg = ast_config_load("users.conf"))) { 03118 while ((cat = ast_category_browse(ucfg, cat))) { 03119 int hasmanager = 0; 03120 struct ast_variable *var = NULL; 03121 03122 if (!strcasecmp(cat, "general")) { 03123 continue; 03124 } 03125 03126 if (!(hasmanager = ast_true(ast_variable_retrieve(ucfg, cat, "hasmanager")))) { 03127 continue; 03128 } 03129 03130 /* Look for an existing entry, if none found - create one and add it to the list */ 03131 if (!(user = ast_get_manager_by_name_locked(cat))) { 03132 if (!(user = ast_calloc(1, sizeof(*user)))) { 03133 break; 03134 } 03135 /* Copy name over */ 03136 ast_copy_string(user->username, cat, sizeof(user->username)); 03137 /* Insert into list */ 03138 AST_LIST_INSERT_TAIL(&users, user, list); 03139 } 03140 03141 /* Make sure we keep this user and don't destroy it during cleanup */ 03142 user->keep = 1; 03143 03144 for (var = ast_variable_browse(ucfg, cat); var; var = var->next) { 03145 if (!strcasecmp(var->name, "secret")) { 03146 if (user->secret) { 03147 free(user->secret); 03148 } 03149 user->secret = ast_strdup(var->value); 03150 } else if (!strcasecmp(var->name, "deny") ) { 03151 if (user->deny) { 03152 free(user->deny); 03153 } 03154 user->deny = ast_strdup(var->value); 03155 } else if (!strcasecmp(var->name, "permit") ) { 03156 if (user->permit) { 03157 free(user->permit); 03158 } 03159 user->permit = ast_strdup(var->value); 03160 } else if (!strcasecmp(var->name, "read") ) { 03161 if (user->read) { 03162 free(user->read); 03163 } 03164 user->read = ast_strdup(var->value); 03165 } else if (!strcasecmp(var->name, "write") ) { 03166 if (user->write) { 03167 free(user->write); 03168 } 03169 user->write = ast_strdup(var->value); 03170 } else if (!strcasecmp(var->name, "displayconnects") ) { 03171 user->displayconnects = ast_true(var->value); 03172 } else if (!strcasecmp(var->name, "hasmanager")) { 03173 /* already handled */ 03174 } else { 03175 ast_log(LOG_DEBUG, "%s is an unknown option (to the manager module).\n", var->name); 03176 } 03177 } 03178 } 03179 ast_config_destroy(ucfg); 03180 } 03181 03182 while ((cat = ast_category_browse(cfg, cat))) { 03183 struct ast_variable *var = NULL; 03184 03185 if (!strcasecmp(cat, "general")) 03186 continue; 03187 03188 /* Look for an existing entry, if none found - create one and add it to the list */ 03189 if (!(user = ast_get_manager_by_name_locked(cat))) { 03190 if (!(user = ast_calloc(1, sizeof(*user)))) 03191 break; 03192 /* Copy name over */ 03193 ast_copy_string(user->username, cat, sizeof(user->username)); 03194 /* Insert into list */ 03195 AST_LIST_INSERT_TAIL(&users, user, list); 03196 } 03197 03198 /* Make sure we keep this user and don't destroy it during cleanup */ 03199 user->keep = 1; 03200 03201 var = ast_variable_browse(cfg, cat); 03202 while (var) { 03203 if (!strcasecmp(var->name, "secret")) { 03204 if (user->secret) 03205 free(user->secret); 03206 user->secret = ast_strdup(var->value); 03207 } else if (!strcasecmp(var->name, "deny") ) { 03208 if (user->deny) 03209 free(user->deny); 03210 user->deny = ast_strdup(var->value); 03211 } else if (!strcasecmp(var->name, "permit") ) { 03212 if (user->permit) 03213 free(user->permit); 03214 user->permit = ast_strdup(var->value); 03215 } else if (!strcasecmp(var->name, "read") ) { 03216 if (user->read) 03217 free(user->read); 03218 user->read = ast_strdup(var->value); 03219 } else if (!strcasecmp(var->name, "write") ) { 03220 if (user->write) 03221 free(user->write); 03222 user->write = ast_strdup(var->value); 03223 } else if (!strcasecmp(var->name, "displayconnects") ) 03224 user->displayconnects = ast_true(var->value); 03225 else 03226 ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name); 03227 var = var->next; 03228 } 03229 } 03230 03231 /* Perform cleanup - essentially prune out old users that no longer exist */ 03232 AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) { 03233 if (user->keep) { 03234 user->keep = 0; 03235 continue; 03236 } 03237 /* We do not need to keep this user so take them out of the list */ 03238 AST_LIST_REMOVE_CURRENT(&users, list); 03239 /* Free their memory now */ 03240 if (user->secret) 03241 free(user->secret); 03242 if (user->deny) 03243 free(user->deny); 03244 if (user->permit) 03245 free(user->permit); 03246 if (user->read) 03247 free(user->read); 03248 if (user->write) 03249 free(user->write); 03250 free(user); 03251 } 03252 AST_LIST_TRAVERSE_SAFE_END 03253 03254 AST_LIST_UNLOCK(&users); 03255 03256 ast_config_destroy(cfg); 03257 03258 if (webmanager_enabled && manager_enabled) { 03259 if (!webregged) { 03260 ast_http_uri_link(&rawmanuri); 03261 ast_http_uri_link(&manageruri); 03262 ast_http_uri_link(&managerxmluri); 03263 webregged = 1; 03264 } 03265 } else { 03266 if (webregged) { 03267 ast_http_uri_unlink(&rawmanuri); 03268 ast_http_uri_unlink(&manageruri); 03269 ast_http_uri_unlink(&managerxmluri); 03270 webregged = 0; 03271 } 03272 } 03273 03274 if (newhttptimeout > 0) 03275 httptimeout = newhttptimeout; 03276 03277 /* If not enabled, do nothing */ 03278 if (!manager_enabled) 03279 return 0; 03280 03281 if (asock < 0) { 03282 asock = socket(AF_INET, SOCK_STREAM, 0); 03283 if (asock < 0) { 03284 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno)); 03285 return -1; 03286 } 03287 setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 03288 if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) { 03289 ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno)); 03290 close(asock); 03291 asock = -1; 03292 return -1; 03293 } 03294 if (listen(asock, 2)) { 03295 ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno)); 03296 close(asock); 03297 asock = -1; 03298 return -1; 03299 } 03300 flags = fcntl(asock, F_GETFL); 03301 fcntl(asock, F_SETFL, flags | O_NONBLOCK); 03302 if (option_verbose) 03303 ast_verbose("Asterisk Management interface listening on port %d\n", portno); 03304 ast_pthread_create_background(&t, NULL, accept_thread, NULL); 03305 } 03306 return 0; 03307 }
int reload_manager | ( | void | ) |
Definition at line 3309 of file manager.c.
References EVENT_FLAG_SYSTEM, init_manager(), and manager_event().
03310 { 03311 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n"); 03312 return init_manager(); 03313 }
int const char* event |
Definition at line 136 of file manager.h.
Referenced by action_userevent(), adsi_process(), ast_rtp_read(), handle_event_nt(), handle_frm(), handle_request_info(), handle_request_notify(), handle_request_subscribe(), handle_soft_key_event_message(), handle_stimulus_message(), log_events(), onevent(), process_cisco_dtmf(), process_rfc2833(), ql_exec(), receive_ademco_contact_id(), sla_handle_hold_event(), sla_queue_event_full(), sla_thread(), and write_event().
void const char* fmt |
Definition at line 149 of file manager.h.
Referenced by __oh323_new(), add_codec_to_sdp(), ast_cdr_getvar(), ast_cli_netstats(), ast_codec_pref_getsize(), ast_openvstream(), ast_request(), ast_rtp_write(), ast_streamfile(), check_header(), get_filestream(), gtalk_new(), handle_open_receive_channel_ack_message(), iax2_request(), local_new(), mgcp_new(), setformat(), sip_new(), skinny_new(), transmit_connect(), try_suggested_sip_codec(), and write_header().