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