Sun Dec 18 20:55:52 2011

Asterisk developer's documentation


manager.c File Reference

The Asterisk Management Interface - AMI. More...

#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"

Include dependency graph for manager.c:

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_userast_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_variableastman_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 mansessionfind_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 authlimit
static int authtimeout
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 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 int enabled
static struct manager_actionfirst_action
static int httptimeout
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 eventqentmaster_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 unauth_sessions = 0
static int webregged = 0


Detailed Description

The Asterisk Management Interface - AMI.

Author:
Mark Spencer <markster@digium.com>
Channel Management and more

manager.conf

Definition in file manager.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
FORMAT_RAW 
FORMAT_HTML 
FORMAT_XML 

Definition at line 2851 of file manager.c.

02851      {
02852    FORMAT_RAW,
02853    FORMAT_HTML,
02854    FORMAT_XML,
02855 };


Function Documentation

int astman_verify_session_readpermissions ( uint32_t  ident,
int  perm 
)

Verify a session's read permissions against a permission mask.

Parameters:
ident session identity
perm permission mask to verify
Returns:
1 if the session has the permission mask capabilities, otherwise 0

Definition at line 2813 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.

02814 {
02815    int result = 0;
02816    struct mansession *s;
02817 
02818    AST_LIST_LOCK(&sessions);
02819    AST_LIST_TRAVERSE(&sessions, s, list) {
02820       ast_mutex_lock(&s->__lock);
02821       if ((s->managerid == ident) && (s->readperm & perm)) {
02822          result = 1;
02823          ast_mutex_unlock(&s->__lock);
02824          break;
02825       }
02826       ast_mutex_unlock(&s->__lock);
02827    }
02828    AST_LIST_UNLOCK(&sessions);
02829    return result;
02830 }

int astman_verify_session_writepermissions ( uint32_t  ident,
int  perm 
)

Verify a session's write permissions against a permission mask.

Parameters:
ident session identity
perm permission mask to verify
Returns:
1 if the session has the permission mask capabilities, otherwise 0

Definition at line 2832 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.

02833 {
02834    int result = 0;
02835    struct mansession *s;
02836 
02837    AST_LIST_LOCK(&sessions);
02838    AST_LIST_TRAVERSE(&sessions, s, list) {
02839       ast_mutex_lock(&s->__lock);
02840       if ((s->managerid == ident) && (s->writeperm & perm)) {
02841          result = 1;
02842          ast_mutex_unlock(&s->__lock);
02843          break;
02844       }
02845       ast_mutex_unlock(&s->__lock);
02846    }
02847    AST_LIST_UNLOCK(&sessions);
02848    return result;
02849 }

static struct mansession* find_session ( uint32_t  ident  )  [static, read]

END Doxygen group

Definition at line 2795 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().

02796 {
02797    struct mansession *s;
02798 
02799    AST_LIST_LOCK(&sessions);
02800    AST_LIST_TRAVERSE(&sessions, s, list) {
02801       ast_mutex_lock(&s->__lock);
02802       if (s->sessiontimeout && (s->managerid == ident) && !s->needdestroy) {
02803          s->inuse++;
02804          break;
02805       }
02806       ast_mutex_unlock(&s->__lock);
02807    }
02808    AST_LIST_UNLOCK(&sessions);
02809 
02810    return s;
02811 }

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]

Note:
There is approximately a 1 in 1.8E19 chance that the following calculation will produce 0, which is an invalid ID, but due to the properties of the rand() function (and the constantcy of s), that won't happen twice in a row.

Definition at line 2858 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().

02859 {
02860    struct mansession *s = NULL;
02861    uint32_t ident = 0;
02862    char workspace[512];
02863    char cookie[128];
02864    size_t len = sizeof(workspace);
02865    int blastaway = 0;
02866    char *c = workspace;
02867    char *retval = NULL;
02868    struct ast_variable *v;
02869 
02870    for (v = params; v; v = v->next) {
02871       if (!strcasecmp(v->name, "mansession_id")) {
02872          sscanf(v->value, "%x", &ident);
02873          break;
02874       }
02875    }
02876    
02877    if (!(s = find_session(ident))) {
02878       /* Create new session */
02879       if (!(s = ast_calloc(1, sizeof(*s)))) {
02880          *status = 500;
02881          goto generic_callback_out;
02882       }
02883       memcpy(&s->sin, requestor, sizeof(s->sin));
02884       s->fd = -1;
02885       s->waiting_thread = AST_PTHREADT_NULL;
02886       s->send_events = 0;
02887       ast_mutex_init(&s->__lock);
02888       ast_mutex_lock(&s->__lock);
02889       s->inuse = 1;
02890       /*!\note There is approximately a 1 in 1.8E19 chance that the following
02891        * calculation will produce 0, which is an invalid ID, but due to the
02892        * properties of the rand() function (and the constantcy of s), that
02893        * won't happen twice in a row.
02894        */
02895       while ((s->managerid = rand() ^ (unsigned long) s) == 0);
02896       AST_LIST_LOCK(&sessions);
02897       AST_LIST_INSERT_HEAD(&sessions, s, list);
02898       /* Hook into the last spot in the event queue */
02899       s->eventq = master_eventq;
02900       while (s->eventq->next)
02901          s->eventq = s->eventq->next;
02902       ast_atomic_fetchadd_int(&s->eventq->usecount, 1);
02903       ast_atomic_fetchadd_int(&num_sessions, 1);
02904       AST_LIST_UNLOCK(&sessions);
02905    }
02906 
02907    /* Reset HTTP timeout.  If we're not yet authenticated, keep it extremely short */
02908    time(&s->sessiontimeout);
02909    if (!s->authenticated && (httptimeout > 5))
02910       s->sessiontimeout += 5;
02911    else
02912       s->sessiontimeout += httptimeout;
02913    ast_mutex_unlock(&s->__lock);
02914    
02915    if (s) {
02916       struct message m = { 0 };
02917       char tmp[80];
02918       unsigned int x;
02919       size_t hdrlen;
02920 
02921       for (x = 0, v = params; v && (x < AST_MAX_MANHEADERS); x++, v = v->next) {
02922          hdrlen = strlen(v->name) + strlen(v->value) + 3;
02923          m.headers[m.hdrcount] = alloca(hdrlen);
02924          snprintf((char *) m.headers[m.hdrcount], hdrlen, "%s: %s", v->name, v->value);
02925          m.hdrcount = x + 1;
02926       }
02927 
02928       if (process_message(s, &m)) {
02929          if (s->authenticated) {
02930             if (option_verbose > 1) {
02931                if (displayconnects) 
02932                   ast_verbose(VERBOSE_PREFIX_2 "HTTP Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr));    
02933             }
02934             ast_log(LOG_EVENT, "HTTP Manager '%s' logged off from %s\n", s->username, ast_inet_ntoa(s->sin.sin_addr));
02935          } else {
02936             if (option_verbose > 1) {
02937                if (displayconnects)
02938                   ast_verbose(VERBOSE_PREFIX_2 "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(s->sin.sin_addr));
02939             }
02940             ast_log(LOG_EVENT, "HTTP Failed attempt from %s\n", ast_inet_ntoa(s->sin.sin_addr));
02941          }
02942          s->needdestroy = 1;
02943       }
02944       ast_build_string(&c, &len, "Content-type: text/%s\r\n", contenttype[format]);
02945       sprintf(tmp, "%08x", s->managerid);
02946       ast_build_string(&c, &len, "%s\r\n", ast_http_setcookie("mansession_id", tmp, httptimeout, cookie, sizeof(cookie)));
02947       if (format == FORMAT_HTML)
02948          ast_build_string(&c, &len, "<title>Asterisk&trade; Manager Interface</title>");
02949       if (format == FORMAT_XML) {
02950          ast_build_string(&c, &len, "<ajax-response>\n");
02951       } else if (format == FORMAT_HTML) {
02952          ast_build_string(&c, &len, "<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n");
02953          ast_build_string(&c, &len, "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\"><h1>&nbsp;&nbsp;Manager Tester</h1></td></tr>\r\n");
02954       }
02955       ast_mutex_lock(&s->__lock);
02956       if (s->outputstr) {
02957          char *tmp;
02958          if (format == FORMAT_XML)
02959             tmp = xml_translate(s->outputstr->str, params);
02960          else if (format == FORMAT_HTML)
02961             tmp = html_translate(s->outputstr->str);
02962          else
02963             tmp = s->outputstr->str;
02964          if (tmp) {
02965             retval = malloc(strlen(workspace) + strlen(tmp) + 128);
02966             if (retval) {
02967                strcpy(retval, workspace);
02968                strcpy(retval + strlen(retval), tmp);
02969                c = retval + strlen(retval);
02970                len = 120;
02971             }
02972          }
02973          if (tmp != s->outputstr->str)
02974             free(tmp);
02975          free(s->outputstr);
02976          s->outputstr = NULL;
02977       }
02978       ast_mutex_unlock(&s->__lock);
02979       /* Still okay because c would safely be pointing to workspace even
02980          if retval failed to allocate above */
02981       if (format == FORMAT_XML) {
02982          ast_build_string(&c, &len, "</ajax-response>\n");
02983       } else if (format == FORMAT_HTML)
02984          ast_build_string(&c, &len, "</table></body>\r\n");
02985    } else {
02986       *status = 500;
02987       *title = strdup("Server Error");
02988    }
02989    ast_mutex_lock(&s->__lock);
02990    if (s->needdestroy) {
02991       if (s->inuse == 1) {
02992          ast_log(LOG_DEBUG, "Need destroy, doing it now!\n");
02993          blastaway = 1;
02994       } else {
02995          ast_log(LOG_DEBUG, "Need destroy, but can't do it yet!\n");
02996          if (s->waiting_thread != AST_PTHREADT_NULL)
02997             pthread_kill(s->waiting_thread, SIGURG);
02998          s->inuse--;
02999       }
03000    } else
03001       s->inuse--;
03002    ast_mutex_unlock(&s->__lock);
03003    
03004    if (blastaway)
03005       destroy_session(s);
03006 generic_callback_out:
03007    if (*status != 200)
03008       return ast_http_error(500, "Server Error", NULL, "Internal Server Error (out of memory)\n"); 
03009    return retval;
03010 }

int init_manager ( void   ) 

Called by Asterisk initialization

Definition at line 3051 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().

03052 {
03053    struct ast_config *cfg = NULL, *ucfg = NULL;
03054    const char *val;
03055    char *cat = NULL;
03056    int oldportno = portno;
03057    static struct sockaddr_in ba;
03058    int x = 1;
03059    int flags;
03060    int webenabled = DEFAULT_WEBENABLED;
03061    int newhttptimeout = DEFAULT_HTTPTIMEOUT;
03062    struct ast_manager_user *user = NULL;
03063 
03064    if (!registered) {
03065       /* Register default actions */
03066       ast_manager_register2("Ping", 0, action_ping, "Keepalive command", mandescr_ping);
03067       ast_manager_register2("Events", 0, action_events, "Control Event Flow", mandescr_events);
03068       ast_manager_register2("Logoff", 0, action_logoff, "Logoff Manager", mandescr_logoff);
03069       ast_manager_register2("Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel", mandescr_hangup);
03070       ast_manager_register2("Message", EVENT_FLAG_CALL, action_message, "Send Message", mandescr_message);
03071       ast_manager_register("Status", EVENT_FLAG_CALL, action_status, "Lists channel status" );
03072       ast_manager_register2("Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable", mandescr_setvar );
03073       ast_manager_register2("Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable", mandescr_getvar );
03074       ast_manager_register2("GetConfig", EVENT_FLAG_CONFIG, action_getconfig, "Retrieve configuration", mandescr_getconfig);
03075       ast_manager_register2("UpdateConfig", EVENT_FLAG_CONFIG, action_updateconfig, "Update basic configuration", mandescr_updateconfig);
03076       ast_manager_register2("Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect (transfer) a call", mandescr_redirect );
03077       ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate);
03078       ast_manager_register2("Command", EVENT_FLAG_COMMAND, action_command, "Execute Asterisk CLI Command", mandescr_command );
03079       ast_manager_register2("ExtensionState", EVENT_FLAG_CALL, action_extensionstate, "Check Extension Status", mandescr_extensionstate );
03080       ast_manager_register2("AbsoluteTimeout", EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout", mandescr_timeout );
03081       ast_manager_register2("MailboxStatus", EVENT_FLAG_CALL, action_mailboxstatus, "Check Mailbox", mandescr_mailboxstatus );
03082       ast_manager_register2("MailboxCount", EVENT_FLAG_CALL, action_mailboxcount, "Check Mailbox Message Count", mandescr_mailboxcount );
03083       ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands);
03084       ast_manager_register2("UserEvent", EVENT_FLAG_USER, action_userevent, "Send an arbitrary event", mandescr_userevent);
03085       ast_manager_register2("WaitEvent", 0, action_waitevent, "Wait for an event to occur", mandescr_waitevent);
03086 
03087       ast_cli_register_multiple(cli_manager, sizeof(cli_manager) / sizeof(struct ast_cli_entry));
03088       ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
03089       registered = 1;
03090       /* Append placeholder event so master_eventq never runs dry */
03091       append_event("Event: Placeholder\r\n\r\n", 0);
03092    }
03093 
03094    portno = DEFAULT_MANAGER_PORT;
03095    displayconnects = DEFAULT_DISPLAYCONNECTS;
03096    block_sockets = DEFAULT_BLOCKSOCKETS;
03097    timestampevents = DEFAULT_TIMESTAMPEVENTS;
03098    httptimeout = DEFAULT_HTTPTIMEOUT;
03099    authtimeout = DEFAULT_AUTHTIMEOUT;
03100    authlimit = DEFAULT_AUTHLIMIT;
03101 
03102    cfg = ast_config_load("manager.conf");
03103    if (!cfg) {
03104       ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf.  Call management disabled.\n");
03105       return 0;
03106    }
03107    val = ast_variable_retrieve(cfg, "general", "enabled");
03108    if (val)
03109       enabled = ast_true(val);
03110 
03111    val = ast_variable_retrieve(cfg, "general", "block-sockets");
03112    if (val)
03113       block_sockets = ast_true(val);
03114 
03115    val = ast_variable_retrieve(cfg, "general", "webenabled");
03116    if (val)
03117       webenabled = ast_true(val);
03118 
03119    if ((val = ast_variable_retrieve(cfg, "general", "port"))) {
03120       if (sscanf(val, "%d", &portno) != 1) {
03121          ast_log(LOG_WARNING, "Invalid port number '%s'\n", val);
03122          portno = DEFAULT_MANAGER_PORT;
03123       }
03124    }
03125 
03126    if ((val = ast_variable_retrieve(cfg, "general", "displayconnects")))
03127       displayconnects = ast_true(val);
03128 
03129    if ((val = ast_variable_retrieve(cfg, "general", "timestampevents")))
03130       timestampevents = ast_true(val);
03131 
03132    if ((val = ast_variable_retrieve(cfg, "general", "httptimeout")))
03133       newhttptimeout = atoi(val);
03134 
03135    if ((val = ast_variable_retrieve(cfg, "general", "authtimeout"))) {
03136       int timeout = atoi(val);
03137 
03138       if (timeout < 1) {
03139          ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", val);
03140       } else {
03141          authtimeout = timeout;
03142       }
03143    }
03144 
03145    if ((val = ast_variable_retrieve(cfg, "general", "authlimit"))) {
03146       int limit = atoi(val);
03147 
03148       if (limit < 1) {
03149          ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", val);
03150       } else {
03151          authlimit = limit;
03152       }
03153    }
03154 
03155    memset(&ba, 0, sizeof(ba));
03156    ba.sin_family = AF_INET;
03157    ba.sin_port = htons(portno);
03158 
03159    if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) {
03160       if (!inet_aton(val, &ba.sin_addr)) { 
03161          ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
03162          memset(&ba.sin_addr, 0, sizeof(ba.sin_addr));
03163       }
03164    }
03165    
03166 
03167    if ((asock > -1) && ((portno != oldportno) || !enabled)) {
03168 #if 0
03169       /* Can't be done yet */
03170       close(asock);
03171       asock = -1;
03172 #else
03173       ast_log(LOG_WARNING, "Unable to change management port / enabled\n");
03174 #endif
03175    }
03176 
03177    AST_LIST_LOCK(&users);
03178 
03179    if ((ucfg = ast_config_load("users.conf"))) {
03180       while ((cat = ast_category_browse(ucfg, cat))) {
03181          int hasmanager = 0;
03182          struct ast_variable *var = NULL;
03183 
03184          if (!strcasecmp(cat, "general")) {
03185             continue;
03186          }
03187 
03188          if (!(hasmanager = ast_true(ast_variable_retrieve(ucfg, cat, "hasmanager")))) {
03189             continue;
03190          }
03191 
03192          /* Look for an existing entry, if none found - create one and add it to the list */
03193          if (!(user = ast_get_manager_by_name_locked(cat))) {
03194             if (!(user = ast_calloc(1, sizeof(*user)))) {
03195                break;
03196             }
03197             /* Copy name over */
03198             ast_copy_string(user->username, cat, sizeof(user->username));
03199             /* Insert into list */
03200             AST_LIST_INSERT_TAIL(&users, user, list);
03201          }
03202 
03203          /* Make sure we keep this user and don't destroy it during cleanup */
03204          user->keep = 1;
03205 
03206          for (var = ast_variable_browse(ucfg, cat); var; var = var->next) {
03207             if (!strcasecmp(var->name, "secret")) {
03208                if (user->secret) {
03209                   free(user->secret);
03210                }
03211                user->secret = ast_strdup(var->value);
03212             } else if (!strcasecmp(var->name, "deny") ) {
03213                if (user->deny) {
03214                   free(user->deny);
03215                }
03216                user->deny = ast_strdup(var->value);
03217             } else if (!strcasecmp(var->name, "permit") ) {
03218                if (user->permit) {
03219                   free(user->permit);
03220                }
03221                user->permit = ast_strdup(var->value);
03222             } else if (!strcasecmp(var->name, "read") ) {
03223                if (user->read) {
03224                   free(user->read);
03225                }
03226                user->read = ast_strdup(var->value);
03227             } else if (!strcasecmp(var->name, "write") ) {
03228                if (user->write) {
03229                   free(user->write);
03230                }
03231                user->write = ast_strdup(var->value);
03232             } else if (!strcasecmp(var->name, "displayconnects") ) {
03233                user->displayconnects = ast_true(var->value);
03234             } else if (!strcasecmp(var->name, "hasmanager")) {
03235                /* already handled */
03236             } else {
03237                ast_log(LOG_DEBUG, "%s is an unknown option (to the manager module).\n", var->name);
03238             }
03239          }
03240       }
03241       ast_config_destroy(ucfg);
03242    }
03243 
03244    while ((cat = ast_category_browse(cfg, cat))) {
03245       struct ast_variable *var = NULL;
03246 
03247       if (!strcasecmp(cat, "general"))
03248          continue;
03249 
03250       /* Look for an existing entry, if none found - create one and add it to the list */
03251       if (!(user = ast_get_manager_by_name_locked(cat))) {
03252          if (!(user = ast_calloc(1, sizeof(*user))))
03253             break;
03254          /* Copy name over */
03255          ast_copy_string(user->username, cat, sizeof(user->username));
03256          /* Insert into list */
03257          AST_LIST_INSERT_TAIL(&users, user, list);
03258       }
03259 
03260       /* Make sure we keep this user and don't destroy it during cleanup */
03261       user->keep = 1;
03262 
03263       var = ast_variable_browse(cfg, cat);
03264       while (var) {
03265          if (!strcasecmp(var->name, "secret")) {
03266             if (user->secret)
03267                free(user->secret);
03268             user->secret = ast_strdup(var->value);
03269          } else if (!strcasecmp(var->name, "deny") ) {
03270             if (user->deny)
03271                free(user->deny);
03272             user->deny = ast_strdup(var->value);
03273          } else if (!strcasecmp(var->name, "permit") ) {
03274             if (user->permit)
03275                free(user->permit);
03276             user->permit = ast_strdup(var->value);
03277          }  else if (!strcasecmp(var->name, "read") ) {
03278             if (user->read)
03279                free(user->read);
03280             user->read = ast_strdup(var->value);
03281          }  else if (!strcasecmp(var->name, "write") ) {
03282             if (user->write)
03283                free(user->write);
03284             user->write = ast_strdup(var->value);
03285          }  else if (!strcasecmp(var->name, "displayconnects") )
03286             user->displayconnects = ast_true(var->value);
03287          else
03288             ast_log(LOG_DEBUG, "%s is an unknown option.\n", var->name);
03289          var = var->next;
03290       }
03291    }
03292 
03293    /* Perform cleanup - essentially prune out old users that no longer exist */
03294    AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
03295       if (user->keep) {
03296          user->keep = 0;
03297          continue;
03298       }
03299       /* We do not need to keep this user so take them out of the list */
03300       AST_LIST_REMOVE_CURRENT(&users, list);
03301       /* Free their memory now */
03302       if (user->secret)
03303          free(user->secret);
03304       if (user->deny)
03305          free(user->deny);
03306       if (user->permit)
03307          free(user->permit);
03308       if (user->read)
03309          free(user->read);
03310       if (user->write)
03311          free(user->write);
03312       free(user);
03313    }
03314    AST_LIST_TRAVERSE_SAFE_END
03315 
03316    AST_LIST_UNLOCK(&users);
03317 
03318    ast_config_destroy(cfg);
03319    
03320    if (webenabled && enabled) {
03321       if (!webregged) {
03322          ast_http_uri_link(&rawmanuri);
03323          ast_http_uri_link(&manageruri);
03324          ast_http_uri_link(&managerxmluri);
03325          webregged = 1;
03326       }
03327    } else {
03328       if (webregged) {
03329          ast_http_uri_unlink(&rawmanuri);
03330          ast_http_uri_unlink(&manageruri);
03331          ast_http_uri_unlink(&managerxmluri);
03332          webregged = 0;
03333       }
03334    }
03335 
03336    if (newhttptimeout > 0)
03337       httptimeout = newhttptimeout;
03338 
03339    /* If not enabled, do nothing */
03340    if (!enabled)
03341       return 0;
03342 
03343    if (asock < 0) {
03344       asock = socket(AF_INET, SOCK_STREAM, 0);
03345       if (asock < 0) {
03346          ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
03347          return -1;
03348       }
03349       setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
03350       if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) {
03351          ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno));
03352          close(asock);
03353          asock = -1;
03354          return -1;
03355       }
03356       if (listen(asock, 2)) {
03357          ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno));
03358          close(asock);
03359          asock = -1;
03360          return -1;
03361       }
03362       flags = fcntl(asock, F_GETFL);
03363       fcntl(asock, F_SETFL, flags | O_NONBLOCK);
03364       if (option_verbose)
03365          ast_verbose("Asterisk Management interface listening on port %d\n", portno);
03366       ast_pthread_create_background(&t, NULL, accept_thread, NULL);
03367    }
03368    return 0;
03369 }

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 3012 of file manager.c.

References FORMAT_HTML, and generic_http_callback().

03013 {
03014    return generic_http_callback(FORMAT_HTML, requestor, uri, params, status, title, contentlength);
03015 }

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 3017 of file manager.c.

References FORMAT_XML, and generic_http_callback().

03018 {
03019    return generic_http_callback(FORMAT_XML, requestor, uri, params, status, title, contentlength);
03020 }

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 3022 of file manager.c.

References FORMAT_RAW, and generic_http_callback().

03023 {
03024    return generic_http_callback(FORMAT_RAW, requestor, uri, params, status, title, contentlength);
03025 }

int reload_manager ( void   ) 

Definition at line 3371 of file manager.c.

References EVENT_FLAG_SYSTEM, init_manager(), and manager_event().

03372 {
03373    manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n");
03374    return init_manager();
03375 }


Variable Documentation

char* contenttype[] = { "plain", "html", "xml" } [static]

Definition at line 2856 of file manager.c.

Definition at line 3034 of file manager.c.

Definition at line 3041 of file manager.c.

Definition at line 3027 of file manager.c.

int registered = 0 [static]

Definition at line 3048 of file manager.c.

int webregged = 0 [static]

Definition at line 3049 of file manager.c.

char* words[AST_MAX_CMD_LEN]

Definition at line 155 of file manager.c.

Referenced by check_blacklist(), and fix_complete_args().


Generated on Sun Dec 18 20:55:52 2011 for Asterisk - the Open Source PBX by  doxygen 1.5.6