#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 "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 | permalias |
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_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_message (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) |
static | AST_LIST_HEAD_STATIC (users, ast_manager_user) |
static | AST_LIST_HEAD_STATIC (sessions, mansession) |
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) |
AST_RWLOCK_DEFINE_STATIC (actionlock) | |
AST_THREADSTORAGE (astman_append_buf, astman_append_buf_init) | |
AST_THREADSTORAGE (manager_event_buf, manager_event_buf_init) | |
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. | |
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) |
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 *s) |
static int | do_message (struct mansession *s) |
static void * | fast_originate (void *data) |
static struct mansession * | find_session (uint32_t ident) |
static void | free_session (struct mansession *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 *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 connected. | |
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 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, char *cid_num, char *cid_name) |
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 *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 int | asock = -1 |
static int | block_sockets |
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 int | displayconnects = 1 |
static int | enabled |
static struct manager_action * | first_action |
static int | httptimeout = 60 |
struct ast_http_uri | manageruri |
struct ast_http_uri | managerxmluri |
static char | mandescr_command [] |
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_message [] |
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. | |
struct eventqent * | master_eventq = NULL |
static int | num_sessions |
static struct permalias | perms [] |
static int | portno = DEFAULT_MANAGER_PORT |
struct 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 | webregged = 0 |
Channel Management and more
Definition in file manager.c.
anonymous enum |
Definition at line 2777 of file manager.c.
02777 { 02778 FORMAT_RAW, 02779 FORMAT_HTML, 02780 FORMAT_XML, 02781 };
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 2739 of file manager.c.
References mansession::__lock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession::managerid, mansession::readperm, and s.
02740 { 02741 int result = 0; 02742 struct mansession *s; 02743 02744 AST_LIST_LOCK(&sessions); 02745 AST_LIST_TRAVERSE(&sessions, s, list) { 02746 ast_mutex_lock(&s->__lock); 02747 if ((s->managerid == ident) && (s->readperm & perm)) { 02748 result = 1; 02749 ast_mutex_unlock(&s->__lock); 02750 break; 02751 } 02752 ast_mutex_unlock(&s->__lock); 02753 } 02754 AST_LIST_UNLOCK(&sessions); 02755 return result; 02756 }
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 2758 of file manager.c.
References mansession::__lock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession::managerid, s, and mansession::writeperm.
02759 { 02760 int result = 0; 02761 struct mansession *s; 02762 02763 AST_LIST_LOCK(&sessions); 02764 AST_LIST_TRAVERSE(&sessions, s, list) { 02765 ast_mutex_lock(&s->__lock); 02766 if ((s->managerid == ident) && (s->writeperm & perm)) { 02767 result = 1; 02768 ast_mutex_unlock(&s->__lock); 02769 break; 02770 } 02771 ast_mutex_unlock(&s->__lock); 02772 } 02773 AST_LIST_UNLOCK(&sessions); 02774 return result; 02775 }
static struct mansession* find_session | ( | uint32_t | ident | ) | [static, read] |
END Doxygen group
Definition at line 2721 of file manager.c.
References mansession::__lock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), mansession::inuse, mansession::managerid, mansession::needdestroy, s, and mansession::sessiontimeout.
Referenced by generic_http_callback().
02722 { 02723 struct mansession *s; 02724 02725 AST_LIST_LOCK(&sessions); 02726 AST_LIST_TRAVERSE(&sessions, s, list) { 02727 ast_mutex_lock(&s->__lock); 02728 if (s->sessiontimeout && (s->managerid == ident) && !s->needdestroy) { 02729 s->inuse++; 02730 break; 02731 } 02732 ast_mutex_unlock(&s->__lock); 02733 } 02734 AST_LIST_UNLOCK(&sessions); 02735 02736 return s; 02737 }
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 2784 of file manager.c.
References mansession::__lock, ast_build_string(), ast_calloc, ast_http_error(), ast_http_setcookie(), ast_inet_ntoa(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_MAX_MANHEADERS, ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, ast_verbose(), mansession::authenticated, destroy_session(), mansession::fd, find_session(), FORMAT_HTML, FORMAT_XML, free, message::hdrcount, message::headers, html_translate(), mansession::inuse, len, LOG_DEBUG, LOG_EVENT, malloc, mansession::managerid, ast_variable::name, mansession::needdestroy, eventqent::next, ast_variable::next, option_verbose, mansession::outputstr, process_message(), s, mansession::send_events, mansession::sessiontimeout, mansession::sin, strdup, mansession::username, ast_variable::value, VERBOSE_PREFIX_2, mansession::waiting_thread, and xml_translate().
Referenced by manager_http_callback(), mxml_http_callback(), and rawman_http_callback().
02785 { 02786 struct mansession *s = NULL; 02787 uint32_t ident = 0; 02788 char workspace[512]; 02789 char cookie[128]; 02790 size_t len = sizeof(workspace); 02791 int blastaway = 0; 02792 char *c = workspace; 02793 char *retval = NULL; 02794 struct ast_variable *v; 02795 02796 for (v = params; v; v = v->next) { 02797 if (!strcasecmp(v->name, "mansession_id")) { 02798 sscanf(v->value, "%x", &ident); 02799 break; 02800 } 02801 } 02802 02803 if (!(s = find_session(ident))) { 02804 /* Create new session */ 02805 if (!(s = ast_calloc(1, sizeof(*s)))) { 02806 *status = 500; 02807 goto generic_callback_out; 02808 } 02809 memcpy(&s->sin, requestor, sizeof(s->sin)); 02810 s->fd = -1; 02811 s->waiting_thread = AST_PTHREADT_NULL; 02812 s->send_events = 0; 02813 ast_mutex_init(&s->__lock); 02814 ast_mutex_lock(&s->__lock); 02815 s->inuse = 1; 02816 /*!\note There is approximately a 1 in 1.8E19 chance that the following 02817 * calculation will produce 0, which is an invalid ID, but due to the 02818 * properties of the rand() function (and the constantcy of s), that 02819 * won't happen twice in a row. 02820 */ 02821 while ((s->managerid = rand() ^ (unsigned long) s) == 0); 02822 AST_LIST_LOCK(&sessions); 02823 AST_LIST_INSERT_HEAD(&sessions, s, list); 02824 /* Hook into the last spot in the event queue */ 02825 s->eventq = master_eventq; 02826 while (s->eventq->next) 02827 s->eventq = s->eventq->next; 02828 ast_atomic_fetchadd_int(&s->eventq->usecount, 1); 02829 ast_atomic_fetchadd_int(&num_sessions, 1); 02830 AST_LIST_UNLOCK(&sessions); 02831 } 02832 02833 /* Reset HTTP timeout. If we're not yet authenticated, keep it extremely short */ 02834 time(&s->sessiontimeout); 02835 if (!s->authenticated && (httptimeout > 5)) 02836 s->sessiontimeout += 5; 02837 else 02838 s->sessiontimeout += httptimeout; 02839 ast_mutex_unlock(&s->__lock); 02840 02841 if (s) { 02842 struct message m = { 0 }; 02843 char tmp[80]; 02844 unsigned int x; 02845 size_t hdrlen; 02846 02847 for (x = 0, v = params; v && (x < AST_MAX_MANHEADERS); x++, v = v->next) { 02848 hdrlen = strlen(v->name) + strlen(v->value) + 3; 02849 m.headers[m.hdrcount] = alloca(hdrlen); 02850 snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value); 02851 m.hdrcount = x + 1; 02852 } 02853 02854 if (process_message(s, &m)) { 02855 if (s->authenticated) { 02856 if (option_verbose > 1) { 02857 if (displayconnects) 02858 ast_verbose(VERBOSE_PREFIX_2 "HTTP Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr)); 02859 } 02860 ast_log(LOG_EVENT, "HTTP Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr)); 02861 } else { 02862 if (option_verbose > 1) { 02863 if (displayconnects) 02864 ast_verbose(VERBOSE_PREFIX_2 "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(s->sin.sin_addr)); 02865 } 02866 ast_log(LOG_EVENT, "HTTP Failed attempt from %s\n", ast_inet_ntoa(s->sin.sin_addr)); 02867 } 02868 s->needdestroy = 1; 02869 } 02870 ast_build_string(&c, &len, "Content-type: text/%s\r\n", contenttype[format]); 02871 sprintf(tmp, "%08x", s->managerid); 02872 ast_build_string(&c, &len, "%s\r\n", ast_http_setcookie("mansession_id", tmp, httptimeout, cookie, sizeof(cookie))); 02873 if (format == FORMAT_HTML) 02874 ast_build_string(&c, &len, "<title>Asterisk™ Manager Interface</title>"); 02875 if (format == FORMAT_XML) { 02876 ast_build_string(&c, &len, "<ajax-response>\n"); 02877 } else if (format == FORMAT_HTML) { 02878 ast_build_string(&c, &len, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n"); 02879 ast_build_string(&c, &len, "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\"><h1> Manager Tester</h1></td></tr>\r\n"); 02880 } 02881 ast_mutex_lock(&s->__lock); 02882 if (s->outputstr) { 02883 char *tmp; 02884 if (format == FORMAT_XML) 02885 tmp = xml_translate(s->outputstr->str, params); 02886 else if (format == FORMAT_HTML) 02887 tmp = html_translate(s->outputstr->str); 02888 else 02889 tmp = s->outputstr->str; 02890 if (tmp) { 02891 retval = malloc(strlen(workspace) + strlen(tmp) + 128); 02892 if (retval) { 02893 strcpy(retval, workspace); 02894 strcpy(retval + strlen(retval), tmp); 02895 c = retval + strlen(retval); 02896 len = 120; 02897 } 02898 } 02899 if (tmp != s->outputstr->str) 02900 free(tmp); 02901 free(s->outputstr); 02902 s->outputstr = NULL; 02903 } 02904 ast_mutex_unlock(&s->__lock); 02905 /* Still okay because c would safely be pointing to workspace even 02906 if retval failed to allocate above */ 02907 if (format == FORMAT_XML) { 02908 ast_build_string(&c, &len, "</ajax-response>\n"); 02909 } else if (format == FORMAT_HTML) 02910 ast_build_string(&c, &len, "</table></body>\r\n"); 02911 } else { 02912 *status = 500; 02913 *title = strdup("Server Error"); 02914 } 02915 ast_mutex_lock(&s->__lock); 02916 if (s->needdestroy) { 02917 if (s->inuse == 1) { 02918 ast_log(LOG_DEBUG, "Need destroy, doing it now!\n"); 02919 blastaway = 1; 02920 } else { 02921 ast_log(LOG_DEBUG, "Need destroy, but can't do it yet!\n"); 02922 if (s->waiting_thread != AST_PTHREADT_NULL) 02923 pthread_kill(s->waiting_thread, SIGURG); 02924 s->inuse--; 02925 } 02926 } else 02927 s->inuse--; 02928 ast_mutex_unlock(&s->__lock); 02929 02930 if (blastaway) 02931 destroy_session(s); 02932 generic_callback_out: 02933 if (*status != 200) 02934 return ast_http_error(500, "Server Error", NULL, "Internal Server Error (out of memory)\n"); 02935 return retval; 02936 }
int init_manager | ( | void | ) |
Called by Asterisk initialization
Definition at line 2977 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_message(), 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_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(), 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, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, manager_state_cb(), ast_variable::name, ast_variable::next, option_verbose, ast_manager_user::permit, ast_manager_user::read, ast_manager_user::secret, ast_manager_user::username, users, ast_variable::value, var, and ast_manager_user::write.
Referenced by main(), and reload_manager().
02978 { 02979 struct ast_config *cfg = NULL, *ucfg = NULL; 02980 const char *val; 02981 char *cat = NULL; 02982 int oldportno = portno; 02983 static struct sockaddr_in ba; 02984 int x = 1; 02985 int flags; 02986 int webenabled = 0; 02987 int newhttptimeout = 60; 02988 struct ast_manager_user *user = NULL; 02989 02990 if (!registered) { 02991 /* Register default actions */ 02992 ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping); 02993 ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events); 02994 ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff); 02995 ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup); 02996 ast_manager_register2("Message", EVENT_FLAG_CALL, action_message, "Send Message", mandescr_message); 02997 ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" ); 02998 ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar ); 02999 ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar ); 03000 ast_manager_register2("GetConfig", EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig); 03001 ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig); 03002 ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect ); 03003 ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate); 03004 ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command ); 03005 ast_manager_register2("ExtensionState", EVENT_FLAG_CALL, action_extensionstate, "Check Extension Status", mandescr_extensionstate ); 03006 ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout ); 03007 ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus ); 03008 ast_manager_register2("MailboxCount", EVENT_FLAG_CALL, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount ); 03009 ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands); 03010 ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent); 03011 ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent); 03012 03013 ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry)); 03014 ast_extension_state_add(NULL, NULL, manager_state_cb, NULL); 03015 registered = 1; 03016 /* Append placeholder event so master_eventq never runs dry */ 03017 append_event("Event: Placeholder\r\n\r\n", 0); 03018 } 03019 portno = DEFAULT_MANAGER_PORT; 03020 displayconnects = 1; 03021 cfg = ast_config_load("manager.conf"); 03022 if (!cfg) { 03023 ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf. Call management disabled.\n"); 03024 return 0; 03025 } 03026 val = ast_variable_retrieve(cfg, "general", "enabled"); 03027 if (val) 03028 enabled = ast_true(val); 03029 03030 val = ast_variable_retrieve(cfg, "general", "block-sockets"); 03031 if (val) 03032 block_sockets = ast_true(val); 03033 03034 val = ast_variable_retrieve(cfg, "general", "webenabled"); 03035 if (val) 03036 webenabled = ast_true(val); 03037 03038 if ((val = ast_variable_retrieve(cfg, "general", "port"))) { 03039 if (sscanf(val, "%d", &portno) != 1) { 03040 ast_log(LOG_WARNING, "Invalid port number '%s'\n", val); 03041 portno = DEFAULT_MANAGER_PORT; 03042 } 03043 } 03044 03045 if ((val = ast_variable_retrieve(cfg, "general", "displayconnects"))) 03046 displayconnects = ast_true(val); 03047 03048 if ((val = ast_variable_retrieve(cfg, "general", "timestampevents"))) 03049 timestampevents = ast_true(val); 03050 03051 if ((val = ast_variable_retrieve(cfg, "general", "httptimeout"))) 03052 newhttptimeout = atoi(val); 03053 03054 memset(&ba, 0, sizeof(ba)); 03055 ba.sin_family = AF_INET; 03056 ba.sin_port = htons(portno); 03057 03058 if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) { 03059 if (!inet_aton(val, &ba.sin_addr)) { 03060 ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val); 03061 memset(&ba.sin_addr, 0, sizeof(ba.sin_addr)); 03062 } 03063 } 03064 03065 03066 if ((asock > -1) && ((portno != oldportno) || !enabled)) { 03067 #if 0 03068 /* Can't be done yet */ 03069 close(asock); 03070 asock = -1; 03071 #else 03072 ast_log(LOG_WARNING, "Unable to change management port / enabled\n"); 03073 #endif 03074 } 03075 03076 AST_LIST_LOCK(&users); 03077 03078 if ((ucfg = ast_config_load("users.conf"))) { 03079 while ((cat = ast_category_browse(ucfg, cat))) { 03080 int hasmanager = 0; 03081 struct ast_variable *var = NULL; 03082 03083 if (!strcasecmp(cat, "general")) { 03084 continue; 03085 } 03086 03087 if (!(hasmanager = ast_true(ast_variable_retrieve(ucfg, cat, "hasmanager")))) { 03088 continue; 03089 } 03090 03091 /* Look for an existing entry, if none found - create one and add it to the list */ 03092 if (!(user = ast_get_manager_by_name_locked(cat))) { 03093 if (!(user = ast_calloc(1, sizeof(*user)))) { 03094 break; 03095 } 03096 /* Copy name over */ 03097 ast_copy_string(user->username, cat, sizeof(user->username)); 03098 /* Insert into list */ 03099 AST_LIST_INSERT_TAIL(&users, user, list); 03100 } 03101 03102 /* Make sure we keep this user and don't destroy it during cleanup */ 03103 user->keep = 1; 03104 03105 for (var = ast_variable_browse(ucfg, cat); var; var = var->next) { 03106 if (!strcasecmp(var->name, "secret")) { 03107 if (user->secret) { 03108 free(user->secret); 03109 } 03110 user->secret = ast_strdup(var->value); 03111 } else if (!strcasecmp(var->name, "deny") ) { 03112 if (user->deny) { 03113 free(user->deny); 03114 } 03115 user->deny = ast_strdup(var->value); 03116 } else if (!strcasecmp(var->name, "permit") ) { 03117 if (user->permit) { 03118 free(user->permit); 03119 } 03120 user->permit = ast_strdup(var->value); 03121 } else if (!strcasecmp(var->name, "read") ) { 03122 if (user->read) { 03123 free(user->read); 03124 } 03125 user->read = ast_strdup(var->value); 03126 } else if (!strcasecmp(var->name, "write") ) { 03127 if (user->write) { 03128 free(user->write); 03129 } 03130 user->write = ast_strdup(var->value); 03131 } else if (!strcasecmp(var->name, "displayconnects") ) { 03132 user->displayconnects = ast_true(var->value); 03133 } else if (!strcasecmp(var->name, "hasmanager")) { 03134 /* already handled */ 03135 } else { 03136 ast_log(LOG_DEBUG, "%s is an unknown option (to the manager module).\n", var->name); 03137 } 03138 } 03139 } 03140 ast_config_destroy(ucfg); 03141 } 03142 03143 while ((cat = ast_category_browse(cfg, cat))) { 03144 struct ast_variable *var = NULL; 03145 03146 if (!strcasecmp(cat, "general")) 03147 continue; 03148 03149 /* Look for an existing entry, if none found - create one and add it to the list */ 03150 if (!(user = ast_get_manager_by_name_locked(cat))) { 03151 if (!(user = ast_calloc(1, sizeof(*user)))) 03152 break; 03153 /* Copy name over */ 03154 ast_copy_string(user->username, cat, sizeof(user->username)); 03155 /* Insert into list */ 03156 AST_LIST_INSERT_TAIL(&users, user, list); 03157 } 03158 03159 /* Make sure we keep this user and don't destroy it during cleanup */ 03160 user->keep = 1; 03161 03162 var = ast_variable_browse(cfg, cat); 03163 while (var) { 03164 if (!strcasecmp(var->name, "secret")) { 03165 if (user->secret) 03166 free(user->secret); 03167 user->secret = ast_strdup(var->value); 03168 } else if (!strcasecmp(var->name, "deny") ) { 03169 if (user->deny) 03170 free(user->deny); 03171 user->deny = ast_strdup(var->value); 03172 } else if (!strcasecmp(var->name, "permit") ) { 03173 if (user->permit) 03174 free(user->permit); 03175 user->permit = ast_strdup(var->value); 03176 } else if (!strcasecmp(var->name, "read") ) { 03177 if (user->read) 03178 free(user->read); 03179 user->read = ast_strdup(var->value); 03180 } else if (!strcasecmp(var->name, "write") ) { 03181 if (user->write) 03182 free(user->write); 03183 user->write = ast_strdup(var->value); 03184 } else if (!strcasecmp(var->name, "displayconnects") ) 03185 user->displayconnects = ast_true(var->value); 03186 else 03187 ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name); 03188 var = var->next; 03189 } 03190 } 03191 03192 /* Perform cleanup - essentially prune out old users that no longer exist */ 03193 AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) { 03194 if (user->keep) { 03195 user->keep = 0; 03196 continue; 03197 } 03198 /* We do not need to keep this user so take them out of the list */ 03199 AST_LIST_REMOVE_CURRENT(&users, list); 03200 /* Free their memory now */ 03201 if (user->secret) 03202 free(user->secret); 03203 if (user->deny) 03204 free(user->deny); 03205 if (user->permit) 03206 free(user->permit); 03207 if (user->read) 03208 free(user->read); 03209 if (user->write) 03210 free(user->write); 03211 free(user); 03212 } 03213 AST_LIST_TRAVERSE_SAFE_END 03214 03215 AST_LIST_UNLOCK(&users); 03216 03217 ast_config_destroy(cfg); 03218 03219 if (webenabled && enabled) { 03220 if (!webregged) { 03221 ast_http_uri_link(&rawmanuri); 03222 ast_http_uri_link(&manageruri); 03223 ast_http_uri_link(&managerxmluri); 03224 webregged = 1; 03225 } 03226 } else { 03227 if (webregged) { 03228 ast_http_uri_unlink(&rawmanuri); 03229 ast_http_uri_unlink(&manageruri); 03230 ast_http_uri_unlink(&managerxmluri); 03231 webregged = 0; 03232 } 03233 } 03234 03235 if (newhttptimeout > 0) 03236 httptimeout = newhttptimeout; 03237 03238 /* If not enabled, do nothing */ 03239 if (!enabled) 03240 return 0; 03241 03242 if (asock < 0) { 03243 asock = socket(AF_INET, SOCK_STREAM, 0); 03244 if (asock < 0) { 03245 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno)); 03246 return -1; 03247 } 03248 setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 03249 if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) { 03250 ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno)); 03251 close(asock); 03252 asock = -1; 03253 return -1; 03254 } 03255 if (listen(asock, 2)) { 03256 ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno)); 03257 close(asock); 03258 asock = -1; 03259 return -1; 03260 } 03261 flags = fcntl(asock, F_GETFL); 03262 fcntl(asock, F_SETFL, flags | O_NONBLOCK); 03263 if (option_verbose) 03264 ast_verbose("Asterisk Management interface listening on port %d\n", portno); 03265 ast_pthread_create_background(&t, NULL, accept_thread, NULL); 03266 } 03267 return 0; 03268 }
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 2938 of file manager.c.
References FORMAT_HTML, and generic_http_callback().
02939 { 02940 return generic_http_callback(FORMAT_HTML, requestor, uri, params, status, title, contentlength); 02941 }
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 2943 of file manager.c.
References FORMAT_XML, and generic_http_callback().
02944 { 02945 return generic_http_callback(FORMAT_XML, requestor, uri, params, status, title, contentlength); 02946 }
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 2948 of file manager.c.
References FORMAT_RAW, and generic_http_callback().
02949 { 02950 return generic_http_callback(FORMAT_RAW, requestor, uri, params, status, title, contentlength); 02951 }
int reload_manager | ( | void | ) |
Definition at line 3270 of file manager.c.
References EVENT_FLAG_SYSTEM, init_manager(), and manager_event().
03271 { 03272 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n"); 03273 return init_manager(); 03274 }
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] |