Sat Aug 6 00:39:59 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 <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_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)
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_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)
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_sessionfind_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_actionfirst_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.
eventqentmaster_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


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

02976      {
02977    FORMAT_RAW,
02978    FORMAT_HTML,
02979    FORMAT_XML,
02980 };


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 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.

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

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&trade; 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>&nbsp;&nbsp;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 }


Variable Documentation

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

Definition at line 2981 of file manager.c.

struct ast_http_uri manageruri

Definition at line 3209 of file manager.c.

struct ast_http_uri managerxmluri

Definition at line 3216 of file manager.c.

struct ast_http_uri rawmanuri

Definition at line 3202 of file manager.c.

int registered = 0 [static]

Definition at line 3223 of file manager.c.

int webregged = 0 [static]

Definition at line 3224 of file manager.c.

char* words[AST_MAX_CMD_LEN]

Definition at line 156 of file manager.c.

Referenced by check_blacklist().


Generated on Sat Aug 6 00:39:59 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7