#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 | |
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) |
void | astman_append (struct mansession *s, const char *fmt,...) |
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. | |
int | init_manager (void) |
int | manager_event (int category, const char *event, const char *contents,...) |
manager_event: Send AMI event to client | |
int | reload_manager (void) |
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(), 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) |
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 2873 of file manager.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), and s.
02874 { 02875 int result = 0; 02876 struct mansession_session *s; 02877 02878 AST_LIST_LOCK(&sessions); 02879 AST_LIST_TRAVERSE(&sessions, s, list) { 02880 ast_mutex_lock(&s->__lock); 02881 if ((s->managerid == ident) && (s->readperm & perm)) { 02882 result = 1; 02883 ast_mutex_unlock(&s->__lock); 02884 break; 02885 } 02886 ast_mutex_unlock(&s->__lock); 02887 } 02888 AST_LIST_UNLOCK(&sessions); 02889 return result; 02890 }
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 2892 of file manager.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), and s.
02893 { 02894 int result = 0; 02895 struct mansession_session *s; 02896 02897 AST_LIST_LOCK(&sessions); 02898 AST_LIST_TRAVERSE(&sessions, s, list) { 02899 ast_mutex_lock(&s->__lock); 02900 if ((s->managerid == ident) && (s->writeperm & perm)) { 02901 result = 1; 02902 ast_mutex_unlock(&s->__lock); 02903 break; 02904 } 02905 ast_mutex_unlock(&s->__lock); 02906 } 02907 AST_LIST_UNLOCK(&sessions); 02908 return result; 02909 }
int init_manager | ( | void | ) |
Called by Asterisk initialization
Definition at line 3150 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_copy_string(), 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(), mandescr_atxfer, mandescr_command, mandescr_events, mandescr_extensionstate, mandescr_getconfig, mandescr_getvar, mandescr_hangup, mandescr_listcommands, mandescr_logoff, mandescr_mailboxcount, mandescr_mailboxstatus, mandescr_originate, mandescr_ping, mandescr_redirect, mandescr_setvar, mandescr_timeout, mandescr_updateconfig, mandescr_userevent, mandescr_waitevent, ast_manager_user::permit, portno, ast_manager_user::read, ast_manager_user::secret, timestampevents, var, webmanager_enabled, and ast_manager_user::write.
Referenced by main(), and reload_manager().
03151 { 03152 struct ast_config *cfg = NULL, *ucfg = NULL; 03153 const char *val; 03154 char *cat = NULL; 03155 int oldportno = portno; 03156 static struct sockaddr_in ba; 03157 int x = 1; 03158 int flags; 03159 int newhttptimeout = 60; 03160 struct ast_manager_user *user = NULL; 03161 03162 if (!registered) { 03163 /* Register default actions */ 03164 ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping); 03165 ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events); 03166 ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff); 03167 ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup); 03168 ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" ); 03169 ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar ); 03170 ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar ); 03171 ast_manager_register2("GetConfig", EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig); 03172 ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig); 03173 ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect ); 03174 ast_manager_register2("Atxfer", EVENT_FLAG_CALL, action_atxfer, "Attended transfer", mandescr_atxfer ); 03175 ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate); 03176 ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command ); 03177 ast_manager_register2("ExtensionState", EVENT_FLAG_CALL, action_extensionstate, "Check Extension Status", mandescr_extensionstate ); 03178 ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout ); 03179 ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus ); 03180 ast_manager_register2("MailboxCount", EVENT_FLAG_CALL, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount ); 03181 ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands); 03182 ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent); 03183 ast_manager_register2("CoreSettings", EVENT_FLAG_SYSTEM, action_coresettings, "Show PBX core settings (version etc)", mandescr_coresettings); 03184 ast_manager_register2("CoreStatus", EVENT_FLAG_SYSTEM, action_corestatus, "Show PBX core status variables", mandescr_corestatus); 03185 ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent); 03186 03187 ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry)); 03188 ast_extension_state_add(NULL, NULL, manager_state_cb, NULL); 03189 registered = 1; 03190 /* Append placeholder event so master_eventq never runs dry */ 03191 append_event("Event: Placeholder\r\n\r\n", 0); 03192 } 03193 portno = DEFAULT_MANAGER_PORT; 03194 displayconnects = 1; 03195 cfg = ast_config_load("manager.conf"); 03196 if (!cfg) { 03197 ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf. Call management disabled.\n"); 03198 return 0; 03199 } 03200 if ((val = ast_variable_retrieve(cfg, "general", "enabled"))) { 03201 manager_enabled = ast_true(val); 03202 } 03203 if ((val = ast_variable_retrieve(cfg, "general", "block-sockets"))) { 03204 block_sockets = ast_true(val); 03205 } 03206 if((val = ast_variable_retrieve(cfg, "general", "webenabled"))) { 03207 webmanager_enabled = ast_true(val); 03208 } 03209 if ((val = ast_variable_retrieve(cfg, "general", "port"))) { 03210 if (sscanf(val, "%d", &portno) != 1) { 03211 ast_log(LOG_WARNING, "Invalid port number '%s'\n", val); 03212 portno = DEFAULT_MANAGER_PORT; 03213 } 03214 } 03215 if ((val = ast_variable_retrieve(cfg, "general", "displayconnects"))) { 03216 displayconnects = ast_true(val); 03217 } 03218 if ((val = ast_variable_retrieve(cfg, "general", "timestampevents"))) { 03219 timestampevents = ast_true(val); 03220 } 03221 if ((val = ast_variable_retrieve(cfg, "general", "httptimeout"))) { 03222 newhttptimeout = atoi(val); 03223 } 03224 03225 memset(&ba, 0, sizeof(ba)); 03226 ba.sin_family = AF_INET; 03227 ba.sin_port = htons(portno); 03228 03229 if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) { 03230 if (!inet_aton(val, &ba.sin_addr)) { 03231 ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val); 03232 memset(&ba.sin_addr, 0, sizeof(ba.sin_addr)); 03233 } 03234 } 03235 03236 03237 if ((asock > -1) && ((portno != oldportno) || !manager_enabled)) { 03238 #if 0 03239 /* Can't be done yet */ 03240 close(asock); 03241 asock = -1; 03242 #else 03243 ast_log(LOG_WARNING, "Unable to change management port / enabled\n"); 03244 #endif 03245 } 03246 03247 AST_LIST_LOCK(&users); 03248 03249 if ((ucfg = ast_config_load("users.conf"))) { 03250 while ((cat = ast_category_browse(ucfg, cat))) { 03251 int hasmanager = 0; 03252 struct ast_variable *var = NULL; 03253 03254 if (!strcasecmp(cat, "general")) { 03255 continue; 03256 } 03257 03258 if (!(hasmanager = ast_true(ast_variable_retrieve(ucfg, cat, "hasmanager")))) { 03259 continue; 03260 } 03261 03262 /* Look for an existing entry, if none found - create one and add it to the list */ 03263 if (!(user = ast_get_manager_by_name_locked(cat))) { 03264 if (!(user = ast_calloc(1, sizeof(*user)))) { 03265 break; 03266 } 03267 /* Copy name over */ 03268 ast_copy_string(user->username, cat, sizeof(user->username)); 03269 /* Insert into list */ 03270 AST_LIST_INSERT_TAIL(&users, user, list); 03271 } 03272 03273 /* Make sure we keep this user and don't destroy it during cleanup */ 03274 user->keep = 1; 03275 03276 for (var = ast_variable_browse(ucfg, cat); var; var = var->next) { 03277 if (!strcasecmp(var->name, "secret")) { 03278 if (user->secret) { 03279 free(user->secret); 03280 } 03281 user->secret = ast_strdup(var->value); 03282 } else if (!strcasecmp(var->name, "deny") ) { 03283 if (user->deny) { 03284 free(user->deny); 03285 } 03286 user->deny = ast_strdup(var->value); 03287 } else if (!strcasecmp(var->name, "permit") ) { 03288 if (user->permit) { 03289 free(user->permit); 03290 } 03291 user->permit = ast_strdup(var->value); 03292 } else if (!strcasecmp(var->name, "read") ) { 03293 if (user->read) { 03294 free(user->read); 03295 } 03296 user->read = ast_strdup(var->value); 03297 } else if (!strcasecmp(var->name, "write") ) { 03298 if (user->write) { 03299 free(user->write); 03300 } 03301 user->write = ast_strdup(var->value); 03302 } else if (!strcasecmp(var->name, "displayconnects") ) { 03303 user->displayconnects = ast_true(var->value); 03304 } else if (!strcasecmp(var->name, "hasmanager")) { 03305 /* already handled */ 03306 } else { 03307 ast_log(LOG_DEBUG, "%s is an unknown option (to the manager module).\n", var->name); 03308 } 03309 } 03310 } 03311 ast_config_destroy(ucfg); 03312 } 03313 03314 while ((cat = ast_category_browse(cfg, cat))) { 03315 struct ast_variable *var = NULL; 03316 03317 if (!strcasecmp(cat, "general")) 03318 continue; 03319 03320 /* Look for an existing entry, if none found - create one and add it to the list */ 03321 if (!(user = ast_get_manager_by_name_locked(cat))) { 03322 if (!(user = ast_calloc(1, sizeof(*user)))) 03323 break; 03324 /* Copy name over */ 03325 ast_copy_string(user->username, cat, sizeof(user->username)); 03326 /* Insert into list */ 03327 AST_LIST_INSERT_TAIL(&users, user, list); 03328 } 03329 03330 /* Make sure we keep this user and don't destroy it during cleanup */ 03331 user->keep = 1; 03332 03333 var = ast_variable_browse(cfg, cat); 03334 while (var) { 03335 if (!strcasecmp(var->name, "secret")) { 03336 if (user->secret) 03337 free(user->secret); 03338 user->secret = ast_strdup(var->value); 03339 } else if (!strcasecmp(var->name, "deny") ) { 03340 if (user->deny) 03341 free(user->deny); 03342 user->deny = ast_strdup(var->value); 03343 } else if (!strcasecmp(var->name, "permit") ) { 03344 if (user->permit) 03345 free(user->permit); 03346 user->permit = ast_strdup(var->value); 03347 } else if (!strcasecmp(var->name, "read") ) { 03348 if (user->read) 03349 free(user->read); 03350 user->read = ast_strdup(var->value); 03351 } else if (!strcasecmp(var->name, "write") ) { 03352 if (user->write) 03353 free(user->write); 03354 user->write = ast_strdup(var->value); 03355 } else if (!strcasecmp(var->name, "displayconnects") ) 03356 user->displayconnects = ast_true(var->value); 03357 else 03358 ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name); 03359 var = var->next; 03360 } 03361 } 03362 03363 /* Perform cleanup - essentially prune out old users that no longer exist */ 03364 AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) { 03365 if (user->keep) { 03366 user->keep = 0; 03367 continue; 03368 } 03369 /* We do not need to keep this user so take them out of the list */ 03370 AST_LIST_REMOVE_CURRENT(&users, list); 03371 /* Free their memory now */ 03372 if (user->secret) 03373 free(user->secret); 03374 if (user->deny) 03375 free(user->deny); 03376 if (user->permit) 03377 free(user->permit); 03378 if (user->read) 03379 free(user->read); 03380 if (user->write) 03381 free(user->write); 03382 free(user); 03383 } 03384 AST_LIST_TRAVERSE_SAFE_END 03385 03386 AST_LIST_UNLOCK(&users); 03387 03388 ast_config_destroy(cfg); 03389 03390 if (webmanager_enabled && manager_enabled) { 03391 if (!webregged) { 03392 ast_http_uri_link(&rawmanuri); 03393 ast_http_uri_link(&manageruri); 03394 ast_http_uri_link(&managerxmluri); 03395 webregged = 1; 03396 } 03397 } else { 03398 if (webregged) { 03399 ast_http_uri_unlink(&rawmanuri); 03400 ast_http_uri_unlink(&manageruri); 03401 ast_http_uri_unlink(&managerxmluri); 03402 webregged = 0; 03403 } 03404 } 03405 03406 if (newhttptimeout > 0) 03407 httptimeout = newhttptimeout; 03408 03409 /* If not enabled, do nothing */ 03410 if (!manager_enabled) 03411 return 0; 03412 03413 if (asock < 0) { 03414 asock = socket(AF_INET, SOCK_STREAM, 0); 03415 if (asock < 0) { 03416 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno)); 03417 return -1; 03418 } 03419 setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 03420 if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) { 03421 ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno)); 03422 close(asock); 03423 asock = -1; 03424 return -1; 03425 } 03426 if (listen(asock, 2)) { 03427 ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno)); 03428 close(asock); 03429 asock = -1; 03430 return -1; 03431 } 03432 flags = fcntl(asock, F_GETFL); 03433 fcntl(asock, F_SETFL, flags | O_NONBLOCK); 03434 if (option_verbose) 03435 ast_verbose("Asterisk Management interface listening on port %d\n", portno); 03436 ast_pthread_create_background(&t, NULL, accept_thread, NULL); 03437 } 03438 return 0; 03439 }
int reload_manager | ( | void | ) |
Definition at line 3441 of file manager.c.
References EVENT_FLAG_SYSTEM, init_manager(), and manager_event().
03442 { 03443 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n"); 03444 return init_manager(); 03445 }