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