#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
#include "asterisk/version.h"
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/manager.h"
#include "asterisk/config.h"
#include "asterisk/callerid.h"
#include "asterisk/lock.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/md5.h"
#include "asterisk/acl.h"
#include "asterisk/utils.h"
#include "asterisk/http.h"
#include "asterisk/threadstorage.h"
#include "asterisk/linkedlists.h"
#include "asterisk/term.h"
#include "asterisk/astobj2.h"
Go to the source code of this file.
Data Structures | |
struct | ast_manager_user |
struct | eventqent |
struct | fast_originate_helper |
struct | mansession |
struct | mansession_session |
struct | permalias |
struct | sessions |
struct | users |
struct | variable_count |
Defines | |
#define | ASTMAN_APPEND_BUF_INITSIZE 256 |
#define | MANAGER_EVENT_BUF_INITSIZE 256 |
#define | MAX_BLACKLIST_CMD_LEN 2 |
Enumerations | |
enum | { FORMAT_RAW, FORMAT_HTML, FORMAT_XML } |
Functions | |
static void * | accept_thread (void *ignore) |
static int | action_command (struct mansession *s, const struct message *m) |
action_command: Manager command "command" - execute CLI command | |
static int | action_coresettings (struct mansession *s, const struct message *m) |
Show PBX core settings information. | |
static int | action_corestatus (struct mansession *s, const struct message *m) |
Show PBX core status information. | |
static int | action_events (struct mansession *s, const struct message *m) |
static int | action_extensionstate (struct mansession *s, const struct message *m) |
static int | action_getconfig (struct mansession *s, const struct message *m) |
static int | action_getvar (struct mansession *s, const struct message *m) |
static int | action_hangup (struct mansession *s, const struct message *m) |
static int | action_listcommands (struct mansession *s, const struct message *m) |
static int | action_logoff (struct mansession *s, const struct message *m) |
static int | action_mailboxcount (struct mansession *s, const struct message *m) |
static int | action_mailboxstatus (struct mansession *s, const struct message *m) |
static int | action_originate (struct mansession *s, const struct message *m) |
static int | action_ping (struct mansession *s, const struct message *m) |
static int | action_redirect (struct mansession *s, const struct message *m) |
action_redirect: The redirect manager command | |
static int | action_setvar (struct mansession *s, const struct message *m) |
static int | action_status (struct mansession *s, const struct message *m) |
Manager "status" command to show channels. | |
static int | action_timeout (struct mansession *s, const struct message *m) |
static int | action_updateconfig (struct mansession *s, const struct message *m) |
static int | action_userevent (struct mansession *s, const struct message *m) |
static int | action_waitevent (struct mansession *s, const struct message *m) |
static int | append_event (const char *str, int category) |
static struct ast_manager_user * | ast_get_manager_by_name_locked (const char *name) |
static int | ast_instring (const char *bigstr, const char *smallstr, char delim) |
static int | ast_is_number (const char *string) |
int | ast_manager_register2 (const char *action, int auth, 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 | |
static int | ast_manager_register_struct (struct manager_action *act) |
int | ast_manager_unregister (char *action) |
void | astman_append (struct mansession *s, const char *fmt,...) |
static void | astman_append_buf_init (void) |
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. | |
static int | authenticate (struct mansession *s, const struct message *m) |
static char * | authority_to_str (int authority, char *res, int reslen) |
Convert authority code to string with serveral options. | |
static int | check_blacklist (const char *cmd) |
int | check_manager_enabled () |
Check if AMI is enabled. | |
int | check_webmanager_enabled () |
Check if AMI/HTTP is enabled. | |
static char * | complete_show_mancmd (const char *line, const char *word, int pos, int state) |
static int | compress_char (char c) |
static void | destroy_session (struct mansession_session *s) |
static int | do_message (struct mansession *s) |
static void * | fast_originate (void *data) |
static struct mansession_session * | find_session (uint32_t ident) |
static void | free_session (struct mansession_session *s) |
static char * | generic_http_callback (int format, struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength) |
static int | get_input (struct mansession_session *s, char *output) |
static int | get_perm (const char *instr) |
static int | handle_showmanager (int fd, int argc, char *argv[]) |
static int | handle_showmanagers (int fd, int argc, char *argv[]) |
static int | handle_showmancmd (int fd, int argc, char *argv[]) |
static int | handle_showmancmds (int fd, int argc, char *argv[]) |
CLI command Should change to "manager show commands". | |
static int | handle_showmanconn (int fd, int argc, char *argv[]) |
CLI command show manager connected. | |
static int | handle_showmaneventq (int fd, int argc, char *argv[]) |
CLI command show manager eventq. | |
static void | handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg) |
static char * | html_translate (char *in) |
int | init_manager (void) |
int | manager_event (int category, const char *event, const char *fmt,...) |
manager_event: Send AMI event to client | |
static void | manager_event_buf_init (void) |
static char * | manager_http_callback (struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength) |
static int | manager_state_cb (char *context, char *exten, int state, void *data) |
static char * | mxml_http_callback (struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength) |
static int | process_events (struct mansession *s) |
static int | process_message (struct mansession *s, const struct message *m) |
static char * | rawman_http_callback (struct sockaddr_in *requestor, const char *uri, struct ast_variable *params, int *status, char **title, int *contentlength) |
int | reload_manager (void) |
static void * | session_do (void *data) |
static int | set_eventmask (struct mansession_session *s, const char *eventmask) |
Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm. | |
static int | strings_to_mask (const char *string) |
static void | unuse_eventqent (struct eventqent *e) |
static int | variable_count_cmp_fn (void *obj, void *vstr, int flags) |
static int | variable_count_hash_fn (const void *vvc, const int flags) |
static void | xml_copy_escape (char **dst, size_t *maxlen, const char *src, int lower) |
static char * | xml_translate (char *in, struct ast_variable *vars) |
Variables | |
static ast_rwlock_t | actionlock = PTHREAD_RWLOCK_INITIALIZER |
static int | asock = -1 |
static struct ast_threadstorage | astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = astman_append_buf_init , } |
static int | authlimit |
static int | authtimeout |
static int | block_sockets |
static int | broken_events_action |
static struct ast_cli_entry | cli_manager [] |
static struct ast_cli_entry | cli_show_manager_command_deprecated |
static struct ast_cli_entry | cli_show_manager_commands_deprecated |
static struct ast_cli_entry | cli_show_manager_connected_deprecated |
static struct ast_cli_entry | cli_show_manager_eventq_deprecated |
struct { | |
char * words [AST_MAX_CMD_LEN] | |
} | command_blacklist [] |
static char * | contenttype [] = { "plain", "html", "xml" } |
static const int | DEFAULT_AUTHLIMIT = 50 |
static const int | DEFAULT_AUTHTIMEOUT = 30 |
static const int | DEFAULT_BLOCKSOCKETS = 0 |
static const int | DEFAULT_BROKENEVENTSACTION = 0 |
static const int | DEFAULT_DISPLAYCONNECTS = 1 |
static const int | DEFAULT_ENABLED = 0 |
static const int | DEFAULT_HTTPTIMEOUT = 60 |
static const int | DEFAULT_TIMESTAMPEVENTS = 0 |
static const int | DEFAULT_WEBENABLED = 0 |
static int | displayconnects |
static struct manager_action * | first_action |
static int | httptimeout |
static int | manager_enabled = 0 |
static struct ast_threadstorage | manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = manager_event_buf_init , } |
ast_http_uri | manageruri |
ast_http_uri | managerxmluri |
static char | mandescr_command [] |
static char | mandescr_coresettings [] |
static char | mandescr_corestatus [] |
static char | mandescr_events [] |
static char | mandescr_extensionstate [] |
static char | mandescr_getconfig [] |
static char | mandescr_getvar [] |
static char | mandescr_hangup [] |
static char | mandescr_listcommands [] |
static char | mandescr_logoff [] |
static char | mandescr_mailboxcount [] |
static char | mandescr_mailboxstatus [] |
Help text for manager command mailboxstatus. | |
static char | mandescr_originate [] |
static char | mandescr_ping [] |
Manager PING. | |
static char | mandescr_redirect [] |
static char | mandescr_setvar [] |
static char | mandescr_timeout [] |
static char | mandescr_updateconfig [] |
static char | mandescr_userevent [] |
static char | mandescr_waitevent [] |
Manager WAITEVENT. | |
eventqent * | master_eventq = NULL |
static int | num_sessions |
static struct permalias | perms [] |
static int | portno = DEFAULT_MANAGER_PORT |
ast_http_uri | rawmanuri |
static int | registered = 0 |
static char | showmanager_help [] |
static char | showmanagers_help [] |
static char | showmancmd_help [] |
static char | showmancmds_help [] |
static char | showmanconn_help [] |
static char | showmaneventq_help [] |
static pthread_t | t |
static int | timestampevents |
static int | unauth_sessions = 0 |
static int | webmanager_enabled = 0 |
static int | webregged = 0 |
Definition in file manager.c.
anonymous enum |
Definition at line 2976 of file manager.c.
02976 { 02977 FORMAT_RAW, 02978 FORMAT_HTML, 02979 FORMAT_XML, 02980 };
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 2938 of file manager.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), and s.
02939 { 02940 int result = 0; 02941 struct mansession_session *s; 02942 02943 AST_LIST_LOCK(&sessions); 02944 AST_LIST_TRAVERSE(&sessions, s, list) { 02945 ast_mutex_lock(&s->__lock); 02946 if ((s->managerid == ident) && (s->readperm & perm)) { 02947 result = 1; 02948 ast_mutex_unlock(&s->__lock); 02949 break; 02950 } 02951 ast_mutex_unlock(&s->__lock); 02952 } 02953 AST_LIST_UNLOCK(&sessions); 02954 return result; 02955 }
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 2957 of file manager.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), and s.
02958 { 02959 int result = 0; 02960 struct mansession_session *s; 02961 02962 AST_LIST_LOCK(&sessions); 02963 AST_LIST_TRAVERSE(&sessions, s, list) { 02964 ast_mutex_lock(&s->__lock); 02965 if ((s->managerid == ident) && (s->writeperm & perm)) { 02966 result = 1; 02967 ast_mutex_unlock(&s->__lock); 02968 break; 02969 } 02970 ast_mutex_unlock(&s->__lock); 02971 } 02972 AST_LIST_UNLOCK(&sessions); 02973 return result; 02974 }
static struct mansession_session* find_session | ( | uint32_t | ident | ) | [static] |
END Doxygen group
Definition at line 2920 of file manager.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), and s.
02921 { 02922 struct mansession_session *s; 02923 02924 AST_LIST_LOCK(&sessions); 02925 AST_LIST_TRAVERSE(&sessions, s, list) { 02926 ast_mutex_lock(&s->__lock); 02927 if (s->sessiontimeout && (s->managerid == ident) && !s->needdestroy) { 02928 s->inuse++; 02929 break; 02930 } 02931 ast_mutex_unlock(&s->__lock); 02932 } 02933 AST_LIST_UNLOCK(&sessions); 02934 02935 return s; 02936 }
static char* generic_http_callback | ( | int | format, | |
struct sockaddr_in * | requestor, | |||
const char * | uri, | |||
struct ast_variable * | params, | |||
int * | status, | |||
char ** | title, | |||
int * | contentlength | |||
) | [static] |
Definition at line 2983 of file manager.c.
References len(), ast_variable::name, ast_variable::next, s, and ast_variable::value.
Referenced by manager_http_callback(), mxml_http_callback(), and rawman_http_callback().
02984 { 02985 struct mansession_session *s = NULL; 02986 struct mansession ss = { .session = NULL, }; 02987 uint32_t ident = 0; 02988 char workspace[512]; 02989 char cookie[128]; 02990 size_t len = sizeof(workspace); 02991 int blastaway = 0; 02992 char *c = workspace; 02993 char *retval = NULL; 02994 struct ast_variable *v; 02995 char template[] = "/tmp/ast-http-XXXXXX"; 02996 02997 for (v = params; v; v = v->next) { 02998 if (!strcasecmp(v->name, "mansession_id")) { 02999 sscanf(v->value, "%30x", &ident); 03000 break; 03001 } 03002 } 03003 03004 if (!(s = find_session(ident))) { 03005 /* Create new session */ 03006 if (!(s = ast_calloc(1, sizeof(*s)))) { 03007 *status = 500; 03008 goto generic_callback_out; 03009 } 03010 memcpy(&s->sin, requestor, sizeof(s->sin)); 03011 s->fd = -1; 03012 s->waiting_thread = AST_PTHREADT_NULL; 03013 s->send_events = 0; 03014 ast_mutex_init(&s->__lock); 03015 ast_mutex_lock(&s->__lock); 03016 s->inuse = 1; 03017 /*!\note There is approximately a 1 in 1.8E19 chance that the following 03018 * calculation will produce 0, which is an invalid ID, but due to the 03019 * properties of the rand() function (and the constantcy of s), that 03020 * won't happen twice in a row. 03021 */ 03022 while ((s->managerid = rand() ^ (unsigned long) s) == 0); 03023 AST_LIST_LOCK(&sessions); 03024 AST_LIST_INSERT_HEAD(&sessions, s, list); 03025 /* Hook into the last spot in the event queue */ 03026 s->eventq = master_eventq; 03027 while (s->eventq->next) 03028 s->eventq = s->eventq->next; 03029 ast_atomic_fetchadd_int(&s->eventq->usecount, 1); 03030 ast_atomic_fetchadd_int(&num_sessions, 1); 03031 AST_LIST_UNLOCK(&sessions); 03032 } 03033 03034 /* Reset HTTP timeout. If we're not yet authenticated, keep it extremely short */ 03035 time(&s->sessiontimeout); 03036 if (!s->authenticated && (httptimeout > 5)) 03037 s->sessiontimeout += 5; 03038 else 03039 s->sessiontimeout += httptimeout; 03040 ss.session = s; 03041 ast_mutex_unlock(&s->__lock); 03042 03043 if ((ss.fd = mkstemp(template)) > -1) { 03044 unlink(template); 03045 } 03046 03047 if (s) { 03048 struct message m = { 0 }; 03049 char tmp[80]; 03050 unsigned int x; 03051 size_t hdrlen; 03052 03053 for (x = 0, v = params; v && (x < AST_MAX_MANHEADERS); x++, v = v->next) { 03054 hdrlen = strlen(v->name) + strlen(v->value) + 3; 03055 m.headers[m.hdrcount] = alloca(hdrlen); 03056 snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value); 03057 m.hdrcount = x + 1; 03058 } 03059 03060 if (process_message(&ss, &m)) { 03061 if (s->authenticated) { 03062 if (option_verbose > 1) { 03063 if (displayconnects) 03064 ast_verbose(VERBOSE_PREFIX_2 "HTTP Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr)); 03065 } 03066 ast_log(LOG_EVENT, "HTTP Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr)); 03067 } else { 03068 if (option_verbose > 1) { 03069 if (displayconnects) 03070 ast_verbose(VERBOSE_PREFIX_2 "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(s->sin.sin_addr)); 03071 } 03072 ast_log(LOG_EVENT, "HTTP Failed attempt from %s\n", ast_inet_ntoa(s->sin.sin_addr)); 03073 } 03074 s->needdestroy = 1; 03075 } 03076 ast_build_string(&c, &len, "Content-type: text/%s\r\n", contenttype[format]); 03077 sprintf(tmp, "%08x", s->managerid); 03078 ast_build_string(&c, &len, "%s\r\n", ast_http_setcookie("mansession_id", tmp, httptimeout, cookie, sizeof(cookie))); 03079 if (format == FORMAT_HTML) 03080 ast_build_string(&c, &len, "<title>Asterisk™ Manager Interface</title>"); 03081 if (format == FORMAT_XML) { 03082 ast_build_string(&c, &len, "<ajax-response>\n"); 03083 } else if (format == FORMAT_HTML) { 03084 ast_build_string(&c, &len, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n"); 03085 ast_build_string(&c, &len, "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\"><h1> Manager Tester</h1></td></tr>\r\n"); 03086 } 03087 ast_mutex_lock(&s->__lock); 03088 if (ss.fd > -1) { 03089 char *buf; 03090 size_t l; 03091 ssize_t res; 03092 03093 /* Make sure that our buffer is NULL terminated */ 03094 while ((res = write(ss.fd, "", 1)) < 1) { 03095 if (res == -1) { 03096 ast_log(LOG_ERROR, "Failed to terminate manager response output: %s\n", strerror(errno)); 03097 break; 03098 } 03099 } 03100 03101 if (res == 1 && (l = lseek(ss.fd, 0, SEEK_END)) > 0) { 03102 if (MAP_FAILED == (buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_SHARED, ss.fd, 0))) { 03103 ast_log(LOG_WARNING, "mmap failed. Manager request output was not processed\n"); 03104 } else { 03105 char *tmpbuf; 03106 if (format == FORMAT_XML) 03107 tmpbuf = xml_translate(buf, params); 03108 else if (format == FORMAT_HTML) 03109 tmpbuf = html_translate(buf); 03110 else 03111 tmpbuf = buf; 03112 if (tmpbuf) { 03113 size_t wlen, tlen; 03114 if ((retval = malloc((wlen = strlen(workspace)) + (tlen = strlen(tmpbuf)) + 128))) { 03115 strcpy(retval, workspace); 03116 strcpy(retval + wlen, tmpbuf); 03117 c = retval + wlen + tlen; 03118 /* Leftover space for footer, if any */ 03119 len = 120; 03120 } 03121 } 03122 if (tmpbuf != buf) 03123 free(tmpbuf); 03124 free(s->outputstr); 03125 s->outputstr = NULL; 03126 munmap(buf, l); 03127 } 03128 } 03129 close(ss.fd); 03130 ss.fd = -1; 03131 } else if (s->outputstr) { 03132 char *tmp; 03133 if (format == FORMAT_XML) 03134 tmp = xml_translate(s->outputstr->str, params); 03135 else if (format == FORMAT_HTML) 03136 tmp = html_translate(s->outputstr->str); 03137 else 03138 tmp = s->outputstr->str; 03139 if (tmp) { 03140 retval = malloc(strlen(workspace) + strlen(tmp) + 128); 03141 if (retval) { 03142 strcpy(retval, workspace); 03143 strcpy(retval + strlen(retval), tmp); 03144 c = retval + strlen(retval); 03145 len = 120; 03146 } 03147 } 03148 if (tmp != s->outputstr->str) 03149 free(tmp); 03150 free(s->outputstr); 03151 s->outputstr = NULL; 03152 } 03153 ast_mutex_unlock(&s->__lock); 03154 /* Still okay because c would safely be pointing to workspace even 03155 if retval failed to allocate above */ 03156 if (format == FORMAT_XML) { 03157 ast_build_string(&c, &len, "</ajax-response>\n"); 03158 } else if (format == FORMAT_HTML) 03159 ast_build_string(&c, &len, "</table></body>\r\n"); 03160 } else { 03161 *status = 500; 03162 *title = strdup("Server Error"); 03163 } 03164 ast_mutex_lock(&s->__lock); 03165 if (s->needdestroy) { 03166 if (s->inuse == 1) { 03167 ast_log(LOG_DEBUG, "Need destroy, doing it now!\n"); 03168 blastaway = 1; 03169 } else { 03170 ast_log(LOG_DEBUG, "Need destroy, but can't do it yet!\n"); 03171 if (s->waiting_thread != AST_PTHREADT_NULL) 03172 pthread_kill(s->waiting_thread, SIGURG); 03173 s->inuse--; 03174 } 03175 } else 03176 s->inuse--; 03177 ast_mutex_unlock(&s->__lock); 03178 03179 if (blastaway) 03180 destroy_session(s); 03181 generic_callback_out: 03182 if (*status != 200) 03183 return ast_http_error(500, "Server Error", NULL, "Internal Server Error (out of memory)\n"); 03184 return retval; 03185 }
int init_manager | ( | void | ) |
Called by Asterisk initialization
Definition at line 3226 of file manager.c.
References 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(), authlimit, authtimeout, block_sockets, broken_events_action, cli_manager, DEFAULT_AUTHLIMIT, DEFAULT_AUTHTIMEOUT, DEFAULT_BLOCKSOCKETS, DEFAULT_BROKENEVENTSACTION, DEFAULT_DISPLAYCONNECTS, DEFAULT_HTTPTIMEOUT, DEFAULT_MANAGER_PORT, DEFAULT_TIMESTAMPEVENTS, DEFAULT_WEBENABLED, ast_manager_user::deny, displayconnects, ast_manager_user::displayconnects, EVENT_FLAG_CALL, EVENT_FLAG_COMMAND, EVENT_FLAG_CONFIG, EVENT_FLAG_SYSTEM, EVENT_FLAG_USER, ast_channel::flags, free, httptimeout, ast_manager_user::keep, LOG_DEBUG, LOG_WARNING, manager_enabled, manager_state_cb(), 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().
03227 { 03228 struct ast_config *cfg = NULL, *ucfg = NULL; 03229 const char *val; 03230 char *cat = NULL; 03231 int oldportno = portno; 03232 static struct sockaddr_in ba; 03233 int x = 1; 03234 int flags; 03235 int webenabled = DEFAULT_WEBENABLED; 03236 int newhttptimeout = DEFAULT_HTTPTIMEOUT; 03237 struct ast_manager_user *user = NULL; 03238 03239 if (!registered) { 03240 /* Register default actions */ 03241 ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping); 03242 ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events); 03243 ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff); 03244 ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup); 03245 ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" ); 03246 ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar ); 03247 ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar ); 03248 ast_manager_register2("GetConfig", EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig); 03249 ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig); 03250 ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect ); 03251 ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate); 03252 ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command ); 03253 ast_manager_register2("ExtensionState", EVENT_FLAG_CALL, action_extensionstate, "Check Extension Status", mandescr_extensionstate ); 03254 ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout ); 03255 ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus ); 03256 ast_manager_register2("MailboxCount", EVENT_FLAG_CALL, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount ); 03257 ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands); 03258 ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent); 03259 ast_manager_register2("CoreSettings", EVENT_FLAG_SYSTEM, action_coresettings, "Show PBX core settings (version etc)", mandescr_coresettings); 03260 ast_manager_register2("CoreStatus", EVENT_FLAG_SYSTEM, action_corestatus, "Show PBX core status variables", mandescr_corestatus); 03261 ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent); 03262 03263 ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry)); 03264 ast_extension_state_add(NULL, NULL, manager_state_cb, NULL); 03265 registered = 1; 03266 /* Append placeholder event so master_eventq never runs dry */ 03267 append_event("Event: Placeholder\r\n\r\n", 0); 03268 } 03269 03270 portno = DEFAULT_MANAGER_PORT; 03271 displayconnects = DEFAULT_DISPLAYCONNECTS; 03272 broken_events_action = DEFAULT_BROKENEVENTSACTION; 03273 block_sockets = DEFAULT_BLOCKSOCKETS; 03274 timestampevents = DEFAULT_TIMESTAMPEVENTS; 03275 httptimeout = DEFAULT_HTTPTIMEOUT; 03276 authtimeout = DEFAULT_AUTHTIMEOUT; 03277 authlimit = DEFAULT_AUTHLIMIT; 03278 03279 cfg = ast_config_load("manager.conf"); 03280 if (!cfg) { 03281 ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf. Call management disabled.\n"); 03282 return 0; 03283 } 03284 if ((val = ast_variable_retrieve(cfg, "general", "enabled"))) { 03285 manager_enabled = ast_true(val); 03286 } 03287 if ((val = ast_variable_retrieve(cfg, "general", "block-sockets"))) { 03288 block_sockets = ast_true(val); 03289 } 03290 if((val = ast_variable_retrieve(cfg, "general", "webenabled"))) { 03291 webmanager_enabled = ast_true(val); 03292 } 03293 if ((val = ast_variable_retrieve(cfg, "general", "port"))) { 03294 if (sscanf(val, "%5d", &portno) != 1) { 03295 ast_log(LOG_WARNING, "Invalid port number '%s'\n", val); 03296 portno = DEFAULT_MANAGER_PORT; 03297 } 03298 } 03299 03300 if ((val = ast_variable_retrieve(cfg, "general", "displayconnects"))) 03301 displayconnects = ast_true(val); 03302 03303 if ((val = ast_variable_retrieve(cfg, "general", "brokeneventsaction"))) 03304 broken_events_action = ast_true(val); 03305 03306 if ((val = ast_variable_retrieve(cfg, "general", "timestampevents"))) 03307 timestampevents = ast_true(val); 03308 03309 if ((val = ast_variable_retrieve(cfg, "general", "httptimeout"))) 03310 newhttptimeout = atoi(val); 03311 03312 if ((val = ast_variable_retrieve(cfg, "general", "authtimeout"))) { 03313 int timeout = atoi(val); 03314 03315 if (timeout < 1) { 03316 ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", val); 03317 } else { 03318 authtimeout = timeout; 03319 } 03320 } 03321 03322 if ((val = ast_variable_retrieve(cfg, "general", "authlimit"))) { 03323 int limit = atoi(val); 03324 03325 if (limit < 1) { 03326 ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", val); 03327 } else { 03328 authlimit = limit; 03329 } 03330 } 03331 03332 memset(&ba, 0, sizeof(ba)); 03333 ba.sin_family = AF_INET; 03334 ba.sin_port = htons(portno); 03335 03336 if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) { 03337 if (!inet_aton(val, &ba.sin_addr)) { 03338 ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val); 03339 memset(&ba.sin_addr, 0, sizeof(ba.sin_addr)); 03340 } 03341 } 03342 03343 03344 if ((asock > -1) && ((portno != oldportno) || !manager_enabled)) { 03345 #if 0 03346 /* Can't be done yet */ 03347 close(asock); 03348 asock = -1; 03349 #else 03350 ast_log(LOG_WARNING, "Unable to change management port / enabled\n"); 03351 #endif 03352 } 03353 03354 AST_LIST_LOCK(&users); 03355 03356 if ((ucfg = ast_config_load("users.conf"))) { 03357 while ((cat = ast_category_browse(ucfg, cat))) { 03358 int hasmanager = 0; 03359 struct ast_variable *var = NULL; 03360 03361 if (!strcasecmp(cat, "general")) { 03362 continue; 03363 } 03364 03365 if (!(hasmanager = ast_true(ast_variable_retrieve(ucfg, cat, "hasmanager")))) { 03366 continue; 03367 } 03368 03369 /* Look for an existing entry, if none found - create one and add it to the list */ 03370 if (!(user = ast_get_manager_by_name_locked(cat))) { 03371 if (!(user = ast_calloc(1, sizeof(*user)))) { 03372 break; 03373 } 03374 /* Copy name over */ 03375 ast_copy_string(user->username, cat, sizeof(user->username)); 03376 /* Insert into list */ 03377 AST_LIST_INSERT_TAIL(&users, user, list); 03378 } 03379 03380 /* Make sure we keep this user and don't destroy it during cleanup */ 03381 user->keep = 1; 03382 03383 for (var = ast_variable_browse(ucfg, cat); var; var = var->next) { 03384 if (!strcasecmp(var->name, "secret")) { 03385 if (user->secret) { 03386 free(user->secret); 03387 } 03388 user->secret = ast_strdup(var->value); 03389 } else if (!strcasecmp(var->name, "deny") ) { 03390 if (user->deny) { 03391 free(user->deny); 03392 } 03393 user->deny = ast_strdup(var->value); 03394 } else if (!strcasecmp(var->name, "permit") ) { 03395 if (user->permit) { 03396 free(user->permit); 03397 } 03398 user->permit = ast_strdup(var->value); 03399 } else if (!strcasecmp(var->name, "read") ) { 03400 if (user->read) { 03401 free(user->read); 03402 } 03403 user->read = ast_strdup(var->value); 03404 } else if (!strcasecmp(var->name, "write") ) { 03405 if (user->write) { 03406 free(user->write); 03407 } 03408 user->write = ast_strdup(var->value); 03409 } else if (!strcasecmp(var->name, "displayconnects") ) { 03410 user->displayconnects = ast_true(var->value); 03411 } else if (!strcasecmp(var->name, "hasmanager")) { 03412 /* already handled */ 03413 } else { 03414 ast_log(LOG_DEBUG, "%s is an unknown option (to the manager module).\n", var->name); 03415 } 03416 } 03417 } 03418 ast_config_destroy(ucfg); 03419 } 03420 03421 while ((cat = ast_category_browse(cfg, cat))) { 03422 struct ast_variable *var = NULL; 03423 03424 if (!strcasecmp(cat, "general")) 03425 continue; 03426 03427 /* Look for an existing entry, if none found - create one and add it to the list */ 03428 if (!(user = ast_get_manager_by_name_locked(cat))) { 03429 if (!(user = ast_calloc(1, sizeof(*user)))) 03430 break; 03431 /* Copy name over */ 03432 ast_copy_string(user->username, cat, sizeof(user->username)); 03433 /* Insert into list */ 03434 AST_LIST_INSERT_TAIL(&users, user, list); 03435 } 03436 03437 /* Make sure we keep this user and don't destroy it during cleanup */ 03438 user->keep = 1; 03439 03440 var = ast_variable_browse(cfg, cat); 03441 while (var) { 03442 if (!strcasecmp(var->name, "secret")) { 03443 if (user->secret) 03444 free(user->secret); 03445 user->secret = ast_strdup(var->value); 03446 } else if (!strcasecmp(var->name, "deny") ) { 03447 if (user->deny) 03448 free(user->deny); 03449 user->deny = ast_strdup(var->value); 03450 } else if (!strcasecmp(var->name, "permit") ) { 03451 if (user->permit) 03452 free(user->permit); 03453 user->permit = ast_strdup(var->value); 03454 } else if (!strcasecmp(var->name, "read") ) { 03455 if (user->read) 03456 free(user->read); 03457 user->read = ast_strdup(var->value); 03458 } else if (!strcasecmp(var->name, "write") ) { 03459 if (user->write) 03460 free(user->write); 03461 user->write = ast_strdup(var->value); 03462 } else if (!strcasecmp(var->name, "displayconnects") ) 03463 user->displayconnects = ast_true(var->value); 03464 else 03465 ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name); 03466 var = var->next; 03467 } 03468 } 03469 03470 /* Perform cleanup - essentially prune out old users that no longer exist */ 03471 AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) { 03472 if (user->keep) { 03473 user->keep = 0; 03474 continue; 03475 } 03476 /* We do not need to keep this user so take them out of the list */ 03477 AST_LIST_REMOVE_CURRENT(&users, list); 03478 /* Free their memory now */ 03479 if (user->secret) 03480 free(user->secret); 03481 if (user->deny) 03482 free(user->deny); 03483 if (user->permit) 03484 free(user->permit); 03485 if (user->read) 03486 free(user->read); 03487 if (user->write) 03488 free(user->write); 03489 free(user); 03490 } 03491 AST_LIST_TRAVERSE_SAFE_END 03492 03493 AST_LIST_UNLOCK(&users); 03494 03495 ast_config_destroy(cfg); 03496 03497 if (webmanager_enabled && manager_enabled) { 03498 if (!webregged) { 03499 ast_http_uri_link(&rawmanuri); 03500 ast_http_uri_link(&manageruri); 03501 ast_http_uri_link(&managerxmluri); 03502 webregged = 1; 03503 } 03504 } else { 03505 if (webregged) { 03506 ast_http_uri_unlink(&rawmanuri); 03507 ast_http_uri_unlink(&manageruri); 03508 ast_http_uri_unlink(&managerxmluri); 03509 webregged = 0; 03510 } 03511 } 03512 03513 if (newhttptimeout > 0) 03514 httptimeout = newhttptimeout; 03515 03516 /* If not enabled, do nothing */ 03517 if (!manager_enabled) 03518 return 0; 03519 03520 if (asock < 0) { 03521 asock = socket(AF_INET, SOCK_STREAM, 0); 03522 if (asock < 0) { 03523 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno)); 03524 return -1; 03525 } 03526 setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 03527 if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) { 03528 ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno)); 03529 close(asock); 03530 asock = -1; 03531 return -1; 03532 } 03533 if (listen(asock, 2)) { 03534 ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno)); 03535 close(asock); 03536 asock = -1; 03537 return -1; 03538 } 03539 flags = fcntl(asock, F_GETFL); 03540 fcntl(asock, F_SETFL, flags | O_NONBLOCK); 03541 if (option_verbose) 03542 ast_verbose("Asterisk Management interface listening on port %d\n", portno); 03543 ast_pthread_create_background(&t, NULL, accept_thread, NULL); 03544 } 03545 return 0; 03546 }
static char* manager_http_callback | ( | struct sockaddr_in * | requestor, | |
const char * | uri, | |||
struct ast_variable * | params, | |||
int * | status, | |||
char ** | title, | |||
int * | contentlength | |||
) | [static] |
Definition at line 3187 of file manager.c.
References FORMAT_HTML, and generic_http_callback().
03188 { 03189 return generic_http_callback(FORMAT_HTML, requestor, uri, params, status, title, contentlength); 03190 }
static char* mxml_http_callback | ( | struct sockaddr_in * | requestor, | |
const char * | uri, | |||
struct ast_variable * | params, | |||
int * | status, | |||
char ** | title, | |||
int * | contentlength | |||
) | [static] |
Definition at line 3192 of file manager.c.
References FORMAT_XML, and generic_http_callback().
03193 { 03194 return generic_http_callback(FORMAT_XML, requestor, uri, params, status, title, contentlength); 03195 }
static char* rawman_http_callback | ( | struct sockaddr_in * | requestor, | |
const char * | uri, | |||
struct ast_variable * | params, | |||
int * | status, | |||
char ** | title, | |||
int * | contentlength | |||
) | [static] |
Definition at line 3197 of file manager.c.
References FORMAT_RAW, and generic_http_callback().
03198 { 03199 return generic_http_callback(FORMAT_RAW, requestor, uri, params, status, title, contentlength); 03200 }
int reload_manager | ( | void | ) |
Definition at line 3548 of file manager.c.
References EVENT_FLAG_SYSTEM, init_manager(), and manager_event().
03549 { 03550 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n"); 03551 return init_manager(); 03552 }
char* contenttype[] = { "plain", "html", "xml" } [static] |
struct ast_http_uri manageruri |
struct ast_http_uri managerxmluri |
struct ast_http_uri rawmanuri |
int registered = 0 [static] |
char* words[AST_MAX_CMD_LEN] |