Tue Sep 30 01:20:00 2008

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

02777      {
02778    FORMAT_RAW,
02779    FORMAT_HTML,
02780    FORMAT_XML,
02781 };


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

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

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]

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


Variable Documentation

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

Definition at line 2782 of file manager.c.

Definition at line 2960 of file manager.c.

Definition at line 2967 of file manager.c.

Definition at line 2953 of file manager.c.

int registered = 0 [static]

Definition at line 2974 of file manager.c.

int webregged = 0 [static]

Definition at line 2975 of file manager.c.

char* words[AST_MAX_CMD_LEN]

Definition at line 141 of file manager.c.

Referenced by check_blacklist(), and fix_complete_args().


Generated on Tue Sep 30 01:20:00 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.6