#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 | 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_EXTENSIONSTATUS (1 << 8) |
#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) |
struct 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. | |
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 ast_manager_register | ( | a, | |||
b, | |||||
c, | |||||
d | ) | ast_manager_register2(a, b, c, d, NULL) |
Definition at line 86 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 55 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 51 of file manager.h.
Referenced by ast_autoanswer_login(), ast_change_name(), ast_channel_alloc(), ast_channel_bridge(), ast_do_masquerade(), ast_hangup(), ast_hold_call(), ast_monitor_stop(), ast_set_callerid(), ast_setstate_and_callerid(), autoanswer_exec(), bridge_exec(), change_hold_state(), conf_run(), do_autoanswer_thread(), fast_originate(), init_manager(), join_queue(), leave_queue(), load_module(), manager_log(), 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_EXTENSIONSTATUS (1 << 8) |
#define EVENT_FLAG_SYSTEM (1 << 0) |
Definition at line 50 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(), load_module(), parse_register_contact(), quit_handler(), register_verify(), reload_config(), 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 56 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)) | ) |
External routines may send asterisk manager events this way
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 2813 of file manager.c.
References mansession::__lock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession::managerid, mansession::readperm, and s.
02814 { 02815 int result = 0; 02816 struct mansession *s; 02817 02818 AST_LIST_LOCK(&sessions); 02819 AST_LIST_TRAVERSE(&sessions, s, list) { 02820 ast_mutex_lock(&s->__lock); 02821 if ((s->managerid == ident) && (s->readperm & perm)) { 02822 result = 1; 02823 ast_mutex_unlock(&s->__lock); 02824 break; 02825 } 02826 ast_mutex_unlock(&s->__lock); 02827 } 02828 AST_LIST_UNLOCK(&sessions); 02829 return result; 02830 }
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 2832 of file manager.c.
References mansession::__lock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession::managerid, s, and mansession::writeperm.
02833 { 02834 int result = 0; 02835 struct mansession *s; 02836 02837 AST_LIST_LOCK(&sessions); 02838 AST_LIST_TRAVERSE(&sessions, s, list) { 02839 ast_mutex_lock(&s->__lock); 02840 if ((s->managerid == ident) && (s->writeperm & perm)) { 02841 result = 1; 02842 ast_mutex_unlock(&s->__lock); 02843 break; 02844 } 02845 ast_mutex_unlock(&s->__lock); 02846 } 02847 AST_LIST_UNLOCK(&sessions); 02848 return result; 02849 }
void const char int init_manager | ( | void | ) |
Called by Asterisk initialization
Definition at line 3051 of file manager.c.
References accept_thread(), action_command(), action_events(), action_extensionstate(), action_getconfig(), action_getvar(), action_hangup(), action_listcommands(), action_logoff(), action_mailboxcount(), action_mailboxstatus(), action_message(), action_originate(), action_ping(), action_redirect(), action_setvar(), action_status(), action_timeout(), action_updateconfig(), action_userevent(), action_waitevent(), append_event(), ast_calloc, ast_category_browse(), ast_cli_register_multiple(), ast_config_destroy(), ast_config_load(), ast_extension_state_add(), ast_get_manager_by_name_locked(), ast_http_uri_link(), ast_http_uri_unlink(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_manager_register, ast_manager_register2(), ast_pthread_create_background, ast_strdup, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), DEFAULT_MANAGER_PORT, ast_manager_user::deny, ast_manager_user::displayconnects, errno, EVENT_FLAG_CALL, EVENT_FLAG_COMMAND, EVENT_FLAG_CONFIG, EVENT_FLAG_USER, ast_channel::flags, free, ast_manager_user::keep, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, manager_state_cb(), ast_variable::name, ast_variable::next, option_verbose, ast_manager_user::permit, ast_manager_user::read, ast_manager_user::secret, ast_manager_user::username, users, ast_variable::value, var, and ast_manager_user::write.
Referenced by main(), and reload_manager().
03052 { 03053 struct ast_config *cfg = NULL, *ucfg = NULL; 03054 const char *val; 03055 char *cat = NULL; 03056 int oldportno = portno; 03057 static struct sockaddr_in ba; 03058 int x = 1; 03059 int flags; 03060 int webenabled = DEFAULT_WEBENABLED; 03061 int newhttptimeout = DEFAULT_HTTPTIMEOUT; 03062 struct ast_manager_user *user = NULL; 03063 03064 if (!registered) { 03065 /* Register default actions */ 03066 ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping); 03067 ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events); 03068 ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff); 03069 ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup); 03070 ast_manager_register2("Message", EVENT_FLAG_CALL, action_message, "Send Message", mandescr_message); 03071 ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" ); 03072 ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar ); 03073 ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar ); 03074 ast_manager_register2("GetConfig", EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig); 03075 ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig); 03076 ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect ); 03077 ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate); 03078 ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command ); 03079 ast_manager_register2("ExtensionState", EVENT_FLAG_CALL, action_extensionstate, "Check Extension Status", mandescr_extensionstate ); 03080 ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout ); 03081 ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus ); 03082 ast_manager_register2("MailboxCount", EVENT_FLAG_CALL, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount ); 03083 ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands); 03084 ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent); 03085 ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent); 03086 03087 ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry)); 03088 ast_extension_state_add(NULL, NULL, manager_state_cb, NULL); 03089 registered = 1; 03090 /* Append placeholder event so master_eventq never runs dry */ 03091 append_event("Event: Placeholder\r\n\r\n", 0); 03092 } 03093 03094 portno = DEFAULT_MANAGER_PORT; 03095 displayconnects = DEFAULT_DISPLAYCONNECTS; 03096 block_sockets = DEFAULT_BLOCKSOCKETS; 03097 timestampevents = DEFAULT_TIMESTAMPEVENTS; 03098 httptimeout = DEFAULT_HTTPTIMEOUT; 03099 authtimeout = DEFAULT_AUTHTIMEOUT; 03100 authlimit = DEFAULT_AUTHLIMIT; 03101 03102 cfg = ast_config_load("manager.conf"); 03103 if (!cfg) { 03104 ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf. Call management disabled.\n"); 03105 return 0; 03106 } 03107 val = ast_variable_retrieve(cfg, "general", "enabled"); 03108 if (val) 03109 enabled = ast_true(val); 03110 03111 val = ast_variable_retrieve(cfg, "general", "block-sockets"); 03112 if (val) 03113 block_sockets = ast_true(val); 03114 03115 val = ast_variable_retrieve(cfg, "general", "webenabled"); 03116 if (val) 03117 webenabled = ast_true(val); 03118 03119 if ((val = ast_variable_retrieve(cfg, "general", "port"))) { 03120 if (sscanf(val, "%d", &portno) != 1) { 03121 ast_log(LOG_WARNING, "Invalid port number '%s'\n", val); 03122 portno = DEFAULT_MANAGER_PORT; 03123 } 03124 } 03125 03126 if ((val = ast_variable_retrieve(cfg, "general", "displayconnects"))) 03127 displayconnects = ast_true(val); 03128 03129 if ((val = ast_variable_retrieve(cfg, "general", "timestampevents"))) 03130 timestampevents = ast_true(val); 03131 03132 if ((val = ast_variable_retrieve(cfg, "general", "httptimeout"))) 03133 newhttptimeout = atoi(val); 03134 03135 if ((val = ast_variable_retrieve(cfg, "general", "authtimeout"))) { 03136 int timeout = atoi(val); 03137 03138 if (timeout < 1) { 03139 ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", val); 03140 } else { 03141 authtimeout = timeout; 03142 } 03143 } 03144 03145 if ((val = ast_variable_retrieve(cfg, "general", "authlimit"))) { 03146 int limit = atoi(val); 03147 03148 if (limit < 1) { 03149 ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", val); 03150 } else { 03151 authlimit = limit; 03152 } 03153 } 03154 03155 memset(&ba, 0, sizeof(ba)); 03156 ba.sin_family = AF_INET; 03157 ba.sin_port = htons(portno); 03158 03159 if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) { 03160 if (!inet_aton(val, &ba.sin_addr)) { 03161 ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val); 03162 memset(&ba.sin_addr, 0, sizeof(ba.sin_addr)); 03163 } 03164 } 03165 03166 03167 if ((asock > -1) && ((portno != oldportno) || !enabled)) { 03168 #if 0 03169 /* Can't be done yet */ 03170 close(asock); 03171 asock = -1; 03172 #else 03173 ast_log(LOG_WARNING, "Unable to change management port / enabled\n"); 03174 #endif 03175 } 03176 03177 AST_LIST_LOCK(&users); 03178 03179 if ((ucfg = ast_config_load("users.conf"))) { 03180 while ((cat = ast_category_browse(ucfg, cat))) { 03181 int hasmanager = 0; 03182 struct ast_variable *var = NULL; 03183 03184 if (!strcasecmp(cat, "general")) { 03185 continue; 03186 } 03187 03188 if (!(hasmanager = ast_true(ast_variable_retrieve(ucfg, cat, "hasmanager")))) { 03189 continue; 03190 } 03191 03192 /* Look for an existing entry, if none found - create one and add it to the list */ 03193 if (!(user = ast_get_manager_by_name_locked(cat))) { 03194 if (!(user = ast_calloc(1, sizeof(*user)))) { 03195 break; 03196 } 03197 /* Copy name over */ 03198 ast_copy_string(user->username, cat, sizeof(user->username)); 03199 /* Insert into list */ 03200 AST_LIST_INSERT_TAIL(&users, user, list); 03201 } 03202 03203 /* Make sure we keep this user and don't destroy it during cleanup */ 03204 user->keep = 1; 03205 03206 for (var = ast_variable_browse(ucfg, cat); var; var = var->next) { 03207 if (!strcasecmp(var->name, "secret")) { 03208 if (user->secret) { 03209 free(user->secret); 03210 } 03211 user->secret = ast_strdup(var->value); 03212 } else if (!strcasecmp(var->name, "deny") ) { 03213 if (user->deny) { 03214 free(user->deny); 03215 } 03216 user->deny = ast_strdup(var->value); 03217 } else if (!strcasecmp(var->name, "permit") ) { 03218 if (user->permit) { 03219 free(user->permit); 03220 } 03221 user->permit = ast_strdup(var->value); 03222 } else if (!strcasecmp(var->name, "read") ) { 03223 if (user->read) { 03224 free(user->read); 03225 } 03226 user->read = ast_strdup(var->value); 03227 } else if (!strcasecmp(var->name, "write") ) { 03228 if (user->write) { 03229 free(user->write); 03230 } 03231 user->write = ast_strdup(var->value); 03232 } else if (!strcasecmp(var->name, "displayconnects") ) { 03233 user->displayconnects = ast_true(var->value); 03234 } else if (!strcasecmp(var->name, "hasmanager")) { 03235 /* already handled */ 03236 } else { 03237 ast_log(LOG_DEBUG, "%s is an unknown option (to the manager module).\n", var->name); 03238 } 03239 } 03240 } 03241 ast_config_destroy(ucfg); 03242 } 03243 03244 while ((cat = ast_category_browse(cfg, cat))) { 03245 struct ast_variable *var = NULL; 03246 03247 if (!strcasecmp(cat, "general")) 03248 continue; 03249 03250 /* Look for an existing entry, if none found - create one and add it to the list */ 03251 if (!(user = ast_get_manager_by_name_locked(cat))) { 03252 if (!(user = ast_calloc(1, sizeof(*user)))) 03253 break; 03254 /* Copy name over */ 03255 ast_copy_string(user->username, cat, sizeof(user->username)); 03256 /* Insert into list */ 03257 AST_LIST_INSERT_TAIL(&users, user, list); 03258 } 03259 03260 /* Make sure we keep this user and don't destroy it during cleanup */ 03261 user->keep = 1; 03262 03263 var = ast_variable_browse(cfg, cat); 03264 while (var) { 03265 if (!strcasecmp(var->name, "secret")) { 03266 if (user->secret) 03267 free(user->secret); 03268 user->secret = ast_strdup(var->value); 03269 } else if (!strcasecmp(var->name, "deny") ) { 03270 if (user->deny) 03271 free(user->deny); 03272 user->deny = ast_strdup(var->value); 03273 } else if (!strcasecmp(var->name, "permit") ) { 03274 if (user->permit) 03275 free(user->permit); 03276 user->permit = ast_strdup(var->value); 03277 } else if (!strcasecmp(var->name, "read") ) { 03278 if (user->read) 03279 free(user->read); 03280 user->read = ast_strdup(var->value); 03281 } else if (!strcasecmp(var->name, "write") ) { 03282 if (user->write) 03283 free(user->write); 03284 user->write = ast_strdup(var->value); 03285 } else if (!strcasecmp(var->name, "displayconnects") ) 03286 user->displayconnects = ast_true(var->value); 03287 else 03288 ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name); 03289 var = var->next; 03290 } 03291 } 03292 03293 /* Perform cleanup - essentially prune out old users that no longer exist */ 03294 AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) { 03295 if (user->keep) { 03296 user->keep = 0; 03297 continue; 03298 } 03299 /* We do not need to keep this user so take them out of the list */ 03300 AST_LIST_REMOVE_CURRENT(&users, list); 03301 /* Free their memory now */ 03302 if (user->secret) 03303 free(user->secret); 03304 if (user->deny) 03305 free(user->deny); 03306 if (user->permit) 03307 free(user->permit); 03308 if (user->read) 03309 free(user->read); 03310 if (user->write) 03311 free(user->write); 03312 free(user); 03313 } 03314 AST_LIST_TRAVERSE_SAFE_END 03315 03316 AST_LIST_UNLOCK(&users); 03317 03318 ast_config_destroy(cfg); 03319 03320 if (webenabled && enabled) { 03321 if (!webregged) { 03322 ast_http_uri_link(&rawmanuri); 03323 ast_http_uri_link(&manageruri); 03324 ast_http_uri_link(&managerxmluri); 03325 webregged = 1; 03326 } 03327 } else { 03328 if (webregged) { 03329 ast_http_uri_unlink(&rawmanuri); 03330 ast_http_uri_unlink(&manageruri); 03331 ast_http_uri_unlink(&managerxmluri); 03332 webregged = 0; 03333 } 03334 } 03335 03336 if (newhttptimeout > 0) 03337 httptimeout = newhttptimeout; 03338 03339 /* If not enabled, do nothing */ 03340 if (!enabled) 03341 return 0; 03342 03343 if (asock < 0) { 03344 asock = socket(AF_INET, SOCK_STREAM, 0); 03345 if (asock < 0) { 03346 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno)); 03347 return -1; 03348 } 03349 setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 03350 if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) { 03351 ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno)); 03352 close(asock); 03353 asock = -1; 03354 return -1; 03355 } 03356 if (listen(asock, 2)) { 03357 ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno)); 03358 close(asock); 03359 asock = -1; 03360 return -1; 03361 } 03362 flags = fcntl(asock, F_GETFL); 03363 fcntl(asock, F_SETFL, flags | O_NONBLOCK); 03364 if (option_verbose) 03365 ast_verbose("Asterisk Management interface listening on port %d\n", portno); 03366 ast_pthread_create_background(&t, NULL, accept_thread, NULL); 03367 } 03368 return 0; 03369 }
int reload_manager | ( | void | ) |
Definition at line 3371 of file manager.c.
References EVENT_FLAG_SYSTEM, init_manager(), and manager_event().
03372 { 03373 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n"); 03374 return init_manager(); 03375 }
int const char* event |
Definition at line 130 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(), onevent(), process_cisco_dtmf(), process_rfc2833(), ql_exec(), receive_ademco_contact_id(), sla_queue_event_full(), and sla_thread().
void const char* fmt |
Definition at line 143 of file manager.h.
Referenced by __oh323_new(), ast_cdr_getvar(), ast_cli_netstats(), ast_openvstream(), ast_request_with_uniqueid(), ast_streamfile(), check_header(), do_say(), gtalk_new(), iax2_request(), local_new(), mgcp_new(), setformat(), sip_new(), skinny_new(), try_suggested_sip_codec(), and write_header().