#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, "%5d", &portno) != 1) { 03211 ast_log(LOG_WARNING, "Invalid port number '%s'\n", val); 03212 portno = DEFAULT_MANAGER_PORT; 03213 } 03214 } 03215 03216 if ((val = ast_variable_retrieve(cfg, "general", "displayconnects"))) { 03217 displayconnects = ast_true(val); 03218 } 03219 if ((val = ast_variable_retrieve(cfg, "general", "timestampevents"))) { 03220 timestampevents = ast_true(val); 03221 } 03222 if ((val = ast_variable_retrieve(cfg, "general", "httptimeout"))) { 03223 newhttptimeout = atoi(val); 03224 } 03225 03226 memset(&ba, 0, sizeof(ba)); 03227 ba.sin_family = AF_INET; 03228 ba.sin_port = htons(portno); 03229 03230 if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) { 03231 if (!inet_aton(val, &ba.sin_addr)) { 03232 ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val); 03233 memset(&ba.sin_addr, 0, sizeof(ba.sin_addr)); 03234 } 03235 } 03236 03237 03238 if ((asock > -1) && ((portno != oldportno) || !manager_enabled)) { 03239 #if 0 03240 /* Can't be done yet */ 03241 close(asock); 03242 asock = -1; 03243 #else 03244 ast_log(LOG_WARNING, "Unable to change management port / enabled\n"); 03245 #endif 03246 } 03247 03248 AST_LIST_LOCK(&users); 03249 03250 if ((ucfg = ast_config_load("users.conf"))) { 03251 while ((cat = ast_category_browse(ucfg, cat))) { 03252 int hasmanager = 0; 03253 struct ast_variable *var = NULL; 03254 03255 if (!strcasecmp(cat, "general")) { 03256 continue; 03257 } 03258 03259 if (!(hasmanager = ast_true(ast_variable_retrieve(ucfg, cat, "hasmanager")))) { 03260 continue; 03261 } 03262 03263 /* Look for an existing entry, if none found - create one and add it to the list */ 03264 if (!(user = ast_get_manager_by_name_locked(cat))) { 03265 if (!(user = ast_calloc(1, sizeof(*user)))) { 03266 break; 03267 } 03268 /* Copy name over */ 03269 ast_copy_string(user->username, cat, sizeof(user->username)); 03270 /* Insert into list */ 03271 AST_LIST_INSERT_TAIL(&users, user, list); 03272 } 03273 03274 /* Make sure we keep this user and don't destroy it during cleanup */ 03275 user->keep = 1; 03276 03277 for (var = ast_variable_browse(ucfg, cat); var; var = var->next) { 03278 if (!strcasecmp(var->name, "secret")) { 03279 if (user->secret) { 03280 free(user->secret); 03281 } 03282 user->secret = ast_strdup(var->value); 03283 } else if (!strcasecmp(var->name, "deny") ) { 03284 if (user->deny) { 03285 free(user->deny); 03286 } 03287 user->deny = ast_strdup(var->value); 03288 } else if (!strcasecmp(var->name, "permit") ) { 03289 if (user->permit) { 03290 free(user->permit); 03291 } 03292 user->permit = ast_strdup(var->value); 03293 } else if (!strcasecmp(var->name, "read") ) { 03294 if (user->read) { 03295 free(user->read); 03296 } 03297 user->read = ast_strdup(var->value); 03298 } else if (!strcasecmp(var->name, "write") ) { 03299 if (user->write) { 03300 free(user->write); 03301 } 03302 user->write = ast_strdup(var->value); 03303 } else if (!strcasecmp(var->name, "displayconnects") ) { 03304 user->displayconnects = ast_true(var->value); 03305 } else if (!strcasecmp(var->name, "hasmanager")) { 03306 /* already handled */ 03307 } else { 03308 ast_log(LOG_DEBUG, "%s is an unknown option (to the manager module).\n", var->name); 03309 } 03310 } 03311 } 03312 ast_config_destroy(ucfg); 03313 } 03314 03315 while ((cat = ast_category_browse(cfg, cat))) { 03316 struct ast_variable *var = NULL; 03317 03318 if (!strcasecmp(cat, "general")) 03319 continue; 03320 03321 /* Look for an existing entry, if none found - create one and add it to the list */ 03322 if (!(user = ast_get_manager_by_name_locked(cat))) { 03323 if (!(user = ast_calloc(1, sizeof(*user)))) 03324 break; 03325 /* Copy name over */ 03326 ast_copy_string(user->username, cat, sizeof(user->username)); 03327 /* Insert into list */ 03328 AST_LIST_INSERT_TAIL(&users, user, list); 03329 } 03330 03331 /* Make sure we keep this user and don't destroy it during cleanup */ 03332 user->keep = 1; 03333 03334 var = ast_variable_browse(cfg, cat); 03335 while (var) { 03336 if (!strcasecmp(var->name, "secret")) { 03337 if (user->secret) 03338 free(user->secret); 03339 user->secret = ast_strdup(var->value); 03340 } else if (!strcasecmp(var->name, "deny") ) { 03341 if (user->deny) 03342 free(user->deny); 03343 user->deny = ast_strdup(var->value); 03344 } else if (!strcasecmp(var->name, "permit") ) { 03345 if (user->permit) 03346 free(user->permit); 03347 user->permit = ast_strdup(var->value); 03348 } else if (!strcasecmp(var->name, "read") ) { 03349 if (user->read) 03350 free(user->read); 03351 user->read = ast_strdup(var->value); 03352 } else if (!strcasecmp(var->name, "write") ) { 03353 if (user->write) 03354 free(user->write); 03355 user->write = ast_strdup(var->value); 03356 } else if (!strcasecmp(var->name, "displayconnects") ) 03357 user->displayconnects = ast_true(var->value); 03358 else 03359 ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name); 03360 var = var->next; 03361 } 03362 } 03363 03364 /* Perform cleanup - essentially prune out old users that no longer exist */ 03365 AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) { 03366 if (user->keep) { 03367 user->keep = 0; 03368 continue; 03369 } 03370 /* We do not need to keep this user so take them out of the list */ 03371 AST_LIST_REMOVE_CURRENT(&users, list); 03372 /* Free their memory now */ 03373 if (user->secret) 03374 free(user->secret); 03375 if (user->deny) 03376 free(user->deny); 03377 if (user->permit) 03378 free(user->permit); 03379 if (user->read) 03380 free(user->read); 03381 if (user->write) 03382 free(user->write); 03383 free(user); 03384 } 03385 AST_LIST_TRAVERSE_SAFE_END 03386 03387 AST_LIST_UNLOCK(&users); 03388 03389 ast_config_destroy(cfg); 03390 03391 if (webmanager_enabled && manager_enabled) { 03392 if (!webregged) { 03393 ast_http_uri_link(&rawmanuri); 03394 ast_http_uri_link(&manageruri); 03395 ast_http_uri_link(&managerxmluri); 03396 webregged = 1; 03397 } 03398 } else { 03399 if (webregged) { 03400 ast_http_uri_unlink(&rawmanuri); 03401 ast_http_uri_unlink(&manageruri); 03402 ast_http_uri_unlink(&managerxmluri); 03403 webregged = 0; 03404 } 03405 } 03406 03407 if (newhttptimeout > 0) 03408 httptimeout = newhttptimeout; 03409 03410 /* If not enabled, do nothing */ 03411 if (!manager_enabled) 03412 return 0; 03413 03414 if (asock < 0) { 03415 asock = socket(AF_INET, SOCK_STREAM, 0); 03416 if (asock < 0) { 03417 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno)); 03418 return -1; 03419 } 03420 setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 03421 if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) { 03422 ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno)); 03423 close(asock); 03424 asock = -1; 03425 return -1; 03426 } 03427 if (listen(asock, 2)) { 03428 ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno)); 03429 close(asock); 03430 asock = -1; 03431 return -1; 03432 } 03433 flags = fcntl(asock, F_GETFL); 03434 fcntl(asock, F_SETFL, flags | O_NONBLOCK); 03435 if (option_verbose) 03436 ast_verbose("Asterisk Management interface listening on port %d\n", portno); 03437 ast_pthread_create_background(&t, NULL, accept_thread, NULL); 03438 } 03439 return 0; 03440 }
int reload_manager | ( | void | ) |
Definition at line 3442 of file manager.c.
References EVENT_FLAG_SYSTEM, init_manager(), and manager_event().
03443 { 03444 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n"); 03445 return init_manager(); 03446 }