#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 ast_change_name(), ast_channel_alloc(), ast_channel_bridge(), ast_do_masquerade(), ast_hangup(), ast_set_callerid(), ast_setstate(), 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(), dahdi_handle_event(), expire_register(), handle_alarms(), 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(), and update_registry().
#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 2789 of file manager.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), s, and sessions.
02790 { 02791 int result = 0; 02792 struct mansession *s; 02793 02794 AST_LIST_LOCK(&sessions); 02795 AST_LIST_TRAVERSE(&sessions, s, list) { 02796 ast_mutex_lock(&s->__lock); 02797 if ((s->managerid == ident) && (s->readperm & perm)) { 02798 result = 1; 02799 ast_mutex_unlock(&s->__lock); 02800 break; 02801 } 02802 ast_mutex_unlock(&s->__lock); 02803 } 02804 AST_LIST_UNLOCK(&sessions); 02805 return result; 02806 }
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 2808 of file manager.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), s, and sessions.
02809 { 02810 int result = 0; 02811 struct mansession *s; 02812 02813 AST_LIST_LOCK(&sessions); 02814 AST_LIST_TRAVERSE(&sessions, s, list) { 02815 ast_mutex_lock(&s->__lock); 02816 if ((s->managerid == ident) && (s->writeperm & perm)) { 02817 result = 1; 02818 ast_mutex_unlock(&s->__lock); 02819 break; 02820 } 02821 ast_mutex_unlock(&s->__lock); 02822 } 02823 AST_LIST_UNLOCK(&sessions); 02824 return result; 02825 }
void const char int init_manager | ( | void | ) |
Called by Asterisk initialization
Definition at line 3027 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().
03028 { 03029 struct ast_config *cfg = NULL, *ucfg = NULL; 03030 const char *val; 03031 char *cat = NULL; 03032 int oldportno = portno; 03033 static struct sockaddr_in ba; 03034 int x = 1; 03035 int flags; 03036 int newhttptimeout = 60; 03037 struct ast_manager_user *user = NULL; 03038 03039 if (!registered) { 03040 /* Register default actions */ 03041 ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping); 03042 ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events); 03043 ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff); 03044 ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup); 03045 ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" ); 03046 ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar ); 03047 ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar ); 03048 ast_manager_register2("GetConfig", EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig); 03049 ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig); 03050 ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect ); 03051 ast_manager_register2("Atxfer", EVENT_FLAG_CALL, action_atxfer, "Attended transfer", mandescr_atxfer ); 03052 ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate); 03053 ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command ); 03054 ast_manager_register2("ExtensionState", EVENT_FLAG_CALL, action_extensionstate, "Check Extension Status", mandescr_extensionstate ); 03055 ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout ); 03056 ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus ); 03057 ast_manager_register2("MailboxCount", EVENT_FLAG_CALL, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount ); 03058 ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands); 03059 ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent); 03060 ast_manager_register2("CoreSettings", EVENT_FLAG_SYSTEM, action_coresettings, "Show PBX core settings (version etc)", mandescr_coresettings); 03061 ast_manager_register2("CoreStatus", EVENT_FLAG_SYSTEM, action_corestatus, "Show PBX core status variables", mandescr_corestatus); 03062 ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent); 03063 03064 ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry)); 03065 ast_extension_state_add(NULL, NULL, manager_state_cb, NULL); 03066 registered = 1; 03067 /* Append placeholder event so master_eventq never runs dry */ 03068 append_event("Event: Placeholder\r\n\r\n", 0); 03069 } 03070 portno = DEFAULT_MANAGER_PORT; 03071 displayconnects = 1; 03072 cfg = ast_config_load("manager.conf"); 03073 if (!cfg) { 03074 ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf. Call management disabled.\n"); 03075 return 0; 03076 } 03077 if ((val = ast_variable_retrieve(cfg, "general", "enabled"))) { 03078 manager_enabled = ast_true(val); 03079 } 03080 if ((val = ast_variable_retrieve(cfg, "general", "block-sockets"))) { 03081 block_sockets = ast_true(val); 03082 } 03083 if((val = ast_variable_retrieve(cfg, "general", "webenabled"))) { 03084 webmanager_enabled = ast_true(val); 03085 } 03086 if ((val = ast_variable_retrieve(cfg, "general", "port"))) { 03087 if (sscanf(val, "%d", &portno) != 1) { 03088 ast_log(LOG_WARNING, "Invalid port number '%s'\n", val); 03089 portno = DEFAULT_MANAGER_PORT; 03090 } 03091 } 03092 if ((val = ast_variable_retrieve(cfg, "general", "displayconnects"))) { 03093 displayconnects = ast_true(val); 03094 } 03095 if ((val = ast_variable_retrieve(cfg, "general", "timestampevents"))) { 03096 timestampevents = ast_true(val); 03097 } 03098 if ((val = ast_variable_retrieve(cfg, "general", "httptimeout"))) { 03099 newhttptimeout = atoi(val); 03100 } 03101 03102 memset(&ba, 0, sizeof(ba)); 03103 ba.sin_family = AF_INET; 03104 ba.sin_port = htons(portno); 03105 03106 if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) { 03107 if (!inet_aton(val, &ba.sin_addr)) { 03108 ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val); 03109 memset(&ba.sin_addr, 0, sizeof(ba.sin_addr)); 03110 } 03111 } 03112 03113 03114 if ((asock > -1) && ((portno != oldportno) || !manager_enabled)) { 03115 #if 0 03116 /* Can't be done yet */ 03117 close(asock); 03118 asock = -1; 03119 #else 03120 ast_log(LOG_WARNING, "Unable to change management port / enabled\n"); 03121 #endif 03122 } 03123 03124 AST_LIST_LOCK(&users); 03125 03126 if ((ucfg = ast_config_load("users.conf"))) { 03127 while ((cat = ast_category_browse(ucfg, cat))) { 03128 int hasmanager = 0; 03129 struct ast_variable *var = NULL; 03130 03131 if (!strcasecmp(cat, "general")) { 03132 continue; 03133 } 03134 03135 if (!(hasmanager = ast_true(ast_variable_retrieve(ucfg, cat, "hasmanager")))) { 03136 continue; 03137 } 03138 03139 /* Look for an existing entry, if none found - create one and add it to the list */ 03140 if (!(user = ast_get_manager_by_name_locked(cat))) { 03141 if (!(user = ast_calloc(1, sizeof(*user)))) { 03142 break; 03143 } 03144 /* Copy name over */ 03145 ast_copy_string(user->username, cat, sizeof(user->username)); 03146 /* Insert into list */ 03147 AST_LIST_INSERT_TAIL(&users, user, list); 03148 } 03149 03150 /* Make sure we keep this user and don't destroy it during cleanup */ 03151 user->keep = 1; 03152 03153 for (var = ast_variable_browse(ucfg, cat); var; var = var->next) { 03154 if (!strcasecmp(var->name, "secret")) { 03155 if (user->secret) { 03156 free(user->secret); 03157 } 03158 user->secret = ast_strdup(var->value); 03159 } else if (!strcasecmp(var->name, "deny") ) { 03160 if (user->deny) { 03161 free(user->deny); 03162 } 03163 user->deny = ast_strdup(var->value); 03164 } else if (!strcasecmp(var->name, "permit") ) { 03165 if (user->permit) { 03166 free(user->permit); 03167 } 03168 user->permit = ast_strdup(var->value); 03169 } else if (!strcasecmp(var->name, "read") ) { 03170 if (user->read) { 03171 free(user->read); 03172 } 03173 user->read = ast_strdup(var->value); 03174 } else if (!strcasecmp(var->name, "write") ) { 03175 if (user->write) { 03176 free(user->write); 03177 } 03178 user->write = ast_strdup(var->value); 03179 } else if (!strcasecmp(var->name, "displayconnects") ) { 03180 user->displayconnects = ast_true(var->value); 03181 } else if (!strcasecmp(var->name, "hasmanager")) { 03182 /* already handled */ 03183 } else { 03184 ast_log(LOG_DEBUG, "%s is an unknown option (to the manager module).\n", var->name); 03185 } 03186 } 03187 } 03188 ast_config_destroy(ucfg); 03189 } 03190 03191 while ((cat = ast_category_browse(cfg, cat))) { 03192 struct ast_variable *var = NULL; 03193 03194 if (!strcasecmp(cat, "general")) 03195 continue; 03196 03197 /* Look for an existing entry, if none found - create one and add it to the list */ 03198 if (!(user = ast_get_manager_by_name_locked(cat))) { 03199 if (!(user = ast_calloc(1, sizeof(*user)))) 03200 break; 03201 /* Copy name over */ 03202 ast_copy_string(user->username, cat, sizeof(user->username)); 03203 /* Insert into list */ 03204 AST_LIST_INSERT_TAIL(&users, user, list); 03205 } 03206 03207 /* Make sure we keep this user and don't destroy it during cleanup */ 03208 user->keep = 1; 03209 03210 var = ast_variable_browse(cfg, cat); 03211 while (var) { 03212 if (!strcasecmp(var->name, "secret")) { 03213 if (user->secret) 03214 free(user->secret); 03215 user->secret = ast_strdup(var->value); 03216 } else if (!strcasecmp(var->name, "deny") ) { 03217 if (user->deny) 03218 free(user->deny); 03219 user->deny = ast_strdup(var->value); 03220 } else if (!strcasecmp(var->name, "permit") ) { 03221 if (user->permit) 03222 free(user->permit); 03223 user->permit = ast_strdup(var->value); 03224 } else if (!strcasecmp(var->name, "read") ) { 03225 if (user->read) 03226 free(user->read); 03227 user->read = ast_strdup(var->value); 03228 } else if (!strcasecmp(var->name, "write") ) { 03229 if (user->write) 03230 free(user->write); 03231 user->write = ast_strdup(var->value); 03232 } else if (!strcasecmp(var->name, "displayconnects") ) 03233 user->displayconnects = ast_true(var->value); 03234 else 03235 ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name); 03236 var = var->next; 03237 } 03238 } 03239 03240 /* Perform cleanup - essentially prune out old users that no longer exist */ 03241 AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) { 03242 if (user->keep) { 03243 user->keep = 0; 03244 continue; 03245 } 03246 /* We do not need to keep this user so take them out of the list */ 03247 AST_LIST_REMOVE_CURRENT(&users, list); 03248 /* Free their memory now */ 03249 if (user->secret) 03250 free(user->secret); 03251 if (user->deny) 03252 free(user->deny); 03253 if (user->permit) 03254 free(user->permit); 03255 if (user->read) 03256 free(user->read); 03257 if (user->write) 03258 free(user->write); 03259 free(user); 03260 } 03261 AST_LIST_TRAVERSE_SAFE_END 03262 03263 AST_LIST_UNLOCK(&users); 03264 03265 ast_config_destroy(cfg); 03266 03267 if (webmanager_enabled && manager_enabled) { 03268 if (!webregged) { 03269 ast_http_uri_link(&rawmanuri); 03270 ast_http_uri_link(&manageruri); 03271 ast_http_uri_link(&managerxmluri); 03272 webregged = 1; 03273 } 03274 } else { 03275 if (webregged) { 03276 ast_http_uri_unlink(&rawmanuri); 03277 ast_http_uri_unlink(&manageruri); 03278 ast_http_uri_unlink(&managerxmluri); 03279 webregged = 0; 03280 } 03281 } 03282 03283 if (newhttptimeout > 0) 03284 httptimeout = newhttptimeout; 03285 03286 /* If not enabled, do nothing */ 03287 if (!manager_enabled) 03288 return 0; 03289 03290 if (asock < 0) { 03291 asock = socket(AF_INET, SOCK_STREAM, 0); 03292 if (asock < 0) { 03293 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno)); 03294 return -1; 03295 } 03296 setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 03297 if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) { 03298 ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno)); 03299 close(asock); 03300 asock = -1; 03301 return -1; 03302 } 03303 if (listen(asock, 2)) { 03304 ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno)); 03305 close(asock); 03306 asock = -1; 03307 return -1; 03308 } 03309 flags = fcntl(asock, F_GETFL); 03310 fcntl(asock, F_SETFL, flags | O_NONBLOCK); 03311 if (option_verbose) 03312 ast_verbose("Asterisk Management interface listening on port %d\n", portno); 03313 ast_pthread_create_background(&t, NULL, accept_thread, NULL); 03314 } 03315 return 0; 03316 }
int reload_manager | ( | void | ) |
Definition at line 3318 of file manager.c.
References EVENT_FLAG_SYSTEM, init_manager(), and manager_event().
03319 { 03320 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n"); 03321 return init_manager(); 03322 }
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().