summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--README54
-rw-r--r--TODO2
-rw-r--r--VERSIONS4
-rw-r--r--src/astmanproxy.c1231
-rw-r--r--src/common.c201
-rw-r--r--src/config.c544
-rw-r--r--src/config_perms.c198
-rw-r--r--src/csv.c39
-rw-r--r--src/http.c397
-rw-r--r--src/include/astmanproxy.h146
-rw-r--r--src/log.c92
-rw-r--r--src/poll.c76
-rw-r--r--src/proxyfunc.c622
-rw-r--r--src/ssl.c272
-rw-r--r--src/standard.c92
-rw-r--r--src/xml.c235
17 files changed, 2144 insertions, 2063 deletions
diff --git a/Makefile b/Makefile
index df71864..7d19bfb 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
OSARCH=$(shell uname -s)
OSREV=$(shell uname -r)
-VERSION := 1.21pre
+VERSION := 1.21
DESTDIR ?=
CONFDIR:=/etc/asterisk
CONFDIR_REAL := $(DESTDIR)/etc/asterisk
diff --git a/README b/README
index 719f784..b090332 100644
--- a/README
+++ b/README
@@ -24,9 +24,6 @@ Features include:
- I/O Formats selectable on a per-client basis
- Written in c/pthreads to be fast and robust
-For example, you can use Astmanproxy as a single point of contact to
-communicate with multiple Asterisk servers.
-
You can use Astmanproxy as the basis for a web-based application:
send it data using HTTP POST or HTTP GET, and receive XML output.
Or use HTTP POST and get Standard (text/plain) output back!
@@ -98,6 +95,7 @@ OutputFormat: (standard|xml)
ProxyAction: SetAutoFilter
AutoFilter: (on|off)
Sets the AutoFilter property on a per-client basis
+ (See autofiltering section below)
ProxyAction: Logoff
Logs client out of Proxy and leaves Asterisk alone.
@@ -165,6 +163,52 @@ Blank Commands
blank command blocks.
===================================================================
+AstManProxy Autofiltering Functionality
+
+One of the most powerful features of AstManProxy is its ability to
+automatically filter output on a per-client basis. It can do this
+with its Autofilter capability, which can be set 'on' in the config
+file or enabled via the ProxyAction: SetAutoFilter function.
+
+With autofiltering enabled, each client only receives output containing
+the "ActionID" parameter it has set most recently. This is useful
+for single atomic requests into asterisk from a client, such as
+when creating a simple UI to inject a command.
+
+For example, if a client sends this packet while autofiltering is
+enabled:
+
+Action: Ping
+ActionID: foo
+
+Then the autofilter ActionID for that client is set to foo, and no
+output besides for responses containing "foo" will be returned
+to that client, such as:
+
+Response: Pong
+ActionID: foo
+
+Replace Ping with Originate and Pong with Success and you can see
+how this same mechanism can be used to quickly query asterisk
+box(es), initiate calls, etc, without your client having to worry
+with filtering a lot of unrelated output.
+
+===================================================================
+On the astmanproxy.users output filtering functionality
+
+Users may now be defined in your astmanproxy.users configuration file.
+This enables a traditional user/password based login mechanism
+for Astmanproxy similar to what is found in Asterisk. Output may be
+filtered on a per-user basis.
+
+"user" is the username, secret is the password, and the (optional)
+channel setting causes filtering of events only for the specified
+channel to be sent to this user.
+
+; user=secret,channel,out_context (to Asterisk),in_context (From Asterisk)
+; steve=steve,SIP/snom190,local,
+
+===================================================================
On the 'Action: Challenge' Authentication Mechanism
John Todd wrote this excellent summary of the Action: Challenge
@@ -280,7 +324,7 @@ Be sure to use the full URL path to the version you wish to check out;
for example, do not checkout the 'branches' tree, but instead choose
which branch to checkout, as in:
-http://svncommunity.digium.com/view/astmanproxy/branches/1.2x
+http://svncommunity.digium.com/svn/astmanproxy/branches/1.2x
I will also try to post current tarballs here:
http://www.popvox.com/astmanproxy
@@ -342,4 +386,4 @@ and output format -- implemented as abstracted I/O handlers -- and
these are configurable on a per-client basis.
===================================================================
-(C) 2005 David C. Troy, dave@popvox.com
+(C) 2005-2006 David C. Troy, dave@popvox.com
diff --git a/TODO b/TODO
index d819428..839aa55 100644
--- a/TODO
+++ b/TODO
@@ -5,9 +5,7 @@ clean up debugmsg instances to add if (debug)
deal with http non-conformity better, and act on POST MIME-type inputs
Check for module versions; do not run without modules installed
- use a key? see loader.c in *
State maintenance modules
-code formatting
tcpwrappers/access control/connect mask?
libtool/autoconf/automake support
SetInputFormat proxyaction?
diff --git a/VERSIONS b/VERSIONS
index 973a86d..1939e79 100644
--- a/VERSIONS
+++ b/VERSIONS
@@ -1,7 +1,9 @@
+1.21 Major code formatting cleanup and official release of 1.21pre (trunk)
+
1.21pre Added URLDecode routine to http.c to deal with URL-encoded GET/POST data
Fixed xml.c to better deal with cli/unparsed data
Cleaned up Makefile for better support of Mac OS X 10.4
- Changed message to dynamically allocated in HandleAsterisk, solving bus error on Mac OS X 10.4
+ Changed message to be dynamically allocated in HandleAsterisk; solved bus error on Mac OS X 10.4
1.20 Cleanup and official release of 1.20pre
diff --git a/src/astmanproxy.c b/src/astmanproxy.c
index bb17935..1b6421b 100644
--- a/src/astmanproxy.c
+++ b/src/astmanproxy.c
@@ -1,9 +1,12 @@
-/* Asterisk Manager Proxy
- Copyright (c) 2005-2006 David C. Troy <dave@popvox.com>
-
- This program is free software, distributed under the terms of
- the GNU General Public License.
-
+/* Asterisk Manager Proxy
+ Copyright (c) 2005-2006 David C. Troy <dave@popvox.com>
+
+ This program is free software, distributed under the terms of
+ the GNU General Public License.
+
+ astmanproxy.c
+ contains the proxy server core, initialization, thread launching,
+ loops, and exit routines
*/
#include "astmanproxy.h"
@@ -35,683 +38,683 @@ FILE *proxylog;
int debug = 0;
void hup(int sig) {
- if (proxylog) {
- fflush(proxylog);
- fclose(proxylog);
- }
- proxylog = OpenLogfile();
- logmsg("Received HUP -- reopened log");
- ReadPerms();
- logmsg("Received HUP -- reread permissions");
+ if (proxylog) {
+ fflush(proxylog);
+ fclose(proxylog);
+ }
+ proxylog = OpenLogfile();
+ logmsg("Received HUP -- reopened log");
+ ReadPerms();
+ logmsg("Received HUP -- reread permissions");
}
void leave(int sig) {
- struct mansession *c;
- struct message sm, cm;
- struct iohandler *io;
- struct ast_server *srv;
- char iabuf[INET_ADDRSTRLEN];
-
- /* Message to send to servers */
- memset(&sm, 0, sizeof(struct message));
- AddHeader(&sm, "Action: Logoff");
-
- /* Message to send to clients */
- memset(&cm, 0, sizeof(struct message));
- AddHeader(&cm, PROXY_SHUTDOWN);
-
- if (debug)
- debugmsg("Notifying and closing sessions");
- pthread_mutex_lock (&sessionlock);
- while (sessions) {
- c = sessions;
- sessions = sessions->next;
-
- if (c->server) {
- if (debug)
- debugmsg("asterisk@%s: closing session", ast_inet_ntoa(iabuf, sizeof(iabuf), c->sin.sin_addr));
- c->output->write(c, &sm);
- logmsg("Shutdown, closed server %s", ast_inet_ntoa(iabuf, sizeof(iabuf), c->sin.sin_addr));
- } else {
- if (debug)
- debugmsg("client@%s: closing session", ast_inet_ntoa(iabuf, sizeof(iabuf), c->sin.sin_addr));
- c->output->write(c, &cm);
- logmsg("Shutdown, closed client %s", ast_inet_ntoa(iabuf, sizeof(iabuf), c->sin.sin_addr));
- }
- close_sock(c->fd); /* close tcp & ssl socket */
- pthread_mutex_destroy(&c->lock);
- free(c);
- }
- pthread_mutex_unlock (&sessionlock);
-
- /* unload server list */
- while (pc.serverlist) {
- srv = pc.serverlist;
- pc.serverlist = srv->next;
- if (debug)
- debugmsg("asterisk@%s: forgetting", srv->ast_host);
- free(srv);
- }
-
- if (debug)
- debugmsg("Closing listener socket");
- close_sock(asock); /* close tcp & ssl socket */
-
- /* unload io handlers */
- while (iohandlers) {
- io = iohandlers;
- iohandlers = iohandlers->next;
- if (debug)
- debugmsg("unloading: %s", io->formatname);
- dlclose(io->dlhandle);
- free(io);
- }
-
- if(debug)
- debugmsg("Done!\n");
- logmsg("Proxy stopped; shutting down.");
-
- fclose(proxylog);
- pthread_mutex_destroy(&sessionlock);
- pthread_mutex_destroy(&loglock);
- pthread_mutex_destroy(&debuglock);
- exit(sig);
+ struct mansession *c;
+ struct message sm, cm;
+ struct iohandler *io;
+ struct ast_server *srv;
+ char iabuf[INET_ADDRSTRLEN];
+
+ /* Message to send to servers */
+ memset(&sm, 0, sizeof(struct message));
+ AddHeader(&sm, "Action: Logoff");
+
+ /* Message to send to clients */
+ memset(&cm, 0, sizeof(struct message));
+ AddHeader(&cm, PROXY_SHUTDOWN);
+
+ if (debug)
+ debugmsg("Notifying and closing sessions");
+ pthread_mutex_lock (&sessionlock);
+ while (sessions) {
+ c = sessions;
+ sessions = sessions->next;
+
+ if (c->server) {
+ if (debug)
+ debugmsg("asterisk@%s: closing session", ast_inet_ntoa(iabuf, sizeof(iabuf), c->sin.sin_addr));
+ c->output->write(c, &sm);
+ logmsg("Shutdown, closed server %s", ast_inet_ntoa(iabuf, sizeof(iabuf), c->sin.sin_addr));
+ } else {
+ if (debug)
+ debugmsg("client@%s: closing session", ast_inet_ntoa(iabuf, sizeof(iabuf), c->sin.sin_addr));
+ c->output->write(c, &cm);
+ logmsg("Shutdown, closed client %s", ast_inet_ntoa(iabuf, sizeof(iabuf), c->sin.sin_addr));
+ }
+ close_sock(c->fd); /* close tcp & ssl socket */
+ pthread_mutex_destroy(&c->lock);
+ free(c);
+ }
+ pthread_mutex_unlock (&sessionlock);
+
+ /* unload server list */
+ while (pc.serverlist) {
+ srv = pc.serverlist;
+ pc.serverlist = srv->next;
+ if (debug)
+ debugmsg("asterisk@%s: forgetting", srv->ast_host);
+ free(srv);
+ }
+
+ if (debug)
+ debugmsg("Closing listener socket");
+ close_sock(asock); /* close tcp & ssl socket */
+
+ /* unload io handlers */
+ while (iohandlers) {
+ io = iohandlers;
+ iohandlers = iohandlers->next;
+ if (debug)
+ debugmsg("unloading: %s", io->formatname);
+ dlclose(io->dlhandle);
+ free(io);
+ }
+
+ if(debug)
+ debugmsg("Done!\n");
+ logmsg("Proxy stopped; shutting down.");
+
+ fclose(proxylog);
+ pthread_mutex_destroy(&sessionlock);
+ pthread_mutex_destroy(&loglock);
+ pthread_mutex_destroy(&debuglock);
+ exit(sig);
}
void Version( void )
{
- printf("astmanproxy: Version %s, (C) David C. Troy 2005-2006\n", PROXY_VERSION);
- return;
+ printf("astmanproxy: Version %s, (C) David C. Troy 2005-2006\n", PROXY_VERSION);
+ return;
}
void Usage( void )
{
- printf("Usage: astmanproxy [-d|-h|-v]\n");
- printf(" -d : Start in Debug Mode\n");
- printf(" -h : Displays this message\n");
- printf(" -v : Displays version information\n");
- printf("Start with no options to run as daemon\n");
- return;
+ printf("Usage: astmanproxy [-d|-h|-v]\n");
+ printf(" -d : Start in Debug Mode\n");
+ printf(" -h : Displays this message\n");
+ printf(" -v : Displays version information\n");
+ printf("Start with no options to run as daemon\n");
+ return;
}
void destroy_session(struct mansession *s)
{
- struct mansession *cur, *prev = NULL;
- char iabuf[INET_ADDRSTRLEN];
-
- pthread_mutex_lock(&sessionlock);
- cur = sessions;
- while(cur) {
- if (cur == s)
- break;
- prev = cur;
- cur = cur->next;
- }
- if (cur) {
- if (prev)
- prev->next = cur->next;
- else
- sessions = cur->next;
- debugmsg("Connection closed: %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
- close_sock(s->fd); /* close tcp/ssl socket */
- pthread_mutex_destroy(&s->lock);
- free(s);
- } else
- debugmsg("Trying to delete non-existent session %p?\n", s);
- pthread_mutex_unlock(&sessionlock);
-
- /* If there are no servers and no clients, why are we here? */
- if (!sessions) {
- logmsg("Cannot connect to any servers! Leaving!");
- leave(0);
- }
+ struct mansession *cur, *prev = NULL;
+ char iabuf[INET_ADDRSTRLEN];
+
+ pthread_mutex_lock(&sessionlock);
+ cur = sessions;
+ while(cur) {
+ if (cur == s)
+ break;
+ prev = cur;
+ cur = cur->next;
+ }
+ if (cur) {
+ if (prev)
+ prev->next = cur->next;
+ else
+ sessions = cur->next;
+ debugmsg("Connection closed: %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
+ close_sock(s->fd); /* close tcp/ssl socket */
+ pthread_mutex_destroy(&s->lock);
+ free(s);
+ } else if (debug)
+ debugmsg("Trying to delete non-existent session %p?\n", s);
+ pthread_mutex_unlock(&sessionlock);
+
+ /* If there are no servers and no clients, why are we here? */
+ if (!sessions) {
+ logmsg("Cannot connect to any servers! Leaving!");
+ leave(0);
+ }
}
int WriteClients(struct message *m) {
- struct mansession *c;
- char *actionid;
-
- c = sessions;
- while (c) {
- if ( !c->server && m->hdrcount>1 && ValidateAction(m, c, 1) ) {
- if (c->autofilter && c->actionid) {
- actionid = astman_get_header(m, ACTION_ID);
- if ( !strcmp(actionid, c->actionid) ) {
- c->output->write(c, m);
- }
- } else
- c->output->write(c, m);
- if (c->inputcomplete) {
- pthread_mutex_lock(&c->lock);
- c->outputcomplete = 1;
- pthread_mutex_unlock(&c->lock);
- }
- }
- c = c->next;
- }
- return 1;
+ struct mansession *c;
+ char *actionid;
+
+ c = sessions;
+ while (c) {
+ if ( !c->server && m->hdrcount>1 && ValidateAction(m, c, 1) ) {
+ if (c->autofilter && c->actionid) {
+ actionid = astman_get_header(m, ACTION_ID);
+ if ( !strcmp(actionid, c->actionid) )
+ c->output->write(c, m);
+ } else
+ c->output->write(c, m);
+
+ if (c->inputcomplete) {
+ pthread_mutex_lock(&c->lock);
+ c->outputcomplete = 1;
+ pthread_mutex_unlock(&c->lock);
+ }
+ }
+ c = c->next;
+ }
+ return 1;
}
int WriteAsterisk(struct message *m) {
- int i;
- char outstring[MAX_LEN], *dest;
- struct mansession *s, *first;
-
- first = NULL;
- dest = NULL;
-
- s = sessions;
-
- dest = astman_get_header(m, "Server");
- if (debug && *dest) debugmsg("set destination: %s", dest);
- while ( s ) {
- if ( s->server && (s->connected > 0) ) {
- if ( !first )
- first = s;
- if (*dest && !strcasecmp(dest, s->server->ast_host) )
- break;
- }
- s = s->next;
- }
-
- if (!s)
- s = first;
-
- /* Check for no servers and empty block -- Don't pester Asterisk if it is one*/
- if (!s || !s->server || (!m->hdrcount && !m->headers[0][0]) )
- return 1;
-
- debugmsg("writing block to %s", s->server->ast_host);
-
- pthread_mutex_lock(&s->lock);
- for (i=0; i<m->hdrcount; i++) {
- if (strcasecmp(m->headers[i], "Server:") ) {
- sprintf(outstring, "%s\r\n", m->headers[i]);
- ast_carefulwrite(s->fd, outstring, strlen(outstring), s->writetimeout );
- }
- }
- ast_carefulwrite(s->fd, "\r\n", 2, s->writetimeout);
- pthread_mutex_unlock(&s->lock);
- return 1;
+ int i;
+ char outstring[MAX_LEN], *dest;
+ struct mansession *s, *first;
+
+ first = NULL;
+ dest = NULL;
+
+ s = sessions;
+
+ dest = astman_get_header(m, "Server");
+ if (debug && *dest) debugmsg("set destination: %s", dest);
+ while ( s ) {
+ if ( s->server && (s->connected > 0) ) {
+ if ( !first )
+ first = s;
+ if (*dest && !strcasecmp(dest, s->server->ast_host) )
+ break;
+ }
+ s = s->next;
+ }
+
+ if (!s)
+ s = first;
+
+ /* Check for no servers and empty block -- Don't pester Asterisk if it is one*/
+ if (!s || !s->server || (!m->hdrcount && !m->headers[0][0]) )
+ return 1;
+
+ debugmsg("writing block to %s", s->server->ast_host);
+
+ pthread_mutex_lock(&s->lock);
+ for (i=0; i<m->hdrcount; i++) {
+ if (strcasecmp(m->headers[i], "Server:") ) {
+ sprintf(outstring, "%s\r\n", m->headers[i]);
+ ast_carefulwrite(s->fd, outstring, strlen(outstring), s->writetimeout );
+ }
+ }
+ ast_carefulwrite(s->fd, "\r\n", 2, s->writetimeout);
+ pthread_mutex_unlock(&s->lock);
+ return 1;
}
void *setactionid(char *actionid, struct message *m, struct mansession *s)
{
- pthread_mutex_lock(&s->lock);
- strncpy(s->actionid, actionid, MAX_LEN);
- pthread_mutex_unlock(&s->lock);
+ pthread_mutex_lock(&s->lock);
+ strncpy(s->actionid, actionid, MAX_LEN);
+ pthread_mutex_unlock(&s->lock);
- return 0;
+ return 0;
}
/* Handles proxy client sessions; closely based on session_do from asterisk's manager.c */
void *session_do(struct mansession *s)
{
- struct message m;
- int res;
- char *proxyaction, *actionid, *action, *key;
-
- if (s->input->onconnect)
- s->input->onconnect(s, &m);
-
- for (;;) {
- /* Get a complete message block from input handler */
- memset(&m, 0, sizeof(struct message) );
- if (debug > 3)
- debugmsg("calling %s_read...", s->input->formatname);
- res = s->input->read(s, &m);
- if (debug > 3)
- debugmsg("%s_read result = %d", s->input->formatname, res);
- m.session = s;
-
- if (res > 0) {
- /* Check for anything that requires proxy-side processing */
- if (pc.key[0] != '\0' && !s->authenticated) {
- key = astman_get_header(&m, "ProxyKey");
- if (!strcmp(key, pc.key) ) {
- pthread_mutex_lock(&s->lock);
- s->authenticated = 1;
- pthread_mutex_unlock(&s->lock);
- } else
- break;
- }
-
- proxyaction = astman_get_header(&m, "ProxyAction");
- actionid = astman_get_header(&m, ACTION_ID);
- action = astman_get_header(&m, "Action");
- if ( !strcasecmp(action, "Login") )
- if (!s->authenticated)
- ProxyLogin(s, &m);
- else
+ struct message m;
+ int res;
+ char *proxyaction, *actionid, *action, *key;
+
+ if (s->input->onconnect)
+ s->input->onconnect(s, &m);
+
+ for (;;) {
+ /* Get a complete message block from input handler */
+ memset(&m, 0, sizeof(struct message) );
+ if (debug > 3)
+ debugmsg("calling %s_read...", s->input->formatname);
+ res = s->input->read(s, &m);
+ if (debug > 3)
+ debugmsg("%s_read result = %d", s->input->formatname, res);
+ m.session = s;
+
+ if (res > 0) {
+ /* Check for anything that requires proxy-side processing */
+ if (pc.key[0] != '\0' && !s->authenticated) {
+ key = astman_get_header(&m, "ProxyKey");
+ if (!strcmp(key, pc.key) ) {
+ pthread_mutex_lock(&s->lock);
+ s->authenticated = 1;
+ pthread_mutex_unlock(&s->lock);
+ } else
+ break;
+ }
+
+ proxyaction = astman_get_header(&m, "ProxyAction");
+ actionid = astman_get_header(&m, ACTION_ID);
+ action = astman_get_header(&m, "Action");
+ if ( !strcasecmp(action, "Login") )
+ if (!s->authenticated)
+ ProxyLogin(s, &m);
+ else
+ break;
+ else if ( !strcasecmp(action, "Logoff") )
+ ProxyLogoff(s);
+ else if ( !strcasecmp(action, "Challenge") )
+ ProxyChallenge(s, &m);
+ else if ( !(*proxyaction == '\0') )
+ proxyaction_do(proxyaction, &m, s);
+ else if ( ValidateAction(&m, s, 0) ) {
+ if ( !(*actionid == '\0') )
+ setactionid(actionid, &m, s);
+ if ( !WriteAsterisk(&m) )
+ break;
+ } else {
+ SendError(s, "Action Filtered");
+ }
+ } else if (res < 0)
break;
- else if ( !strcasecmp(action, "Logoff") )
- ProxyLogoff(s);
- else if ( !strcasecmp(action, "Challenge") )
- ProxyChallenge(s, &m);
- else if ( !(*proxyaction == '\0') )
- proxyaction_do(proxyaction, &m, s);
- else if ( ValidateAction(&m, s, 0) ) {
- if ( !(*actionid == '\0') )
- setactionid(actionid, &m, s);
- if ( !WriteAsterisk(&m) )
- break;
- } else {
- SendError(s, "Action Filtered");
- }
- } else if (res < 0)
- break;
- }
-
- destroy_session(s);
- if (debug)
- debugmsg("--- exiting session_do thread ---");
- pthread_exit(NULL);
- return NULL;
+ }
+
+ destroy_session(s);
+ if (debug)
+ debugmsg("--- exiting session_do thread ---");
+ pthread_exit(NULL);
+ return NULL;
}
void *HandleAsterisk(struct mansession *s)
{
- struct message *m;
- int res,i;
- char iabuf[INET_ADDRSTRLEN];
-
- if (ConnectAsterisk(s))
- goto leave;
- if (! (m = malloc(sizeof(struct message))) )
- goto leave;
-
- for (;;) {
-
- debugmsg("asterisk@%s: attempting read...", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
- memset(&m, 0, sizeof(struct message) );
- res = s->input->read(s, m);
- m->session = s;
-
- if (res > 0) {
- if (debug) {
- for(i=0; i<m->hdrcount; i++) {
- debugmsg("asterisk@%s got: %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), m->headers[i]);
- }
- }
-
- if (!s->connected) {
- if ( !strcmp("Authentication accepted", astman_get_header(m, "Message")) ) {
- s->connected = 1;
- if (debug)
- debugmsg("asterisk@%s: connected successfully!", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr) );
- }
- if ( !strcmp("Authentication failed", astman_get_header(m, "Message")) ) {
- s->connected = -1;
- }
- }
-
- m->session = s;
- AddHeader(m, "Server: %s", m->session->server->ast_host);
-
- if (!WriteClients(m))
- break;
- } else if (res < 0) {
- /* TODO: do we need to do more than this here? or something different? */
- if ( debug )
- debugmsg("asterisk@%s: Not connected", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
- if ( ConnectAsterisk(s) )
- break;
- }
- }
- free(m);
+ struct message *m;
+ int res,i;
+ char iabuf[INET_ADDRSTRLEN];
+
+ if (ConnectAsterisk(s))
+ goto leave;
+ if (! (m = malloc(sizeof(struct message))) )
+ goto leave;
+
+ for (;;) {
+ if (debug)
+ debugmsg("asterisk@%s: attempting read...", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
+ memset(&m, 0, sizeof(struct message) );
+ res = s->input->read(s, m);
+ m->session = s;
+
+ if (res > 0) {
+ if (debug) {
+ for(i=0; i<m->hdrcount; i++) {
+ debugmsg("asterisk@%s got: %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), m->headers[i]);
+ }
+ }
+
+ if (!s->connected) {
+ if ( !strcmp("Authentication accepted", astman_get_header(m, "Message")) ) {
+ s->connected = 1;
+ if (debug)
+ debugmsg("asterisk@%s: connected successfully!", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr) );
+ }
+ if ( !strcmp("Authentication failed", astman_get_header(m, "Message")) ) {
+ s->connected = -1;
+ }
+ }
+
+ m->session = s;
+ AddHeader(m, "Server: %s", m->session->server->ast_host);
+
+ if (!WriteClients(m))
+ break;
+ } else if (res < 0) {
+ /* TODO: do we need to do more than this here? or something different? */
+ if ( debug )
+ debugmsg("asterisk@%s: Not connected", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
+ if ( ConnectAsterisk(s) )
+ break;
+ }
+ }
+ free(m);
leave:
- if (debug)
- debugmsg("asterisk@%s: Giving up and exiting thread", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr) );
- destroy_session(s);
- pthread_exit(NULL);
- return NULL;
+ if (debug)
+ debugmsg("asterisk@%s: Giving up and exiting thread", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr) );
+ destroy_session(s);
+ pthread_exit(NULL);
+ return NULL;
}
int ConnectAsterisk(struct mansession *s) {
- char iabuf[INET_ADDRSTRLEN];
- int r = 1, res = 0;
- struct message m;
-
- /* Don't try to do this if auth has already failed! */
- if (s->connected < 0 )
- return 1;
- else
- s->connected = 0;
-
- if (debug)
- debugmsg("asterisk@%s: Connecting (u=%s, p=%s, ssl=%s)", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr),
- s->server->ast_user, s->server->ast_pass, s->server->use_ssl ? "on" : "off");
-
- /* Construct auth message just once */
- memset( &m, 0, sizeof(struct message) );
- AddHeader(&m, "Action: Login");
- AddHeader(&m, "Username: %s", s->server->ast_user);
- AddHeader(&m, "Secret: %s", s->server->ast_pass);
- AddHeader(&m, "Events: %s", s->server->ast_events);
-
- for ( ;; ) {
- if ( ast_connect(s) == -1 ) {
- if (debug)
- debugmsg("asterisk@%s: Connect failed, Retrying (%d) %s [%d]",
- ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), r, strerror(errno), errno );
- if (pc.maxretries && (++r>pc.maxretries) ) {
- res = 1;
- break;
- } else
- sleep(pc.retryinterval);
- } else {
- /* Send login */
- s->output->write(s, &m);
- res = 0;
- break;
- }
- }
-
- return res;
+ char iabuf[INET_ADDRSTRLEN];
+ int r = 1, res = 0;
+ struct message m;
+
+ /* Don't try to do this if auth has already failed! */
+ if (s->connected < 0 )
+ return 1;
+ else
+ s->connected = 0;
+
+ if (debug)
+ debugmsg("asterisk@%s: Connecting (u=%s, p=%s, ssl=%s)", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr),
+ s->server->ast_user, s->server->ast_pass, s->server->use_ssl ? "on" : "off");
+
+ /* Construct auth message just once */
+ memset( &m, 0, sizeof(struct message) );
+ AddHeader(&m, "Action: Login");
+ AddHeader(&m, "Username: %s", s->server->ast_user);
+ AddHeader(&m, "Secret: %s", s->server->ast_pass);
+ AddHeader(&m, "Events: %s", s->server->ast_events);
+
+ for ( ;; ) {
+ if ( ast_connect(s) == -1 ) {
+ if (debug)
+ debugmsg("asterisk@%s: Connect failed, Retrying (%d) %s [%d]",
+ ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), r, strerror(errno), errno );
+ if (pc.maxretries && (++r>pc.maxretries) ) {
+ res = 1;
+ break;
+ } else
+ sleep(pc.retryinterval);
+ } else {
+ /* Send login */
+ s->output->write(s, &m);
+ res = 0;
+ break;
+ }
+ }
+
+ return res;
}
int StartServer(struct ast_server *srv) {
- struct mansession *s;
- struct hostent *ast_hostent;
-
- char iabuf[INET_ADDRSTRLEN];
- pthread_attr_t attr;
-
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- ast_hostent = gethostbyname(srv->ast_host);
- if (!ast_hostent) {
- logmsg("Cannot resolve host %s, cannot add!", srv->ast_host);
- debugmsg("Cannot resolve host %s, cannot add!", srv->ast_host);
- return 1;
- }
-
- s = malloc(sizeof(struct mansession));
- if ( !s ) {
- logmsg("Failed to allocate server session: %s\n", strerror(errno));
- debugmsg("Failed to allocate server session: %s\n", strerror(errno));
- return 1;
- }
-
- memset(s, 0, sizeof(struct mansession));
- SetIOHandlers(s, "standard", "standard");
- s->server = srv;
-
- bzero((char *) &s->sin,sizeof(s->sin));
- s->sin.sin_family = AF_INET;
- memcpy( &s->sin.sin_addr.s_addr, ast_hostent->h_addr, ast_hostent->h_length );
- s->sin.sin_port = htons(atoi(s->server->ast_port));
- s->fd = socket(AF_INET, SOCK_STREAM, 0);
-
- pthread_mutex_lock(&sessionlock);
- s->next = sessions;
- sessions = s;
- pthread_mutex_unlock(&sessionlock);
-
- logmsg("Allocated Asterisk server session for %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
- if (debug) {
- debugmsg("asterisk@%s: Allocated server session", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
- debugmsg("Set %s input format to %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), s->input->formatname);
- debugmsg("Set %s output format to %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), s->output->formatname);
- }
-
- if (pthread_create(&s->t, &attr, (void *)HandleAsterisk, s))
- destroy_session(s);
- else
- debugmsg("launched ast %s thread!", s->server->ast_host);
-
- pthread_attr_destroy(&attr);
- return 0;
+ struct mansession *s;
+ struct hostent *ast_hostent;
+
+ char iabuf[INET_ADDRSTRLEN];
+ pthread_attr_t attr;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ ast_hostent = gethostbyname(srv->ast_host);
+ if (!ast_hostent) {
+ logmsg("Cannot resolve host %s, cannot add!", srv->ast_host);
+ debugmsg("Cannot resolve host %s, cannot add!", srv->ast_host);
+ return 1;
+ }
+
+ s = malloc(sizeof(struct mansession));
+ if ( !s ) {
+ logmsg("Failed to allocate server session: %s\n", strerror(errno));
+ debugmsg("Failed to allocate server session: %s\n", strerror(errno));
+ return 1;
+ }
+
+ memset(s, 0, sizeof(struct mansession));
+ SetIOHandlers(s, "standard", "standard");
+ s->server = srv;
+
+ bzero((char *) &s->sin,sizeof(s->sin));
+ s->sin.sin_family = AF_INET;
+ memcpy( &s->sin.sin_addr.s_addr, ast_hostent->h_addr, ast_hostent->h_length );
+ s->sin.sin_port = htons(atoi(s->server->ast_port));
+ s->fd = socket(AF_INET, SOCK_STREAM, 0);
+
+ pthread_mutex_lock(&sessionlock);
+ s->next = sessions;
+ sessions = s;
+ pthread_mutex_unlock(&sessionlock);
+
+ logmsg("Allocated Asterisk server session for %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
+ if (debug) {
+ debugmsg("asterisk@%s: Allocated server session", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
+ debugmsg("Set %s input format to %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), s->input->formatname);
+ debugmsg("Set %s output format to %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), s->output->formatname);
+ }
+
+ if (pthread_create(&s->t, &attr, (void *)HandleAsterisk, s))
+ destroy_session(s);
+ else
+ debugmsg("launched ast %s thread!", s->server->ast_host);
+
+ pthread_attr_destroy(&attr);
+ return 0;
}
int LaunchAsteriskThreads() {
- struct ast_server *srv;
+ struct ast_server *srv;
- srv = pc.serverlist;
- while (srv) {
- StartServer(srv);
- srv = srv->next;
- }
- return 0;
+ srv = pc.serverlist;
+ while (srv) {
+ StartServer(srv);
+ srv = srv->next;
+ }
+ return 0;
}
int SetIOHandlers(struct mansession *s, char *ifmt, char *ofmt)
{
- int res = 0;
- struct iohandler *io;
-
- io = iohandlers;
- pthread_mutex_lock(&s->lock);
- while (io) {
- if ( !strcasecmp(io->formatname, ifmt) )
- s->input = io;
-
- if ( !strcasecmp(io->formatname, ofmt) )
- s->output = io;
-
- io = io->next;
- }
-
- /* set default handlers if non match was found */
- if (!s->output) {
- s->output = iohandlers;
- res = 1;
- }
-
- if (!s->input) {
- s->input = iohandlers;
- res = 1;
- }
- pthread_mutex_unlock(&s->lock);
-
- return res;
+ int res = 0;
+ struct iohandler *io;
+
+ io = iohandlers;
+ pthread_mutex_lock(&s->lock);
+ while (io) {
+ if ( !strcasecmp(io->formatname, ifmt) )
+ s->input = io;
+
+ if ( !strcasecmp(io->formatname, ofmt) )
+ s->output = io;
+
+ io = io->next;
+ }
+
+ /* set default handlers if non match was found */
+ if (!s->output) {
+ s->output = iohandlers;
+ res = 1;
+ }
+
+ if (!s->input) {
+ s->input = iohandlers;
+ res = 1;
+ }
+ pthread_mutex_unlock(&s->lock);
+
+ return res;
}
static void *accept_thread()
{
- int as;
- struct sockaddr_in sin;
- socklen_t sinlen;
- struct mansession *s;
- struct protoent *p;
- int arg = 1;
- int flags;
- pthread_attr_t attr;
- char iabuf[INET_ADDRSTRLEN];
- int is_encrypted;
-
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- for (;;) {
- sinlen = sizeof(sin);
- as = accept(asock, (struct sockaddr *)&sin, &sinlen);
- if (as < 0) {
- logmsg("Accept returned -1: %s\n", strerror(errno));
- continue;
- }
- p = (struct protoent *)getprotobyname("tcp");
- if( p ) {
- if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
- logmsg("Failed to set listener tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
- }
- }
+ int as;
+ struct sockaddr_in sin;
+ socklen_t sinlen;
+ struct mansession *s;
+ struct protoent *p;
+ int arg = 1;
+ int flags;
+ pthread_attr_t attr;
+ char iabuf[INET_ADDRSTRLEN];
+ int is_encrypted;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ for (;;) {
+ sinlen = sizeof(sin);
+ as = accept(asock, (struct sockaddr *)&sin, &sinlen);
+ if (as < 0) {
+ logmsg("Accept returned -1: %s\n", strerror(errno));
+ continue;
+ }
+ p = (struct protoent *)getprotobyname("tcp");
+ if( p ) {
+ if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
+ logmsg("Failed to set listener tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
+ }
+ }
/* SSL stuff below */
- is_encrypted = is_encrypt_request(pc.sslclhellotimeout, as);
+ is_encrypted = is_encrypt_request(pc.sslclhellotimeout, as);
debugmsg("is_encrypted: %d", is_encrypted);
- if (is_encrypted > 0) {
- if (!pc.acceptencryptedconnection) {
- if( debug )
+ if (is_encrypted > 0) {
+ if (!pc.acceptencryptedconnection) {
+ if( debug )
debugmsg("Accepting encrypted connection disabled, closing the connection \n");
- close_sock(as);
- continue;
- } else {
- if((as = saccept(as)) >= 0 ) {
+ close_sock(as);
+ continue;
+ } else {
+ if((as = saccept(as)) >= 0 ) {
if( debug )
- debugmsg("Can't accept the ssl connection, since SSL init has failed for certificate reason\n");
- close_sock(as);
- continue;
- }
- }
- } else if (is_encrypted == -1) {
- logmsg("SSL version 2 is unsecure, we don't support it\n");
- close_sock(as);
- continue;
- }
- if ( (! pc.acceptunencryptedconnection) && (as >= 0)) {
- logmsg("Unencrypted connections are not accepted and we received an unencrypted connection request\n");
- close_sock(as);
- continue;
- }
+ debugmsg("Can't accept the ssl connection, since SSL init has failed for certificate reason\n");
+ close_sock(as);
+ continue;
+ }
+ }
+ } else if (is_encrypted == -1) {
+ logmsg("SSL version 2 is unsecure, we don't support it\n");
+ close_sock(as);
+ continue;
+ }
+ if ( (! pc.acceptunencryptedconnection) && (as >= 0)) {
+ logmsg("Unencrypted connections are not accepted and we received an unencrypted connection request\n");
+ close_sock(as);
+ continue;
+ }
/* SSL stuff end */
- s = malloc(sizeof(struct mansession));
- if ( !s ) {
- logmsg("Failed to allocate listener session: %s\n", strerror(errno));
- continue;
- }
- memset(s, 0, sizeof(struct mansession));
- memcpy(&s->sin, &sin, sizeof(sin));
+ s = malloc(sizeof(struct mansession));
+ if ( !s ) {
+ logmsg("Failed to allocate listener session: %s\n", strerror(errno));
+ continue;
+ }
+ memset(s, 0, sizeof(struct mansession));
+ memcpy(&s->sin, &sin, sizeof(sin));
- /* For safety, make sure socket is non-blocking */
- flags = fcntl(get_real_fd(as), F_GETFL);
+ /* For safety, make sure socket is non-blocking */
+ flags = fcntl(get_real_fd(as), F_GETFL);
fcntl(get_real_fd(as), F_SETFL, flags | O_NONBLOCK);
- pthread_mutex_init(&s->lock, NULL);
- s->fd = as;
- SetIOHandlers(s, pc.inputformat, pc.outputformat);
- s->autofilter = pc.autofilter;
- s->server = NULL;
-
- pthread_mutex_lock(&sessionlock);
- s->next = sessions;
- sessions = s;
- pthread_mutex_unlock(&sessionlock);
-
- logmsg("Connection received from %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
- if (debug) {
- debugmsg("Connection received from %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
- debugmsg("Set %s input format to %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), s->input->formatname);
- debugmsg("Set %s output format to %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), s->output->formatname);
- }
-
- if (pthread_create(&s->t, &attr, (void *)session_do, s))
- destroy_session(s);
- }
- pthread_attr_destroy(&attr);
- return NULL;
+ pthread_mutex_init(&s->lock, NULL);
+ s->fd = as;
+ SetIOHandlers(s, pc.inputformat, pc.outputformat);
+ s->autofilter = pc.autofilter;
+ s->server = NULL;
+
+ pthread_mutex_lock(&sessionlock);
+ s->next = sessions;
+ sessions = s;
+ pthread_mutex_unlock(&sessionlock);
+
+ logmsg("Connection received from %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
+ if (debug) {
+ debugmsg("Connection received from %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
+ debugmsg("Set %s input format to %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), s->input->formatname);
+ debugmsg("Set %s output format to %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), s->output->formatname);
+ }
+
+ if (pthread_create(&s->t, &attr, (void *)session_do, s))
+ destroy_session(s);
+ }
+ pthread_attr_destroy(&attr);
+ return NULL;
}
int main(int argc, char *argv[])
{
- struct sockaddr_in serv_sock_addr, client_sock_addr;
- int cli_addrlen;
- struct linger lingerstruct; /* for socket reuse */
- int flag; /* for socket reuse */
- pid_t pid;
- char i;
-
- /* Figure out if we are in debug mode, handle other switches */
- while (( i = getopt( argc, argv, "dhv" ) ) != EOF )
- {
- switch( i ) {
- case 'd':
- debug++;
- break;
- case 'h':
- Usage();
- exit(0);
- case 'v':
- Version();
- exit(0);
- case '?':
- Usage();
- exit(1);
- }
- }
-
-
- ReadConfig();
- proxylog = OpenLogfile();
- debugmsg("loading handlers");
- LoadHandlers();
- debugmsg("loaded handlers");
-
- if (SetProcUID()) {
- fprintf(stderr,"Cannot set user/group! Check proc_user and proc_group config setting!\n");
- exit(1);
- }
-
- /* If we are not in debug mode, then fork to background */
- if (!debug) {
- if ( (pid = fork()) < 0)
- exit( 1 );
- else if ( pid > 0)
- exit( 0 );
- }
-
- /* Setup signal handlers */
- (void) signal(SIGINT,leave);
- (void) signal(SIGHUP,hup);
- (void) signal(SIGTERM,leave);
- (void) signal(SIGPIPE, SIG_IGN);
-
- /* Initialize global mutexes */
- pthread_mutex_init(&sessionlock, NULL);
- pthread_mutex_init(&userslock, NULL);
- pthread_mutex_init(&loglock, NULL);
- pthread_mutex_init(&debuglock, NULL);
-
- /* Read initial state for user permissions */
- ReadPerms();
-
- /* Initialize SSL Client-Side Context */
- client_init_secure();
-
- /* Initialize global client/server list */
- sessions = NULL;
- LaunchAsteriskThreads();
-
- /* Setup listener socket to setup new sessions... */
- if ((asock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- fprintf(stderr,"Cannot create listener socket!\n");
- exit(1);
- }
- bzero((char *) &serv_sock_addr, sizeof serv_sock_addr );
- serv_sock_addr.sin_family = AF_INET;
-
- if ( !strcmp(pc.listen_addr,"*") )
- serv_sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- else
- serv_sock_addr.sin_addr.s_addr = inet_addr( pc.listen_addr);
- serv_sock_addr.sin_port = htons((short)pc.listen_port);
-
- /* Set listener socket re-use options */
- setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, (void *)&flag, sizeof(flag));
- lingerstruct.l_onoff = 1;
- lingerstruct.l_linger = 5;
- setsockopt(asock, SOL_SOCKET, SO_LINGER, (void *)&lingerstruct, sizeof(lingerstruct));
-
- if (bind(asock, (struct sockaddr *) &serv_sock_addr, sizeof serv_sock_addr ) < 0) {
- fprintf(stderr,"Cannot bind to listener socket!\n");
- exit(1);
- }
-
- listen(asock, 5);
- cli_addrlen = sizeof(client_sock_addr);
- if (debug)
- debugmsg("Listening for connections");
- logmsg("Proxy Started: Listening for connections");
-
- /* Launch listener thread */
- accept_thread();
-
- pthread_exit(NULL);
- exit(0);
-}
-
+ struct sockaddr_in serv_sock_addr, client_sock_addr;
+ int cli_addrlen;
+ struct linger lingerstruct; /* for socket reuse */
+ int flag; /* for socket reuse */
+ pid_t pid;
+ char i;
+
+ /* Figure out if we are in debug mode, handle other switches */
+ while (( i = getopt( argc, argv, "dhv" ) ) != EOF )
+ {
+ switch( i ) {
+ case 'd':
+ debug++;
+ break;
+ case 'h':
+ Usage();
+ exit(0);
+ case 'v':
+ Version();
+ exit(0);
+ case '?':
+ Usage();
+ exit(1);
+ }
+ }
+
+
+ ReadConfig();
+ proxylog = OpenLogfile();
+ debugmsg("loading handlers");
+ LoadHandlers();
+ debugmsg("loaded handlers");
+
+ if (SetProcUID()) {
+ fprintf(stderr,"Cannot set user/group! Check proc_user and proc_group config setting!\n");
+ exit(1);
+ }
+
+ /* If we are not in debug mode, then fork to background */
+ if (!debug) {
+ if ( (pid = fork()) < 0)
+ exit( 1 );
+ else if ( pid > 0)
+ exit( 0 );
+ }
+
+ /* Setup signal handlers */
+ (void) signal(SIGINT,leave);
+ (void) signal(SIGHUP,hup);
+ (void) signal(SIGTERM,leave);
+ (void) signal(SIGPIPE, SIG_IGN);
+
+ /* Initialize global mutexes */
+ pthread_mutex_init(&sessionlock, NULL);
+ pthread_mutex_init(&userslock, NULL);
+ pthread_mutex_init(&loglock, NULL);
+ pthread_mutex_init(&debuglock, NULL);
+
+ /* Read initial state for user permissions */
+ ReadPerms();
+
+ /* Initialize SSL Client-Side Context */
+ client_init_secure();
+
+ /* Initialize global client/server list */
+ sessions = NULL;
+ LaunchAsteriskThreads();
+
+ /* Setup listener socket to setup new sessions... */
+ if ((asock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ fprintf(stderr,"Cannot create listener socket!\n");
+ exit(1);
+ }
+ bzero((char *) &serv_sock_addr, sizeof serv_sock_addr );
+ serv_sock_addr.sin_family = AF_INET;
+
+ if ( !strcmp(pc.listen_addr,"*") )
+ serv_sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ else
+ serv_sock_addr.sin_addr.s_addr = inet_addr( pc.listen_addr);
+
+ serv_sock_addr.sin_port = htons((short)pc.listen_port);
+
+ /* Set listener socket re-use options */
+ setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, (void *)&flag, sizeof(flag));
+ lingerstruct.l_onoff = 1;
+ lingerstruct.l_linger = 5;
+ setsockopt(asock, SOL_SOCKET, SO_LINGER, (void *)&lingerstruct, sizeof(lingerstruct));
+
+ if (bind(asock, (struct sockaddr *) &serv_sock_addr, sizeof serv_sock_addr ) < 0) {
+ fprintf(stderr,"Cannot bind to listener socket!\n");
+ exit(1);
+ }
+
+ listen(asock, 5);
+ cli_addrlen = sizeof(client_sock_addr);
+ if (debug)
+ debugmsg("Listening for connections");
+ logmsg("Proxy Started: Listening for connections");
+
+ /* Launch listener thread */
+ accept_thread();
+
+ pthread_exit(NULL);
+ exit(0);
+} \ No newline at end of file
diff --git a/src/common.c b/src/common.c
index d6bea7a..b87d564 100644
--- a/src/common.c
+++ b/src/common.c
@@ -1,3 +1,14 @@
+/* Asterisk Manager Proxy
+ Copyright (c) 2005-2006 David C. Troy <dave@popvox.com>
+
+ This program is free software, distributed under the terms of
+ the GNU General Public License.
+
+ common.c
+ contains common utililty functions used by both astmanproxy
+ core as well as (many) of the various I/O handlers
+*/
+
#include "astmanproxy.h"
/* This routine based on get_input from Asterisk manager.c */
@@ -5,131 +16,131 @@
/* Used by standard.c and other input handlers */
int get_input(struct mansession *s, char *output)
{
- /* output must have at least sizeof(s->inbuf) space */
- int res;
- int x;
- struct pollfd fds[1];
- char iabuf[INET_ADDRSTRLEN];
-
- /* Look for \r\n from the front, our preferred end of line */
- for (x=0;x<s->inlen;x++) {
- int xtra = 0;
- if (s->inbuf[x] == '\n') {
- if (x && s->inbuf[x-1] == '\r') {
- xtra = 1;
- }
- /* Copy output data not including \r\n */
- memcpy(output, s->inbuf, x - xtra);
- /* Add trailing \0 */
- output[x-xtra] = '\0';
- /* Move remaining data back to the front */
- memmove(s->inbuf, s->inbuf + x + 1, s->inlen - x);
- s->inlen -= (x + 1);
- return 1;
- }
- }
-
- if (s->inlen >= sizeof(s->inbuf) - 1) {
- if (debug)
- debugmsg("Warning: Got long line with no end from %s: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), s->inbuf);
- s->inlen = 0;
- }
+ /* output must have at least sizeof(s->inbuf) space */
+ int res;
+ int x;
+ struct pollfd fds[1];
+ char iabuf[INET_ADDRSTRLEN];
+
+ /* Look for \r\n from the front, our preferred end of line */
+ for (x=0;x<s->inlen;x++) {
+ int xtra = 0;
+ if (s->inbuf[x] == '\n') {
+ if (x && s->inbuf[x-1] == '\r') {
+ xtra = 1;
+ }
+ /* Copy output data not including \r\n */
+ memcpy(output, s->inbuf, x - xtra);
+ /* Add trailing \0 */
+ output[x-xtra] = '\0';
+ /* Move remaining data back to the front */
+ memmove(s->inbuf, s->inbuf + x + 1, s->inlen - x);
+ s->inlen -= (x + 1);
+ return 1;
+ }
+ }
+
+ if (s->inlen >= sizeof(s->inbuf) - 1) {
+ if (debug)
+ debugmsg("Warning: Got long line with no end from %s: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), s->inbuf);
+ s->inlen = 0;
+ }
/* get actual fd, even if a negative SSL fd */
- fds[0].fd = get_real_fd(s->fd);
+ fds[0].fd = get_real_fd(s->fd);
- fds[0].events = POLLIN;
- do {
- res = poll(fds, 1, -1);
+ fds[0].events = POLLIN;
+ do {
+ res = poll(fds, 1, -1);
if (res < 0) {
- if (errno == EINTR) {
- if (s->dead)
- return -1;
- continue;
- }
- if (debug)
- debugmsg("Select returned error");
+ if (errno == EINTR) {
+ if (s->dead)
+ return -1;
+ continue;
+ }
+ if (debug)
+ debugmsg("Select returned error");
return -1;
- } else if (res > 0) {
- pthread_mutex_lock(&s->lock);
+ } else if (res > 0) {
+ pthread_mutex_lock(&s->lock);
/* read from socket; SSL or otherwise */
res = m_recv(s->fd, s->inbuf + s->inlen, sizeof(s->inbuf) - 1 - s->inlen, 0);
- pthread_mutex_unlock(&s->lock);
- if (res < 1)
- return -1;
+ pthread_mutex_unlock(&s->lock);
+ if (res < 1)
+ return -1;
break;
- }
+ }
} while(1);
- /* We have some input, but it's not ready for processing */
- s->inlen += res;
- s->inbuf[s->inlen] = '\0';
- return 0;
+ /* We have some input, but it's not ready for processing */
+ s->inlen += res;
+ s->inbuf[s->inlen] = '\0';
+ return 0;
}
char *astman_get_header(struct message *m, char *var)
{
- char cmp[80];
- int x;
- snprintf(cmp, sizeof(cmp), "%s: ", var);
- for (x=0;x<m->hdrcount;x++)
- if (!strncasecmp(cmp, m->headers[x], strlen(cmp)))
- return m->headers[x] + strlen(cmp);
- return "";
+ char cmp[80];
+ int x;
+ snprintf(cmp, sizeof(cmp), "%s: ", var);
+ for (x=0;x<m->hdrcount;x++)
+ if (!strncasecmp(cmp, m->headers[x], strlen(cmp)))
+ return m->headers[x] + strlen(cmp);
+ return "";
}
int AddHeader(struct message *m, const char *fmt, ...) {
- va_list ap;
+ va_list ap;
- int res;
+ int res;
- if (m->hdrcount < MAX_HEADERS - 1) {
- va_start(ap, fmt);
- vsprintf(m->headers[m->hdrcount], fmt, ap);
- va_end(ap);
- m->hdrcount++;
- res = 0;
- } else
- res = 1;
+ if (m->hdrcount < MAX_HEADERS - 1) {
+ va_start(ap, fmt);
+ vsprintf(m->headers[m->hdrcount], fmt, ap);
+ va_end(ap);
+ m->hdrcount++;
+ res = 0;
+ } else
+ res = 1;
- return res;
+ return res;
}
/* Recursive thread safe replacement of inet_ntoa */
const char *ast_inet_ntoa(char *buf, int bufsiz, struct in_addr ia)
{
- return inet_ntop(AF_INET, &ia, buf, bufsiz);
+ return inet_ntop(AF_INET, &ia, buf, bufsiz);
}
/*! If you are calling ast_carefulwrite, it is assumed that you are calling
- it on a file descriptor that _DOES_ have NONBLOCK set. This way,
- there is only one system call made to do a write, unless we actually
- have a need to wait. This way, we get better performance. */
+ it on a file descriptor that _DOES_ have NONBLOCK set. This way,
+ there is only one system call made to do a write, unless we actually
+ have a need to wait. This way, we get better performance. */
int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
{
- /* Try to write string, but wait no more than ms milliseconds
- before timing out */
- int res=0;
- struct pollfd fds[1];
- while(len) {
- res = m_send(fd, s, len);
- if ((res < 0) && (errno != EAGAIN)) {
- return -1;
- }
- if (res < 0) res = 0;
- len -= res;
- s += res;
- res = 0;
- if (len) {
- fds[0].fd = get_real_fd(fd);
- fds[0].events = POLLOUT;
- /* Wait until writable again */
- res = poll(fds, 1, timeoutms);
- if (res < 1)
- return -1;
- }
- }
- return res;
+ /* Try to write string, but wait no more than ms milliseconds
+ before timing out */
+ int res=0;
+ struct pollfd fds[1];
+ while(len) {
+ res = m_send(fd, s, len);
+ if ((res < 0) && (errno != EAGAIN)) {
+ return -1;
+ }
+ if (res < 0) res = 0;
+ len -= res;
+ s += res;
+ res = 0;
+ if (len) {
+ fds[0].fd = get_real_fd(fd);
+ fds[0].events = POLLOUT;
+ /* Wait until writable again */
+ res = poll(fds, 1, timeoutms);
+ if (res < 1)
+ return -1;
+ }
+ }
+ return res;
}
diff --git a/src/config.c b/src/config.c
index f642aa6..4a9ce2b 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1,3 +1,14 @@
+/* Asterisk Manager Proxy
+ Copyright (c) 2005-2006 David C. Troy <dave@popvox.com>
+
+ This program is free software, distributed under the terms of
+ the GNU General Public License.
+
+ config.c
+ routines to read and parse the configuration file and initialize
+ the internal configuration datastructures
+*/
+
#include <pwd.h>
#include <grp.h>
#include "astmanproxy.h"
@@ -6,300 +17,297 @@ extern struct iohandler *iohandlers;
void *add_server(char *srvspec) {
- int ccount = 0;
- struct ast_server *srv;
- char *s;
- char usessl[10];
-
- /* malloc ourselves a server credentials structure */
- srv = malloc(sizeof(struct ast_server));
- if ( !srv ) {
- fprintf(stderr, "Failed to allocate server credentials: %s\n", strerror(errno));
- exit(1);
- }
- memset(srv, 0, sizeof (struct ast_server) );
- memset(usessl, 0, sizeof (usessl) );
-
- s = srvspec;
- do {
- *s = tolower(*s);
- if ( *s == ',' ) {
- ccount++;
- continue;
- }
- switch(ccount) {
- case 0:
- strncat(srv->ast_host, s, 1);
- break;
- case 1:
- strncat(srv->ast_port, s, 1);
- break;
- case 2:
- strncat(srv->ast_user, s, 1);
- break;
- case 3:
- strncat(srv->ast_pass, s, 1);
- break;
- case 4:
- strncat(srv->ast_events, s, 1);
- break;
- case 5:
- strncat(usessl, s, 1);
- break;
- }
- } while (*(s++));
-
-
- if (!*srv->ast_host || !*srv->ast_port || !*srv->ast_user || !*srv->ast_pass || !*srv->ast_events || !*usessl) {
- fprintf(stderr, "Aborting: server spec incomplete: %s\n", srvspec);
- free(srv);
- exit(1);
- }
-
- srv->use_ssl = (!strcmp(usessl,"on"));
- srv->next = pc.serverlist;
- pc.serverlist = srv;
-
- return 0;
+ int ccount = 0;
+ struct ast_server *srv;
+ char *s;
+ char usessl[10];
+
+ /* malloc ourselves a server credentials structure */
+ srv = malloc(sizeof(struct ast_server));
+ if ( !srv ) {
+ fprintf(stderr, "Failed to allocate server credentials: %s\n", strerror(errno));
+ exit(1);
+ }
+ memset(srv, 0, sizeof (struct ast_server) );
+ memset(usessl, 0, sizeof (usessl) );
+
+ s = srvspec;
+ do {
+ *s = tolower(*s);
+ if ( *s == ',' ) {
+ ccount++;
+ continue;
+ }
+ switch(ccount) {
+ case 0:
+ strncat(srv->ast_host, s, 1);
+ break;
+ case 1:
+ strncat(srv->ast_port, s, 1);
+ break;
+ case 2:
+ strncat(srv->ast_user, s, 1);
+ break;
+ case 3:
+ strncat(srv->ast_pass, s, 1);
+ break;
+ case 4:
+ strncat(srv->ast_events, s, 1);
+ break;
+ case 5:
+ strncat(usessl, s, 1);
+ break;
+ }
+ } while (*(s++));
+
+
+ if (!*srv->ast_host || !*srv->ast_port || !*srv->ast_user || !*srv->ast_pass || !*srv->ast_events || !*usessl) {
+ fprintf(stderr, "Aborting: server spec incomplete: %s\n", srvspec);
+ free(srv);
+ exit(1);
+ }
+
+ srv->use_ssl = (!strcmp(usessl,"on"));
+ srv->next = pc.serverlist;
+ pc.serverlist = srv;
+
+ return 0;
}
void *processline(char *s) {
- char name[80],value[80];
- int nvstate = 0;
-
-
- memset (name,0,sizeof name);
- memset (value,0,sizeof value);
-
- do {
- *s = tolower(*s);
-
- if ( *s == ' ' || *s == '\t')
- continue;
- if ( *s == ';' || *s == '#' || *s == '\r' || *s == '\n' )
- break;
- if ( *s == '=' ) {
- nvstate = 1;
- continue;
- }
- if (!nvstate)
- strncat(name, s, 1);
- else
- strncat(value, s, 1);
- } while (*(s++));
-
- if (debug)
- debugmsg("config: %s, %s", name, value);
-
- if ( !strcmp(name,"host") )
- add_server(value);
- else if (!strcmp(name,"retryinterval") )
- pc.retryinterval = atoi(value);
- else if (!strcmp(name,"maxretries") )
- pc.maxretries = atoi(value);
- else if (!strcmp(name,"listenaddress") )
- strcpy(pc.listen_addr, value);
- else if (!strcmp(name,"listenport") )
- pc.listen_port = atoi(value);
- else if (!strcmp(name,"asteriskwritetimeout") )
- pc.asteriskwritetimeout = atoi(value);
- else if (!strcmp(name,"clientwritetimeout") )
- pc.clientwritetimeout = atoi(value);
- else if (!strcmp(name,"sslclienthellotimeout") )
- pc.sslclhellotimeout = atoi(value);
- else if (!strcmp(name,"authrequired") )
- pc.authrequired = strcmp(value,"yes") ? 0 : 1;
- else if (!strcmp(name,"acceptencryptedconnection") )
- pc.acceptencryptedconnection = strcmp(value,"yes") ? 0 : 1;
- else if (!strcmp(name,"acceptunencryptedconnection") )
- pc.acceptunencryptedconnection = strcmp(value,"yes") ? 0 : 1;
- else if (!strcmp(name,"certfile") )
- strcpy(pc.certfile, value);
- else if (!strcmp(name,"proxykey") )
- strcpy(pc.key, value);
- else if (!strcmp(name,"proc_user") )
- strcpy(pc.proc_user, value);
- else if (!strcmp(name,"proc_group") )
- strcpy(pc.proc_group, value);
- else if (!strcmp(name,"logfile") )
- strcpy(pc.logfile, value);
- else if (!strcmp(name,"autofilter") )
- pc.autofilter = strcmp(value,"on") ? 0 : 1;
- else if (!strcmp(name,"outputformat") )
- strcpy(pc.outputformat, value);
- else if (!strcmp(name,"inputformat") )
- strcpy(pc.inputformat, value);
-
- return 0;
+ char name[80],value[80];
+ int nvstate = 0;
+
+
+ memset (name,0,sizeof name);
+ memset (value,0,sizeof value);
+
+ do {
+ *s = tolower(*s);
+
+ if ( *s == ' ' || *s == '\t')
+ continue;
+ if ( *s == ';' || *s == '#' || *s == '\r' || *s == '\n' )
+ break;
+ if ( *s == '=' ) {
+ nvstate = 1;
+ continue;
+ }
+ if (!nvstate)
+ strncat(name, s, 1);
+ else
+ strncat(value, s, 1);
+ } while (*(s++));
+
+ if (debug)
+ debugmsg("config: %s, %s", name, value);
+
+ if ( !strcmp(name,"host") )
+ add_server(value);
+ else if (!strcmp(name,"retryinterval") )
+ pc.retryinterval = atoi(value);
+ else if (!strcmp(name,"maxretries") )
+ pc.maxretries = atoi(value);
+ else if (!strcmp(name,"listenaddress") )
+ strcpy(pc.listen_addr, value);
+ else if (!strcmp(name,"listenport") )
+ pc.listen_port = atoi(value);
+ else if (!strcmp(name,"asteriskwritetimeout") )
+ pc.asteriskwritetimeout = atoi(value);
+ else if (!strcmp(name,"clientwritetimeout") )
+ pc.clientwritetimeout = atoi(value);
+ else if (!strcmp(name,"sslclienthellotimeout") )
+ pc.sslclhellotimeout = atoi(value);
+ else if (!strcmp(name,"authrequired") )
+ pc.authrequired = strcmp(value,"yes") ? 0 : 1;
+ else if (!strcmp(name,"acceptencryptedconnection") )
+ pc.acceptencryptedconnection = strcmp(value,"yes") ? 0 : 1;
+ else if (!strcmp(name,"acceptunencryptedconnection") )
+ pc.acceptunencryptedconnection = strcmp(value,"yes") ? 0 : 1;
+ else if (!strcmp(name,"certfile") )
+ strcpy(pc.certfile, value);
+ else if (!strcmp(name,"proxykey") )
+ strcpy(pc.key, value);
+ else if (!strcmp(name,"proc_user") )
+ strcpy(pc.proc_user, value);
+ else if (!strcmp(name,"proc_group") )
+ strcpy(pc.proc_group, value);
+ else if (!strcmp(name,"logfile") )
+ strcpy(pc.logfile, value);
+ else if (!strcmp(name,"autofilter") )
+ pc.autofilter = strcmp(value,"on") ? 0 : 1;
+ else if (!strcmp(name,"outputformat") )
+ strcpy(pc.outputformat, value);
+ else if (!strcmp(name,"inputformat") )
+ strcpy(pc.inputformat, value);
+
+ return 0;
}
int LoadHandlers() {
- void *dlhandle = NULL;
- const char *error;
- char fmt[20], moddir[80] = MDIR, modfile[80];
- DIR *mods;
- struct dirent *d;
- void *rh, *wh, *och;
- struct iohandler *io = NULL;
-
- mods = opendir(moddir);
- if (!mods)
- exit(1);
-
- while((d = readdir(mods))) {
- /* Must end in .so to load it. */
- if ( (strlen(d->d_name) > 3) && !strcasecmp(d->d_name + strlen(d->d_name) - 3, ".so") ) {
-
- memset(fmt, 0, sizeof fmt);
- strncpy(fmt, d->d_name, strlen(d->d_name) - 3);
-
- sprintf(modfile, "%s/%s", moddir, d->d_name);
- if (debug)
- debugmsg("loading: module %s (%s)", fmt, modfile);
-
- dlhandle = dlopen (modfile, RTLD_LAZY);
- if (!dlhandle) {
- fprintf(stderr, "dlopen failed: %s\n", dlerror());
- exit(1);
- }
-
- rh = dlsym(dlhandle, "_read");
- if ((error = dlerror()) != NULL) {
- if (debug)
- debugmsg("loading: note, %s_read does not exist; ignoring", fmt);
- }
-
- wh = dlsym(dlhandle, "_write");
- if ((error = dlerror()) != NULL) {
- if (debug)
- debugmsg("loading: note, %s_write does not exist; ignoring", fmt);
- }
-
- och = dlsym(dlhandle, "_onconnect");
- if ((error = dlerror()) != NULL) {
- if (debug)
- debugmsg("loading: note, %s_onconnect does not exist; ignoring", fmt);
- }
-
- if (rh || wh) {
- io = malloc(sizeof(struct iohandler));
- memset(io, 0, sizeof(struct iohandler));
- strcpy(io->formatname, fmt);
- if (rh)
- io->read = rh;
- if (wh)
- io->write = wh;
- if (och)
- io->onconnect = och;
-
- io->dlhandle = dlhandle;
- io->next = iohandlers;
- iohandlers = io;
- } else
- dlclose(dlhandle);
-
- }
- }
- closedir(mods);
-
- if (!iohandlers) {
- fprintf(stderr, "Unable to load *ANY* IO Handlers from %s!\n", MDIR);
- exit(1);
- }
-
- return 0;
+ void *dlhandle = NULL;
+ const char *error;
+ char fmt[20], moddir[80] = MDIR, modfile[80];
+ DIR *mods;
+ struct dirent *d;
+ void *rh, *wh, *och;
+ struct iohandler *io = NULL;
+
+ mods = opendir(moddir);
+ if (!mods)
+ exit(1);
+
+ while((d = readdir(mods))) {
+ /* Must end in .so to load it. */
+ if ( (strlen(d->d_name) > 3) && !strcasecmp(d->d_name + strlen(d->d_name) - 3, ".so") ) {
+
+ memset(fmt, 0, sizeof fmt);
+ strncpy(fmt, d->d_name, strlen(d->d_name) - 3);
+
+ sprintf(modfile, "%s/%s", moddir, d->d_name);
+ if (debug)
+ debugmsg("loading: module %s (%s)", fmt, modfile);
+
+ dlhandle = dlopen (modfile, RTLD_LAZY);
+ if (!dlhandle) {
+ fprintf(stderr, "dlopen failed: %s\n", dlerror());
+ exit(1);
+ }
+
+ rh = dlsym(dlhandle, "_read");
+ if ((error = dlerror()) != NULL) {
+ if (debug)
+ debugmsg("loading: note, %s_read does not exist; ignoring", fmt);
+ }
+
+ wh = dlsym(dlhandle, "_write");
+ if ((error = dlerror()) != NULL) {
+ if (debug)
+ debugmsg("loading: note, %s_write does not exist; ignoring", fmt);
+ }
+
+ och = dlsym(dlhandle, "_onconnect");
+ if ((error = dlerror()) != NULL) {
+ if (debug)
+ debugmsg("loading: note, %s_onconnect does not exist; ignoring", fmt);
+ }
+
+ if (rh || wh) {
+ io = malloc(sizeof(struct iohandler));
+ memset(io, 0, sizeof(struct iohandler));
+ strcpy(io->formatname, fmt);
+ if (rh)
+ io->read = rh;
+ if (wh)
+ io->write = wh;
+ if (och)
+ io->onconnect = och;
+
+ io->dlhandle = dlhandle;
+ io->next = iohandlers;
+ iohandlers = io;
+ } else
+ dlclose(dlhandle);
+ }
+ }
+ closedir(mods);
+
+ if (!iohandlers) {
+ fprintf(stderr, "Unable to load *ANY* IO Handlers from %s!\n", MDIR);
+ exit(1);
+ }
+
+ return 0;
}
int ReadConfig() {
- FILE *FP;
- char buf[1024];
- char cfn[80];
+ FILE *FP;
+ char buf[1024];
+ char cfn[80];
- memset( &pc, 0, sizeof pc );
+ memset( &pc, 0, sizeof pc );
- /* Set nonzero config defaults */
- pc.asteriskwritetimeout = 100;
- pc.clientwritetimeout = 100;
- pc.sslclhellotimeout = 500;
+ /* Set nonzero config defaults */
+ pc.asteriskwritetimeout = 100;
+ pc.clientwritetimeout = 100;
+ pc.sslclhellotimeout = 500;
- sprintf(cfn, "%s/%s", CDIR, CFILE);
- FP = fopen( cfn, "r" );
+ sprintf(cfn, "%s/%s", CDIR, CFILE);
+ FP = fopen( cfn, "r" );
- if ( !FP )
- {
- fprintf(stderr, "Unable to open config file: %s/%s!\n", CDIR, CFILE);
- exit( 1 );
- }
+ if ( !FP ) {
+ fprintf(stderr, "Unable to open config file: %s/%s!\n", CDIR, CFILE);
+ exit( 1 );
+ }
- if (debug)
- debugmsg("config: parsing configuration file: %s", cfn);
+ if (debug)
+ debugmsg("config: parsing configuration file: %s", cfn);
- while ( fgets( buf, sizeof buf, FP ) ) {
- if (*buf == ';' || *buf == '\r' || *buf == '\n' || *buf == '#') continue;
- processline(buf);
- }
+ while ( fgets( buf, sizeof buf, FP ) ) {
+ if (*buf == ';' || *buf == '\r' || *buf == '\n' || *buf == '#') continue;
+ processline(buf);
+ }
- fclose(FP);
+ fclose(FP);
- /* initialize SSL layer with our server certfile */
- init_secure(pc.certfile);
+ /* initialize SSL layer with our server certfile */
+ init_secure(pc.certfile);
- return 0;
+ return 0;
}
FILE *OpenLogfile() {
- FILE *FP;
- FP = fopen( pc.logfile, "a" );
- if ( !FP ) {
- fprintf(stderr, "Unable to open logfile: %s!\n", pc.logfile);
- exit( 1 );
- }
-
- return FP;
+ FILE *FP;
+ FP = fopen( pc.logfile, "a" );
+ if ( !FP ) {
+ fprintf(stderr, "Unable to open logfile: %s!\n", pc.logfile);
+ exit( 1 );
+ }
+
+ return FP;
}
int SetProcUID() {
- struct passwd *pwent;
- struct group *gp;
- uid_t newuid = 0;
- gid_t newgid = 0;
-
- if ((pwent = (struct passwd *)getpwnam( pc.proc_user )) == NULL) {
- fprintf(stderr, "getpwnam(%s) failed.\n", pc.proc_user);
- return(-1);
- } else
- newuid = pwent->pw_uid;
-
- if ( newuid == 0 ) {
- fprintf(stderr, "getpwnam(%s) returned root user; aborting!\n", pc.proc_user);
- return(-1);
- }
-
- if ((gp = (struct group *)getgrnam( pc.proc_group )) == NULL) {
- fprintf(stderr, "getgrnam(%s) failed.\n", pc.proc_group);
- return(-1);
- } else
- newgid = gp->gr_gid;
-
- if ( chown( pc.logfile, newuid, newgid ) < 0 )
- {
- fprintf(stderr, "chown(%d,%d) of %s failed!\n", newuid, newgid, pc.logfile);
- return( -1 );
- }
-
- if (setgid(newgid) < 0) {
- fprintf(stderr, "setgid(%d) failed.\n", newgid);
- return(-1);
- }
-
- if (setuid(newuid) < 0) {
- fprintf(stderr, "setuid(%d) failed.\n", newuid);
- return(-1);
- }
-
- return 0;
+ struct passwd *pwent;
+ struct group *gp;
+ uid_t newuid = 0;
+ gid_t newgid = 0;
+
+ if ((pwent = (struct passwd *)getpwnam( pc.proc_user )) == NULL) {
+ fprintf(stderr, "getpwnam(%s) failed.\n", pc.proc_user);
+ return(-1);
+ } else
+ newuid = pwent->pw_uid;
+
+ if ( newuid == 0 ) {
+ fprintf(stderr, "getpwnam(%s) returned root user; aborting!\n", pc.proc_user);
+ return(-1);
+ }
+
+ if ((gp = (struct group *)getgrnam( pc.proc_group )) == NULL) {
+ fprintf(stderr, "getgrnam(%s) failed.\n", pc.proc_group);
+ return(-1);
+ } else
+ newgid = gp->gr_gid;
+
+ if ( chown( pc.logfile, newuid, newgid ) < 0 ) {
+ fprintf(stderr, "chown(%d,%d) of %s failed!\n", newuid, newgid, pc.logfile);
+ return( -1 );
+ }
+
+ if (setgid(newgid) < 0) {
+ fprintf(stderr, "setgid(%d) failed.\n", newgid);
+ return(-1);
+ }
+
+ if (setuid(newuid) < 0) {
+ fprintf(stderr, "setuid(%d) failed.\n", newuid);
+ return(-1);
+ }
+
+ return 0;
}
diff --git a/src/config_perms.c b/src/config_perms.c
index 4dbeeb0..647e36b 100644
--- a/src/config_perms.c
+++ b/src/config_perms.c
@@ -1,125 +1,135 @@
+/* Asterisk Manager Proxy
+ Copyright (c) 2005-2006 David C. Troy <dave@popvox.com>
+
+ This program is free software, distributed under the terms of
+ the GNU General Public License.
+
+ config_perms.c
+ routines to read and parse the astmanproxy.users file
+*/
+
#include "astmanproxy.h"
extern pthread_mutex_t userslock;
void *free_userperm(struct proxy_user *pu) {
- struct proxy_user *next_pu;
-
- while( pu ) {
- next_pu = pu->next;
- free( pu );
- pu = next_pu;
- }
- return 0;
+ struct proxy_user *next_pu;
+
+ while( pu ) {
+ next_pu = pu->next;
+ free( pu );
+ pu = next_pu;
+ }
+ return 0;
}
void *add_userperm(char* username, char *userspec, struct proxy_user **pu) {
- int ccount = 0;
- struct proxy_user *user;
- char *s;
-
- /* malloc ourselves a server credentials structure */
- user = malloc(sizeof(struct proxy_user));
- if ( !user ) {
- fprintf(stderr, "Failed to allocate user credentials: %s\n", strerror(errno));
- exit(1);
- }
- memset(user, 0, sizeof (struct proxy_user) );
-
- s = userspec;
- strncpy(user->username, username, sizeof(user->username)-1 );
- do {
- if ( *s == ',' ) {
- ccount++;
- continue;
- }
- switch(ccount) {
- case 0:
- strncat(user->secret, s, 1);
- break;
- case 1:
- strncat(user->channel, s, 1);
- break;
- case 2:
- strncat(user->ocontext, s, 1);
- break;
- case 3:
- strncat(user->icontext, s, 1);
- break;
- }
- } while (*(s++));
-
- user->next = *pu;
- *pu = user;
-
- return 0;
+ int ccount = 0;
+ struct proxy_user *user;
+ char *s;
+
+ /* malloc ourselves a server credentials structure */
+ user = malloc(sizeof(struct proxy_user));
+ if ( !user ) {
+ fprintf(stderr, "Failed to allocate user credentials: %s\n", strerror(errno));
+ exit(1);
+ }
+ memset(user, 0, sizeof (struct proxy_user) );
+
+ s = userspec;
+ strncpy(user->username, username, sizeof(user->username)-1 );
+ do {
+ if ( *s == ',' ) {
+ ccount++;
+ continue;
+ }
+ switch(ccount) {
+ case 0:
+ strncat(user->secret, s, 1);
+ break;
+ case 1:
+ strncat(user->channel, s, 1);
+ break;
+ case 2:
+ strncat(user->ocontext, s, 1);
+ break;
+ case 3:
+ strncat(user->icontext, s, 1);
+ break;
+ }
+ } while (*(s++));
+
+ user->next = *pu;
+ *pu = user;
+
+ return 0;
}
void *processperm(char *s, struct proxy_user **pu) {
- char name[80],value[80];
- int nvstate = 0;
+ char name[80],value[80];
+ int nvstate = 0;
- memset (name,0,sizeof name);
- memset (value,0,sizeof value);
+ memset (name,0,sizeof name);
+ memset (value,0,sizeof value);
- do {
- *s = tolower(*s);
+ do {
+ *s = tolower(*s);
- if ( *s == ' ' || *s == '\t')
- continue;
- if ( *s == ';' || *s == '#' || *s == '\r' || *s == '\n' )
- break;
- if ( *s == '=' ) {
- nvstate = 1;
- continue;
- }
- if (!nvstate)
- strncat(name, s, 1);
- else
- strncat(value, s, 1);
- } while (*(s++));
+ if ( *s == ' ' || *s == '\t')
+ continue;
+ if ( *s == ';' || *s == '#' || *s == '\r' || *s == '\n' )
+ break;
+ if ( *s == '=' ) {
+ nvstate = 1;
+ continue;
+ }
+ if (!nvstate)
+ strncat(name, s, 1);
+ else
+ strncat(value, s, 1);
+ } while (*(s++));
- if (debug)
- debugmsg("perm: %s, %s", name, value);
+ if (debug)
+ debugmsg("perm: %s, %s", name, value);
- add_userperm(name,value,pu);
+ add_userperm(name,value,pu);
- return 0;
+ return 0;
}
int ReadPerms() {
- FILE *FP;
- char buf[1024];
- char cfn[80];
- struct proxy_user *pu;
+ FILE *FP;
+ char buf[1024];
+ char cfn[80];
+ struct proxy_user *pu;
- pu=0;
- sprintf(cfn, "%s/%s", PDIR, PFILE);
- FP = fopen( cfn, "r" );
+ pu=0;
+ sprintf(cfn, "%s/%s", PDIR, PFILE);
+ FP = fopen( cfn, "r" );
- if ( !FP )
- {
- fprintf(stderr, "Unable to open permissions file: %s/%s!\n", PDIR, PFILE);
- exit( 1 );
- }
+ if ( !FP )
+ {
+ fprintf(stderr, "Unable to open permissions file: %s/%s!\n", PDIR, PFILE);
+ exit( 1 );
+ }
- if (debug)
- debugmsg("config: parsing configuration file: %s", cfn);
+ if (debug)
+ debugmsg("config: parsing configuration file: %s", cfn);
- while ( fgets( buf, sizeof buf, FP ) ) {
- if (*buf == ';' || *buf == '\r' || *buf == '\n' || *buf == '#') continue;
- processperm(buf,&pu);
- }
+ while ( fgets( buf, sizeof buf, FP ) ) {
+ if (*buf == ';' || *buf == '\r' || *buf == '\n' || *buf == '#') continue;
+ processperm(buf,&pu);
+ }
- fclose(FP);
+ fclose(FP);
- pthread_mutex_lock(&userslock);
- free_userperm(pc.userlist);
- pc.userlist=pu;
- pthread_mutex_unlock(&userslock);
+ pthread_mutex_lock(&userslock);
+ free_userperm(pc.userlist);
+ pc.userlist=pu;
+ pthread_mutex_unlock(&userslock);
- return 0;
+ return 0;
}
diff --git a/src/csv.c b/src/csv.c
index 94d9a00..bcd9a88 100644
--- a/src/csv.c
+++ b/src/csv.c
@@ -1,10 +1,11 @@
-/* Asterisk Manager Proxy
- Copyright (c) 2005 David C. Troy <dave@popvox.com>
+/* Asterisk Manager Proxy
+ Copyright (c) 2005-2006 David C. Troy <dave@popvox.com>
- This program is free software, distributed under the terms of
- the GNU General Public License.
+ This program is free software, distributed under the terms of
+ the GNU General Public License.
- CSV I/O Handler
+ csv.c
+ CSV I/O Handler
*/
#include "astmanproxy.h"
@@ -12,19 +13,19 @@
/* TODO: catch and expand/handle commas in output */
int _write(struct mansession *s, struct message *m) {
- int i;
- char outstring[MAX_LEN];
-
- pthread_mutex_lock(&s->lock);
- for (i=0; i<m->hdrcount; i++) {
- sprintf(outstring, "\"%s\"", m->headers[i]);
- if (i<m->hdrcount-1)
- strcat(outstring, ", ");
- ast_carefulwrite(s->fd, outstring, strlen(outstring), s->writetimeout);
- }
- ast_carefulwrite(s->fd, "\r\n\r\n", 4, s->writetimeout);
- pthread_mutex_unlock(&s->lock);
-
- return 0;
+ int i;
+ char outstring[MAX_LEN];
+
+ pthread_mutex_lock(&s->lock);
+ for (i=0; i<m->hdrcount; i++) {
+ sprintf(outstring, "\"%s\"", m->headers[i]);
+ if (i<m->hdrcount-1)
+ strcat(outstring, ", ");
+ ast_carefulwrite(s->fd, outstring, strlen(outstring), s->writetimeout);
+ }
+ ast_carefulwrite(s->fd, "\r\n\r\n", 4, s->writetimeout);
+ pthread_mutex_unlock(&s->lock);
+
+ return 0;
}
diff --git a/src/http.c b/src/http.c
index a21a7ed..3dc874f 100644
--- a/src/http.c
+++ b/src/http.c
@@ -1,61 +1,62 @@
-/* Asterisk Manager Proxy
- Copyright (c) 2005 David C. Troy <dave@popvox.com>
+/* Asterisk Manager Proxy
+ Copyright (c) 2005-2006 David C. Troy <dave@popvox.com>
- This program is free software, distributed under the terms of
- the GNU General Public License.
+ This program is free software, distributed under the terms of
+ the GNU General Public License.
- HTTP Input Handler
+ http.c
+ HTTP Input Handler
*/
#include "astmanproxy.h"
-// SwapChar: This routine swaps one character for another
+// SwapChar: This routine swaps one character for another
void SwapChar(char *pOriginal, char cBad, char cGood) {
- int i; // generic counter variable
+ int i; // generic counter variable
- // Loop through the input string (cOriginal), character by
- // character, replacing each instance of cBad with cGood
+ // Loop through the input string (cOriginal), character by
+ // character, replacing each instance of cBad with cGood
- i = 0;
- while (pOriginal[i]) {
- if (pOriginal[i] == cBad) pOriginal[i] = cGood;
- i++;
- }
+ i = 0;
+ while (pOriginal[i]) {
+ if (pOriginal[i] == cBad) pOriginal[i] = cGood;
+ i++;
+ }
}
-// IntFromHex: A subroutine to unescape escaped characters.
+// IntFromHex: A subroutine to unescape escaped characters.
static int IntFromHex(char *pChars) {
- int Hi; // holds high byte
- int Lo; // holds low byte
- int Result; // holds result
-
- // Get the value of the first byte to Hi
-
- Hi = pChars[0];
- if ('0' <= Hi && Hi <= '9') {
- Hi -= '0';
- } else
- if ('a' <= Hi && Hi <= 'f') {
- Hi -= ('a'-10);
- } else
- if ('A' <= Hi && Hi <= 'F') {
- Hi -= ('A'-10);
- }
-
- // Get the value of the second byte to Lo
-
- Lo = pChars[1];
- if ('0' <= Lo && Lo <= '9') {
- Lo -= '0';
- } else
- if ('a' <= Lo && Lo <= 'f') {
- Lo -= ('a'-10);
- } else
- if ('A' <= Lo && Lo <= 'F') {
- Lo -= ('A'-10);
- }
- Result = Lo + (16 * Hi);
- return (Result);
+ int Hi; // holds high byte
+ int Lo; // holds low byte
+ int Result; // holds result
+
+ // Get the value of the first byte to Hi
+
+ Hi = pChars[0];
+ if ('0' <= Hi && Hi <= '9') {
+ Hi -= '0';
+ } else
+ if ('a' <= Hi && Hi <= 'f') {
+ Hi -= ('a'-10);
+ } else
+ if ('A' <= Hi && Hi <= 'F') {
+ Hi -= ('A'-10);
+ }
+
+ // Get the value of the second byte to Lo
+
+ Lo = pChars[1];
+ if ('0' <= Lo && Lo <= '9') {
+ Lo -= '0';
+ } else
+ if ('a' <= Lo && Lo <= 'f') {
+ Lo -= ('a'-10);
+ } else
+ if ('A' <= Lo && Lo <= 'F') {
+ Lo -= ('A'-10);
+ }
+ Result = Lo + (16 * Hi);
+ return (Result);
}
// URLDecode: This routine loops through the string pEncoded
@@ -65,173 +66,173 @@ static int IntFromHex(char *pChars) {
// above in this listing, IntFromHex() and SwapChar().
void URLDecode(char *pEncoded) {
- char *pDecoded; // generic pointer
-
- // First, change those pesky plusses to spaces
- SwapChar (pEncoded, '+', ' ');
-
- // Now, loop through looking for escapes
- pDecoded = pEncoded;
- while (*pEncoded) {
- if (*pEncoded=='%') {
- // A percent sign followed by two hex digits means
- // that the digits represent an escaped character. We
- // must decode it.
-
- pEncoded++;
- if (isxdigit(pEncoded[0]) && isxdigit(pEncoded[1])) {
- *pDecoded++ = (char) IntFromHex(pEncoded);
- pEncoded += 2;
- }
- } else {
- *pDecoded ++ = *pEncoded++;
- }
- }
- *pDecoded = '\0';
+ char *pDecoded; // generic pointer
+
+ // First, change those pesky plusses to spaces
+ SwapChar (pEncoded, '+', ' ');
+
+ // Now, loop through looking for escapes
+ pDecoded = pEncoded;
+ while (*pEncoded) {
+ if (*pEncoded=='%') {
+ // A percent sign followed by two hex digits means
+ // that the digits represent an escaped character. We
+ // must decode it.
+
+ pEncoded++;
+ if (isxdigit(pEncoded[0]) && isxdigit(pEncoded[1])) {
+ *pDecoded++ = (char) IntFromHex(pEncoded);
+ pEncoded += 2;
+ }
+ } else {
+ *pDecoded ++ = *pEncoded++;
+ }
+ }
+ *pDecoded = '\0';
}
int ParseHTTPInput(char *buf, struct message *m) {
- char *n, *v;
-
- n = buf;
- while ( (v = strstr(n, "=")) ) {
- v += 1;
- debugmsg("n: %s, v: %s", n, v);
- strncat(m->headers[m->hdrcount], n, v-n-1);
- strcat(m->headers[m->hdrcount], ": ");
-
- if ( (n = strstr(v, "&")) ) {
- n += 1;
- } else {
- n = (v + strlen(v) + 1);
- }
- strncat(m->headers[m->hdrcount], v, n-v-1);
- debugmsg("got hdr: %s", m->headers[m->hdrcount]);
- m->hdrcount++;
- }
-
- return (m->hdrcount > 0);
+ char *n, *v;
+
+ n = buf;
+ while ( (v = strstr(n, "=")) ) {
+ v += 1;
+ debugmsg("n: %s, v: %s", n, v);
+ strncat(m->headers[m->hdrcount], n, v-n-1);
+ strcat(m->headers[m->hdrcount], ": ");
+
+ if ( (n = strstr(v, "&")) ) {
+ n += 1;
+ } else {
+ n = (v + strlen(v) + 1);
+ }
+ strncat(m->headers[m->hdrcount], v, n-v-1);
+ debugmsg("got hdr: %s", m->headers[m->hdrcount]);
+ m->hdrcount++;
+ }
+
+ return (m->hdrcount > 0);
}
int HTTPHeader(struct mansession *s, char *status) {
- time_t t;
- struct tm tm;
- char date[80];
- char ctype[15], hdr[MAX_LEN];
-
- time(&t);
- localtime_r(&t, &tm);
- strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", &tm);
-
- if ( !strcasecmp("xml", s->output->formatname) )
- sprintf(ctype, "text/xml");
- else
- sprintf(ctype, "text/plain");
-
- if (!strcmp("200 OK", status) )
- sprintf(hdr,
- "HTTP/1.1 %s\r\n"
- "Date: %s\r\n"
- "Content-Type: %s\r\n"
- "Connection: close\r\n"
- "Server: %s/%s\r\n\r\n", status,
- date, ctype, PROXY_BANNER, PROXY_VERSION);
- else
- sprintf(hdr,
- "HTTP/1.1 %s\r\n"
- "Date: %s\r\n"
- "Status: %s\r\n"
- "Server: %s/%s\r\n\r\n", status, date, status, PROXY_BANNER, PROXY_VERSION);
-
- pthread_mutex_lock(&s->lock);
- s->inputcomplete = 1;
- ast_carefulwrite(s->fd, hdr, strlen(hdr), s->writetimeout);
- pthread_mutex_unlock(&s->lock);
- debugmsg("http header: %s", hdr);
-
- return 0;
+ time_t t;
+ struct tm tm;
+ char date[80];
+ char ctype[15], hdr[MAX_LEN];
+
+ time(&t);
+ localtime_r(&t, &tm);
+ strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", &tm);
+
+ if ( !strcasecmp("xml", s->output->formatname) )
+ sprintf(ctype, "text/xml");
+ else
+ sprintf(ctype, "text/plain");
+
+ if (!strcmp("200 OK", status) )
+ sprintf(hdr,
+ "HTTP/1.1 %s\r\n"
+ "Date: %s\r\n"
+ "Content-Type: %s\r\n"
+ "Connection: close\r\n"
+ "Server: %s/%s\r\n\r\n", status,
+ date, ctype, PROXY_BANNER, PROXY_VERSION);
+ else
+ sprintf(hdr,
+ "HTTP/1.1 %s\r\n"
+ "Date: %s\r\n"
+ "Status: %s\r\n"
+ "Server: %s/%s\r\n\r\n", status, date, status, PROXY_BANNER, PROXY_VERSION);
+
+ pthread_mutex_lock(&s->lock);
+ s->inputcomplete = 1;
+ ast_carefulwrite(s->fd, hdr, strlen(hdr), s->writetimeout);
+ pthread_mutex_unlock(&s->lock);
+ debugmsg("http header: %s", hdr);
+
+ return 0;
}
int _read(struct mansession *s, struct message *m) {
- /* Note: No single line may be longer than MAX_LEN/s->inbuf, as per get_input */
- /* No HTTP Input may be longer than BUFSIZE */
-
- char line[MAX_LEN], method[10], formdata[MAX_LEN], status[15];
- int res, clength = 0;
-
- memset(method, 0, sizeof method);
- memset(formdata, 0, sizeof formdata);
- memset(status, 0, sizeof status);
-
- /* for http, don't do get_input forever */
- for (;;) {
-
- if (s->inputcomplete && !s->outputcomplete)
- continue;
- else if (s->inputcomplete && s->outputcomplete)
- return -1;
-
- memset(line, 0, sizeof line);
- res = get_input(s, line);
- debugmsg("res=%d, line: %s",res, line);
-
- if (res > 0) {
- debugmsg("Got http: %s", line);
-
- if ( !clength && !strncasecmp(line, "Content-Length: ", 16) )
- clength = atoi(line+16);
-
- if (!*method) {
- if ( !strncmp(line,"POST",4) ) {
- strncpy(method, line, 4);
- } else if ( !strncmp(line,"GET",3)) {
- if ( strlen(line) > 14 ) {
- /* GET / HTTP/1.1 ---- this is bad */
- /* GET /?Action=Ping&ActionID=Foo HTTP/1.1 */
- strncpy(method, line, 3);
- memcpy(formdata, line+6, strstr(line, " HTTP")-line-6);
- sprintf(status, "200 OK");
- } else
- sprintf(status, "501 Not Implemented");
- }
+ /* Note: No single line may be longer than MAX_LEN/s->inbuf, as per get_input */
+ /* No HTTP Input may be longer than BUFSIZE */
+
+ char line[MAX_LEN], method[10], formdata[MAX_LEN], status[15];
+ int res, clength = 0;
+
+ memset(method, 0, sizeof method);
+ memset(formdata, 0, sizeof formdata);
+ memset(status, 0, sizeof status);
+
+ /* for http, don't do get_input forever */
+ for (;;) {
+
+ if (s->inputcomplete && !s->outputcomplete)
+ continue;
+ else if (s->inputcomplete && s->outputcomplete)
+ return -1;
+
+ memset(line, 0, sizeof line);
+ res = get_input(s, line);
+ debugmsg("res=%d, line: %s",res, line);
+
+ if (res > 0) {
+ debugmsg("Got http: %s", line);
+
+ if ( !clength && !strncasecmp(line, "Content-Length: ", 16) )
+ clength = atoi(line+16);
+
+ if (!*method) {
+ if ( !strncmp(line,"POST",4) ) {
+ strncpy(method, line, 4);
+ } else if ( !strncmp(line,"GET",3)) {
+ if ( strlen(line) > 14 ) {
+ /* GET / HTTP/1.1 ---- this is bad */
+ /* GET /?Action=Ping&ActionID=Foo HTTP/1.1 */
+ strncpy(method, line, 3);
+ memcpy(formdata, line+6, strstr(line, " HTTP")-line-6);
+ sprintf(status, "200 OK");
+ } else
+ sprintf(status, "501 Not Implemented");
+ }
+ }
+ } else if (res == 0) {
+ /* x-www-form-urlencoded handler */
+ /* Content-Type: application/x-www-form-urlencoded */
+ if (*method && !*formdata) {
+ if ( !strcasecmp(method, "POST") && clength && s->inlen==clength) {
+ pthread_mutex_lock(&s->lock);
+ strncpy(formdata, s->inbuf, clength);
+ s->inlen = 0;
+ pthread_mutex_unlock(&s->lock);
+ sprintf(status, "200 OK");
+ }
+ }
}
- } else if (res == 0) {
- /* x-www-form-urlencoded handler */
- /* Content-Type: application/x-www-form-urlencoded */
- if (*method && !*formdata) {
- if ( !strcasecmp(method, "POST") && clength && s->inlen==clength) {
- pthread_mutex_lock(&s->lock);
- strncpy(formdata, s->inbuf, clength);
- s->inlen = 0;
- pthread_mutex_unlock(&s->lock);
- sprintf(status, "200 OK");
- }
- }
- }
-
- if (res < 0)
- break;
-
- if (*status) {
- HTTPHeader(s, status);
-
- /* now, let's transform and copy into a standard message block */
- if (!strcmp("200 OK", status) ) {
- URLDecode(formdata);
- res = ParseHTTPInput(formdata, m);
- return res;
- } else {
- pthread_mutex_lock(&s->lock);
- s->outputcomplete = 1;
- pthread_mutex_unlock(&s->lock);
- return 0;
+
+ if (res < 0)
+ break;
+
+ if (*status) {
+ HTTPHeader(s, status);
+
+ /* now, let's transform and copy into a standard message block */
+ if (!strcmp("200 OK", status) ) {
+ URLDecode(formdata);
+ res = ParseHTTPInput(formdata, m);
+ return res;
+ } else {
+ pthread_mutex_lock(&s->lock);
+ s->outputcomplete = 1;
+ pthread_mutex_unlock(&s->lock);
+ return 0;
+ }
}
}
- }
- return -1;
+ return -1;
}
/* We do not define a _write or _onconnect method */
diff --git a/src/include/astmanproxy.h b/src/include/astmanproxy.h
index 9d8ed89..b7d1629 100644
--- a/src/include/astmanproxy.h
+++ b/src/include/astmanproxy.h
@@ -19,101 +19,101 @@
#include <errno.h>
#include <dlfcn.h>
#ifdef __APPLE__
- #include "poll-compat.h"
+ #include "poll-compat.h"
#else
- #include <sys/poll.h>
+ #include <sys/poll.h>
#endif
-#define BUFSIZE 1024
-#define MAX_HEADERS 256
-#define MAX_LEN 1024
+#define BUFSIZE 1024
+#define MAX_HEADERS 256
+#define MAX_LEN 1024
-#define PROXY_BANNER "Asterisk Call Manager Proxy"
+#define PROXY_BANNER "Asterisk Call Manager Proxy"
#define PROXY_SHUTDOWN "ProxyMessage: Proxy Shutting Down"
-#define ACTION_ID "ActionID"
+#define ACTION_ID "ActionID"
struct ast_server {
- char nickname[80];
- char ast_host[40];
- char ast_port[10];
- char ast_user[80];
- char ast_pass[80];
- char ast_events[10];
- int use_ssl; /* Use SSL when Connecting to Server? */
- int status; /* TODO: have this mean something */
- struct ast_server *next;
+ char nickname[80];
+ char ast_host[40];
+ char ast_port[10];
+ char ast_user[80];
+ char ast_pass[80];
+ char ast_events[10];
+ int use_ssl; /* Use SSL when Connecting to Server? */
+ int status; /* TODO: have this mean something */
+ struct ast_server *next;
};
struct proxy_user {
- char username[80];
- char secret[80];
- char channel[80];
- char icontext[80];
- char ocontext[80];
- struct proxy_user *next;
+ char username[80];
+ char secret[80];
+ char channel[80];
+ char icontext[80];
+ char ocontext[80];
+ struct proxy_user *next;
};
struct proxyconfig {
- struct ast_server *serverlist;
- struct proxy_user *userlist;
- char listen_addr[INET_ADDRSTRLEN];
- int listen_port;
- char inputformat[80];
- char outputformat[80];
- int autofilter; /* enable autofiltering? */
- int authrequired; /* is authentication required? */
- char key[80];
- char proc_user[40];
- char proc_group[40];
- char logfile[256];
- int retryinterval;
- int maxretries;
- int asteriskwritetimeout; /* ms to wait when writing to asteriskfor ast_carefulwrite */
- int clientwritetimeout; /* ms to wait when writing to client ast_carefulwrite */
- int sslclhellotimeout; /* ssl client hello timeout -- how long to wait before assuming not ssl */
- int acceptencryptedconnection; /* accept encrypted connections? */
- int acceptunencryptedconnection; /* accept unencrypted connections? */
- char certfile[256]; /* our SERVER-side SSL certificate file */
+ struct ast_server *serverlist;
+ struct proxy_user *userlist;
+ char listen_addr[INET_ADDRSTRLEN];
+ int listen_port;
+ char inputformat[80];
+ char outputformat[80];
+ int autofilter; /* enable autofiltering? */
+ int authrequired; /* is authentication required? */
+ char key[80];
+ char proc_user[40];
+ char proc_group[40];
+ char logfile[256];
+ int retryinterval;
+ int maxretries;
+ int asteriskwritetimeout; /* ms to wait when writing to asteriskfor ast_carefulwrite */
+ int clientwritetimeout; /* ms to wait when writing to client ast_carefulwrite */
+ int sslclhellotimeout; /* ssl client hello timeout -- how long to wait before assuming not ssl */
+ int acceptencryptedconnection; /* accept encrypted connections? */
+ int acceptunencryptedconnection; /* accept unencrypted connections? */
+ char certfile[256]; /* our SERVER-side SSL certificate file */
};
struct iohandler {
- int (*read) ();
- int (*write) ();
- int (*onconnect) ();
- char formatname[80];
- void *dlhandle;
- struct iohandler *next;
+ int (*read) ();
+ int (*write) ();
+ int (*onconnect) ();
+ char formatname[80];
+ void *dlhandle;
+ struct iohandler *next;
};
struct mansession {
- pthread_t t;
- pthread_mutex_t lock;
- struct sockaddr_in sin;
- int fd;
- char inbuf[MAX_LEN];
- int inlen;
- struct iohandler *input;
- struct iohandler *output;
- int autofilter;
- int authenticated;
- int connected;
- int dead; /* Whether we are dead */
- int busy; /* Whether we are busy */
- int inputcomplete; /* Whether we want any more input from this session (http) */
- int outputcomplete; /* Whether output to this session is done (http) */
- struct ast_server *server;
- struct proxy_user user;
- char actionid[MAX_LEN];
- char challenge[10]; /*! Authentication challenge */
- int writetimeout; /* Timeout for ast_carefulwrite() */
- struct mansession *next;
+ pthread_t t;
+ pthread_mutex_t lock;
+ struct sockaddr_in sin;
+ int fd;
+ char inbuf[MAX_LEN];
+ int inlen;
+ struct iohandler *input;
+ struct iohandler *output;
+ int autofilter;
+ int authenticated;
+ int connected;
+ int dead; /* Whether we are dead */
+ int busy; /* Whether we are busy */
+ int inputcomplete; /* Whether we want any more input from this session (http) */
+ int outputcomplete; /* Whether output to this session is done (http) */
+ struct ast_server *server;
+ struct proxy_user user;
+ char actionid[MAX_LEN];
+ char challenge[10]; /*! Authentication challenge */
+ int writetimeout; /* Timeout for ast_carefulwrite() */
+ struct mansession *next;
};
struct message {
- int hdrcount;
- char headers[MAX_HEADERS][MAX_LEN];
- int in_command;
- struct mansession *session;
+ int hdrcount;
+ char headers[MAX_HEADERS][MAX_LEN];
+ int in_command;
+ struct mansession *session;
};
struct proxyconfig pc;
diff --git a/src/log.c b/src/log.c
index d3f8d15..fc86643 100644
--- a/src/log.c
+++ b/src/log.c
@@ -1,6 +1,16 @@
+/* Asterisk Manager Proxy
+ Copyright (c) 2005-2006 David C. Troy <dave@popvox.com>
+
+ This program is free software, distributed under the terms of
+ the GNU General Public License.
+
+ log.c
+ Log & debug routines
+*/
+
#include "astmanproxy.h"
-#define DATEFORMAT "%b %e %T"
+#define DATEFORMAT "%b %e %T"
extern FILE *proxylog;
extern int debug;
@@ -9,49 +19,49 @@ extern pthread_mutex_t debuglock;
void debugmsg (const char *fmt, ...)
{
- va_list ap;
-
- time_t t;
- struct tm tm;
- char date[80];
-
- if (!debug)
- return;
-
- time(&t);
- localtime_r(&t, &tm);
- strftime(date, sizeof(date), DATEFORMAT, &tm);
-
- pthread_mutex_lock(&debuglock);
- va_start(ap, fmt);
- printf("%s: ", date);
- vprintf(fmt, ap);
- printf("\n");
- va_end(ap);
- pthread_mutex_unlock(&debuglock);
+ va_list ap;
+
+ time_t t;
+ struct tm tm;
+ char date[80];
+
+ if (!debug)
+ return;
+
+ time(&t);
+ localtime_r(&t, &tm);
+ strftime(date, sizeof(date), DATEFORMAT, &tm);
+
+ pthread_mutex_lock(&debuglock);
+ va_start(ap, fmt);
+ printf("%s: ", date);
+ vprintf(fmt, ap);
+ printf("\n");
+ va_end(ap);
+ pthread_mutex_unlock(&debuglock);
}
void logmsg (const char *fmt, ...)
{
- va_list ap;
-
- time_t t;
- struct tm tm;
- char date[80];
-
- time(&t);
- localtime_r(&t, &tm);
- strftime(date, sizeof(date), DATEFORMAT, &tm);
-
- if (proxylog) {
- pthread_mutex_lock(&loglock);
- va_start(ap, fmt);
- fprintf(proxylog, "%s: ", date);
- vfprintf(proxylog, fmt, ap);
- fprintf(proxylog, "\n");
- va_end(ap);
- fflush(proxylog);
- pthread_mutex_unlock(&loglock);
- }
+ va_list ap;
+
+ time_t t;
+ struct tm tm;
+ char date[80];
+
+ time(&t);
+ localtime_r(&t, &tm);
+ strftime(date, sizeof(date), DATEFORMAT, &tm);
+
+ if (proxylog) {
+ pthread_mutex_lock(&loglock);
+ va_start(ap, fmt);
+ fprintf(proxylog, "%s: ", date);
+ vfprintf(proxylog, fmt, ap);
+ fprintf(proxylog, "\n");
+ va_end(ap);
+ fflush(proxylog);
+ pthread_mutex_unlock(&loglock);
+ }
}
diff --git a/src/poll.c b/src/poll.c
index a36539a..4e7cda3 100644
--- a/src/poll.c
+++ b/src/poll.c
@@ -72,12 +72,12 @@
\*---------------------------------------------------------------------------*/
#include <unistd.h> /* standard Unix definitions */
-#include <sys/types.h> /* system types */
-#include <sys/time.h> /* time definitions */
-#include <assert.h> /* assertion macros */
-#include <string.h> /* string functions */
+#include <sys/types.h> /* system types */
+#include <sys/time.h> /* time definitions */
+#include <assert.h> /* assertion macros */
+#include <string.h> /* string functions */
-#include "poll-compat.h" /* this package */
+#include "poll-compat.h" /* this package */
/*---------------------------------------------------------------------------*\
Macros
@@ -96,21 +96,21 @@ static int map_poll_spec
#if __STDC__ > 0
(struct pollfd *pArray,
unsigned long n_fds,
- fd_set *pReadSet,
- fd_set *pWriteSet,
- fd_set *pExceptSet)
+ fd_set *pReadSet,
+ fd_set *pWriteSet,
+ fd_set *pExceptSet)
#else
(pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
struct pollfd *pArray;
unsigned long n_fds;
- fd_set *pReadSet;
- fd_set *pWriteSet;
- fd_set *pExceptSet;
+ fd_set *pReadSet;
+ fd_set *pWriteSet;
+ fd_set *pExceptSet;
#endif
{
- register unsigned long i; /* loop control */
- register struct pollfd *pCur; /* current array element */
- register int max_fd = -1; /* return value */
+ register unsigned long i; /* loop control */
+ register struct pollfd *pCur; /* current array element */
+ register int max_fd = -1; /* return value */
/*
Map the poll() structures into the file descriptor sets required
@@ -118,10 +118,10 @@ static int map_poll_spec
*/
for (i = 0, pCur = pArray; i < n_fds; i++, pCur++)
{
- /* Skip any bad FDs in the array. */
+ /* Skip any bad FDs in the array. */
- if (pCur->fd < 0)
- continue;
+ if (pCur->fd < 0)
+ continue;
if (pCur->events & POLLIN)
{
@@ -155,7 +155,7 @@ static struct timeval *map_timeout
(int poll_timeout, struct timeval *pSelTimeout)
#else
(poll_timeout, pSelTimeout)
- int poll_timeout;
+ int poll_timeout;
struct timeval *pSelTimeout;
#endif
{
@@ -168,7 +168,7 @@ static struct timeval *map_timeout
VALUE MEANING
-1 wait indefinitely (until signal occurs)
- 0 return immediately, don't block
+ 0 return immediately, don't block
>0 wait specified number of milliseconds
select() uses a "struct timeval", which specifies the timeout in
@@ -200,7 +200,7 @@ static struct timeval *map_timeout
default:
/* Wait the specified number of milliseconds. */
pSelTimeout->tv_sec = poll_timeout / 1000; /* get seconds */
- poll_timeout %= 1000; /* remove seconds */
+ poll_timeout %= 1000; /* remove seconds */
pSelTimeout->tv_usec = poll_timeout * 1000; /* get microseconds */
pResult = pSelTimeout;
break;
@@ -214,27 +214,27 @@ static void map_select_results
#if __STDC__ > 0
(struct pollfd *pArray,
unsigned long n_fds,
- fd_set *pReadSet,
- fd_set *pWriteSet,
- fd_set *pExceptSet)
+ fd_set *pReadSet,
+ fd_set *pWriteSet,
+ fd_set *pExceptSet)
#else
(pArray, n_fds, pReadSet, pWriteSet, pExceptSet)
struct pollfd *pArray;
unsigned long n_fds;
- fd_set *pReadSet;
- fd_set *pWriteSet;
- fd_set *pExceptSet;
+ fd_set *pReadSet;
+ fd_set *pWriteSet;
+ fd_set *pExceptSet;
#endif
{
- register unsigned long i; /* loop control */
- register struct pollfd *pCur; /* current array element */
+ register unsigned long i; /* loop control */
+ register struct pollfd *pCur; /* current array element */
for (i = 0, pCur = pArray; i < n_fds; i++, pCur++)
{
- /* Skip any bad FDs in the array. */
+ /* Skip any bad FDs in the array. */
- if (pCur->fd < 0)
- continue;
+ if (pCur->fd < 0)
+ continue;
/* Exception events take priority over input events. */
@@ -268,13 +268,13 @@ int poll
#endif
{
- fd_set read_descs; /* input file descs */
- fd_set write_descs; /* output file descs */
- fd_set except_descs; /* exception descs */
- struct timeval stime; /* select() timeout value */
- int ready_descriptors; /* function result */
- int max_fd; /* maximum fd value */
- struct timeval *pTimeout; /* actually passed */
+ fd_set read_descs; /* input file descs */
+ fd_set write_descs; /* output file descs */
+ fd_set except_descs; /* exception descs */
+ struct timeval stime; /* select() timeout value */
+ int ready_descriptors; /* function result */
+ int max_fd; /* maximum fd value */
+ struct timeval *pTimeout; /* actually passed */
FD_ZERO (&read_descs);
FD_ZERO (&write_descs);
diff --git a/src/proxyfunc.c b/src/proxyfunc.c
index 434baff..484da78 100644
--- a/src/proxyfunc.c
+++ b/src/proxyfunc.c
@@ -1,3 +1,13 @@
+/* Asterisk Manager Proxy
+ Copyright (c) 2005-2006 David C. Troy <dave@popvox.com>
+
+ This program is free software, distributed under the terms of
+ the GNU General Public License.
+
+ proxyfunc.c
+ Functions specific to the manager proxy, not found in standard Asterisk AMI
+*/
+
#include "astmanproxy.h"
#include "md5.h"
@@ -7,384 +17,382 @@ extern pthread_mutex_t serverlock;
extern pthread_mutex_t userslock;
void *ProxyListIOHandlers(struct mansession *s) {
- struct message m;
- struct iohandler *i;
-
- memset(&m, 0, sizeof(struct message));
- AddHeader(&m, "ProxyResponse: Success");
-
- i = iohandlers;
- while (i && (m.hdrcount < MAX_HEADERS - 1) ) {
- if (i->read)
- AddHeader(&m, "InputHandler: %s", i->formatname);
- if (i->write)
- AddHeader(&m, "OutputHandler: %s", i->formatname);
- i = i->next;
- }
-
- s->output->write(s, &m);
- return 0;
+ struct message m;
+ struct iohandler *i;
+
+ memset(&m, 0, sizeof(struct message));
+ AddHeader(&m, "ProxyResponse: Success");
+
+ i = iohandlers;
+ while (i && (m.hdrcount < MAX_HEADERS - 1) ) {
+ if (i->read)
+ AddHeader(&m, "InputHandler: %s", i->formatname);
+ if (i->write)
+ AddHeader(&m, "OutputHandler: %s", i->formatname);
+ i = i->next;
+ }
+
+ s->output->write(s, &m);
+ return 0;
}
void *ProxyListSessions(struct mansession *s) {
- struct message m;
- struct mansession *c;
- char iabuf[INET_ADDRSTRLEN];
-
- memset(&m, 0, sizeof(struct message));
- AddHeader(&m, "ProxyResponse: Success");
-
- c = sessions;
- while (c && (m.hdrcount < MAX_HEADERS - 1) ) {
- if (!c->server) {
- AddHeader(&m, "ProxyClientSession: %s", ast_inet_ntoa(iabuf, sizeof(iabuf), c->sin.sin_addr), c->actionid);
- AddHeader(&m, "ProxyClientInputHandler: %s", c->input->formatname);
- AddHeader(&m, "ProxyClientOutputHandler: %s", c->output->formatname);
- } else
- AddHeader(&m, "ProxyServerSession: %s", ast_inet_ntoa(iabuf, sizeof(iabuf), c->sin.sin_addr));
- c = c->next;
- }
- s->output->write(s, &m);
- return 0;
+ struct message m;
+ struct mansession *c;
+ char iabuf[INET_ADDRSTRLEN];
+
+ memset(&m, 0, sizeof(struct message));
+ AddHeader(&m, "ProxyResponse: Success");
+
+ c = sessions;
+ while (c && (m.hdrcount < MAX_HEADERS - 1) ) {
+ if (!c->server) {
+ AddHeader(&m, "ProxyClientSession: %s", ast_inet_ntoa(iabuf, sizeof(iabuf), c->sin.sin_addr), c->actionid);
+ AddHeader(&m, "ProxyClientInputHandler: %s", c->input->formatname);
+ AddHeader(&m, "ProxyClientOutputHandler: %s", c->output->formatname);
+ } else
+ AddHeader(&m, "ProxyServerSession: %s", ast_inet_ntoa(iabuf, sizeof(iabuf), c->sin.sin_addr));
+ c = c->next;
+ }
+ s->output->write(s, &m);
+ return 0;
}
void *ProxySetOutputFormat(struct mansession *s, struct message *m) {
- struct message mo;
- char *value;
+ struct message mo;
+ char *value;
- value = astman_get_header(m, "OutputFormat");
- SetIOHandlers(s, s->input->formatname, value);
+ value = astman_get_header(m, "OutputFormat");
+ SetIOHandlers(s, s->input->formatname, value);
- memset(&mo, 0, sizeof(struct message));
- AddHeader(&mo, "ProxyResponse: Success");
- AddHeader(&mo, "OutputFormat: %s", s->output->formatname );
+ memset(&mo, 0, sizeof(struct message));
+ AddHeader(&mo, "ProxyResponse: Success");
+ AddHeader(&mo, "OutputFormat: %s", s->output->formatname );
- s->output->write(s, &mo);
+ s->output->write(s, &mo);
- return 0;
+ return 0;
}
int ProxyChallenge(struct mansession *s, struct message *m) {
- struct message mo;
+ struct message mo;
- if ( strcasecmp("MD5", astman_get_header(m, "AuthType")) ) {
- SendError(s, "Must specify AuthType");
- return 1;
- }
+ if ( strcasecmp("MD5", astman_get_header(m, "AuthType")) ) {
+ SendError(s, "Must specify AuthType");
+ return 1;
+ }
- if (!*s->challenge)
- snprintf(s->challenge, sizeof(s->challenge), "%d", rand());
+ if (!*s->challenge)
+ snprintf(s->challenge, sizeof(s->challenge), "%d", rand());
- memset(&mo, 0, sizeof(struct message));
- AddHeader(&mo, "Response: Success");
- AddHeader(&mo, "Challenge: %s", s->challenge);
+ memset(&mo, 0, sizeof(struct message));
+ AddHeader(&mo, "Response: Success");
+ AddHeader(&mo, "Challenge: %s", s->challenge);
- s->output->write(s, &mo);
- return 0;
+ s->output->write(s, &mo);
+ return 0;
}
void *ProxySetAutoFilter(struct mansession *s, struct message *m) {
- struct message mo;
- char *value;
- int i;
-
- value = astman_get_header(m, "AutoFilter");
- if ( !strcasecmp(value, "on") )
- i = 1;
- else
- i = 0;
- pthread_mutex_lock(&s->lock);
- s->autofilter = i;
- pthread_mutex_unlock(&s->lock);
-
- memset(&mo, 0, sizeof(struct message));
- AddHeader(&mo, "ProxyResponse: Success");
- AddHeader(&mo, "AutoFilter: %d", s->autofilter);
-
- s->output->write(s, &mo);
-
- return 0;
+ struct message mo;
+ char *value;
+ int i;
+
+ value = astman_get_header(m, "AutoFilter");
+ if ( !strcasecmp(value, "on") )
+ i = 1;
+ else
+ i = 0;
+ pthread_mutex_lock(&s->lock);
+ s->autofilter = i;
+ pthread_mutex_unlock(&s->lock);
+
+ memset(&mo, 0, sizeof(struct message));
+ AddHeader(&mo, "ProxyResponse: Success");
+ AddHeader(&mo, "AutoFilter: %d", s->autofilter);
+
+ s->output->write(s, &mo);
+
+ return 0;
}
int AuthMD5(char *key, char *challenge, char *password) {
- int x;
- int len=0;
- char md5key[256] = "";
- struct MD5Context md5;
- unsigned char digest[16];
+ int x;
+ int len=0;
+ char md5key[256] = "";
+ struct MD5Context md5;
+ unsigned char digest[16];
- if (!*key || !*challenge || !*password )
+ if (!*key || !*challenge || !*password )
return 1;
- if (debug)
- debugmsg("MD5 password=%s, challenge=%s", password, challenge);
-
- MD5Init(&md5);
- MD5Update(&md5, (unsigned char *) challenge, strlen(challenge));
- MD5Update(&md5, (unsigned char *) password, strlen(password));
- MD5Final(digest, &md5);
- for (x=0;x<16;x++)
- len += sprintf(md5key + len, "%2.2x", digest[x]);
- if( debug ) {
- debugmsg("MD5 computed=%s, received=%s", md5key, key);
- }
- if (!strcmp(md5key, key))
+ if (debug)
+ debugmsg("MD5 password=%s, challenge=%s", password, challenge);
+
+ MD5Init(&md5);
+ MD5Update(&md5, (unsigned char *) challenge, strlen(challenge));
+ MD5Update(&md5, (unsigned char *) password, strlen(password));
+ MD5Final(digest, &md5);
+ for (x=0;x<16;x++)
+ len += sprintf(md5key + len, "%2.2x", digest[x]);
+ if( debug ) {
+ debugmsg("MD5 computed=%s, received=%s", md5key, key);
+ }
+ if (!strcmp(md5key, key))
return 0;
- else
+ else
return 1;
}
void *ProxyLogin(struct mansession *s, struct message *m) {
- struct message mo;
- struct proxy_user *pu;
- char *user, *secret, *key;
+ struct message mo;
+ struct proxy_user *pu;
+ char *user, *secret, *key;
- user = astman_get_header(m, "Username");
- secret = astman_get_header(m, "Secret");
- key = astman_get_header(m, "Key");
+ user = astman_get_header(m, "Username");
+ secret = astman_get_header(m, "Secret");
+ key = astman_get_header(m, "Key");
- memset(&mo, 0, sizeof(struct message));
- if( debug )
- debugmsg("Login attempt as: %s/%s", user, secret);
+ memset(&mo, 0, sizeof(struct message));
+ if( debug )
+ debugmsg("Login attempt as: %s/%s", user, secret);
- pthread_mutex_lock(&userslock);
- pu = pc.userlist;
- while( pu ) {
+ pthread_mutex_lock(&userslock);
+ pu = pc.userlist;
+ while( pu ) {
if ( !strcmp(user, pu->username) ) {
- if (!AuthMD5(key, s->challenge, pu->secret) ||
- !strcmp(secret, pu->secret) ) {
- AddHeader(&mo, "Response: Success");
- AddHeader(&mo, "Message: Authentication accepted");
- s->output->write(s, &mo);
- pthread_mutex_lock(&s->lock);
- s->authenticated = 1;
- strcpy(s->user.channel, pu->channel);
- strcpy(s->user.icontext, pu->icontext);
- strcpy(s->user.ocontext, pu->ocontext);
- pthread_mutex_unlock(&s->lock);
- if( debug )
- debugmsg("Login as: %s", user);
- break;
- }
- }
- pu = pu->next;
- }
- pthread_mutex_unlock(&userslock);
-
- if( !pu ) {
- SendError(s, "Authentication failed");
- pthread_mutex_lock(&s->lock);
- s->authenticated = 0;
- pthread_mutex_unlock(&s->lock);
- if( debug )
- debugmsg("Login failed as: %s/%s", user, secret);
- }
-
-
- return 0;
+ if (!AuthMD5(key, s->challenge, pu->secret) || !strcmp(secret, pu->secret) ) {
+ AddHeader(&mo, "Response: Success");
+ AddHeader(&mo, "Message: Authentication accepted");
+ s->output->write(s, &mo);
+ pthread_mutex_lock(&s->lock);
+ s->authenticated = 1;
+ strcpy(s->user.channel, pu->channel);
+ strcpy(s->user.icontext, pu->icontext);
+ strcpy(s->user.ocontext, pu->ocontext);
+ pthread_mutex_unlock(&s->lock);
+ if( debug )
+ debugmsg("Login as: %s", user);
+ break;
+ }
+ }
+ pu = pu->next;
+ }
+ pthread_mutex_unlock(&userslock);
+
+ if( !pu ) {
+ SendError(s, "Authentication failed");
+ pthread_mutex_lock(&s->lock);
+ s->authenticated = 0;
+ pthread_mutex_unlock(&s->lock);
+ if( debug )
+ debugmsg("Login failed as: %s/%s", user, secret);
+ }
+
+ return 0;
}
void *ProxyLogoff(struct mansession *s) {
- struct message m;
+ struct message m;
- memset(&m, 0, sizeof(struct message));
- AddHeader(&m, "Goodbye: Y'all come back now, y'hear?");
+ memset(&m, 0, sizeof(struct message));
+ AddHeader(&m, "Goodbye: Y'all come back now, y'hear?");
- s->output->write(s, &m);
+ s->output->write(s, &m);
- destroy_session(s);
- if (debug)
- debugmsg("Client logged off - exiting thread");
- pthread_exit(NULL);
- return 0;
+ destroy_session(s);
+ if (debug)
+ debugmsg("Client logged off - exiting thread");
+ pthread_exit(NULL);
+ return 0;
}
int ProxyAddServer(struct mansession *s, struct message *m) {
- struct message mo;
- struct ast_server *srv;
- int res = 0;
-
- /* malloc ourselves a server credentials structure */
- srv = malloc(sizeof(struct ast_server));
- if ( !srv ) {
- fprintf(stderr, "Failed to allocate server credentials: %s\n", strerror(errno));
- exit(1);
- }
-
- memset(srv, 0, sizeof(struct ast_server) );
- memset(&mo, 0, sizeof(struct message));
- strcpy(srv->ast_host, astman_get_header(m, "Server"));
- strcpy(srv->ast_user, astman_get_header(m, "Username"));
- strcpy(srv->ast_pass, astman_get_header(m, "Secret"));
- strcpy(srv->ast_port, astman_get_header(m, "Port"));
- strcpy(srv->ast_events, astman_get_header(m, "Events"));
-
- if (*srv->ast_host && *srv->ast_user && *srv->ast_pass && *srv->ast_port && *srv->ast_events) {
- pthread_mutex_lock(&serverlock);
- srv->next = pc.serverlist;
- pc.serverlist = srv;
- pthread_mutex_unlock(&serverlock);
- res = StartServer(srv);
- } else
- res = 1;
-
- if (res) {
- AddHeader(&mo, "ProxyResponse: Failure");
- AddHeader(&mo, "Message: Could not add %s", srv->ast_host);
- } else {
- AddHeader(&mo, "ProxyResponse: Success");
- AddHeader(&mo, "Message: Added %s", srv->ast_host);
- }
-
- s->output->write(s, &mo);
- return 0;
+ struct message mo;
+ struct ast_server *srv;
+ int res = 0;
+
+ /* malloc ourselves a server credentials structure */
+ srv = malloc(sizeof(struct ast_server));
+ if ( !srv ) {
+ fprintf(stderr, "Failed to allocate server credentials: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ memset(srv, 0, sizeof(struct ast_server) );
+ memset(&mo, 0, sizeof(struct message));
+ strcpy(srv->ast_host, astman_get_header(m, "Server"));
+ strcpy(srv->ast_user, astman_get_header(m, "Username"));
+ strcpy(srv->ast_pass, astman_get_header(m, "Secret"));
+ strcpy(srv->ast_port, astman_get_header(m, "Port"));
+ strcpy(srv->ast_events, astman_get_header(m, "Events"));
+
+ if (*srv->ast_host && *srv->ast_user && *srv->ast_pass && *srv->ast_port && *srv->ast_events) {
+ pthread_mutex_lock(&serverlock);
+ srv->next = pc.serverlist;
+ pc.serverlist = srv;
+ pthread_mutex_unlock(&serverlock);
+ res = StartServer(srv);
+ } else
+ res = 1;
+
+ if (res) {
+ AddHeader(&mo, "ProxyResponse: Failure");
+ AddHeader(&mo, "Message: Could not add %s", srv->ast_host);
+ } else {
+ AddHeader(&mo, "ProxyResponse: Success");
+ AddHeader(&mo, "Message: Added %s", srv->ast_host);
+ }
+
+ s->output->write(s, &mo);
+ return 0;
}
int ProxyDropServer(struct mansession *s, struct message *m) {
- struct message mo;
- struct mansession *srv;
- char *value;
- int res;
-
- memset(&mo, 0, sizeof(struct message));
- value = astman_get_header(m, "Server");
- srv = sessions;
- while (*value && srv) {
- if (srv->server && !strcmp(srv->server->ast_host, value))
- break;
- srv = srv->next;
- }
-
- if (srv) {
- destroy_session(srv);
- debugmsg("Dropping Server %s", value);
- AddHeader(&mo, "ProxyResponse: Success");
- AddHeader(&mo, "Message: Dropped %s", value);
- res = 0;
- } else {
- debugmsg("Failed to Drop Server %s -- not found", value);
- AddHeader(&mo, "ProxyResponse: Failure");
- AddHeader(&mo, "Message: Cannot Drop Server %s, Does Not Exist", value);
- res = 1;
- }
-
- s->output->write(s, &mo);
- return res;
+ struct message mo;
+ struct mansession *srv;
+ char *value;
+ int res;
+
+ memset(&mo, 0, sizeof(struct message));
+ value = astman_get_header(m, "Server");
+ srv = sessions;
+ while (*value && srv) {
+ if (srv->server && !strcmp(srv->server->ast_host, value))
+ break;
+ srv = srv->next;
+ }
+
+ if (srv) {
+ destroy_session(srv);
+ debugmsg("Dropping Server %s", value);
+ AddHeader(&mo, "ProxyResponse: Success");
+ AddHeader(&mo, "Message: Dropped %s", value);
+ res = 0;
+ } else {
+ debugmsg("Failed to Drop Server %s -- not found", value);
+ AddHeader(&mo, "ProxyResponse: Failure");
+ AddHeader(&mo, "Message: Cannot Drop Server %s, Does Not Exist", value);
+ res = 1;
+ }
+
+ s->output->write(s, &mo);
+ return res;
}
void *ProxyListServers(struct mansession *s) {
- struct message m;
- struct mansession *c;
- char iabuf[INET_ADDRSTRLEN];
-
- memset(&m, 0, sizeof(struct message));
- AddHeader(&m, "ProxyResponse: Success");
-
- c = sessions;
- while (c) {
- if (c->server) {
- AddHeader(&m, "ProxyListServer I: %s H: %s U: %s P: %s E: %s ",
- ast_inet_ntoa(iabuf, sizeof(iabuf), c->sin.sin_addr),
- c->server->ast_host, c->server->ast_user,
- c->server->ast_port, c->server->ast_events);
- }
-
- c = c->next;
- }
- s->output->write(s, &m);
- return 0;
+ struct message m;
+ struct mansession *c;
+ char iabuf[INET_ADDRSTRLEN];
+
+ memset(&m, 0, sizeof(struct message));
+ AddHeader(&m, "ProxyResponse: Success");
+
+ c = sessions;
+ while (c) {
+ if (c->server) {
+ AddHeader(&m, "ProxyListServer I: %s H: %s U: %s P: %s E: %s ",
+ ast_inet_ntoa(iabuf, sizeof(iabuf), c->sin.sin_addr),
+ c->server->ast_host, c->server->ast_user,
+ c->server->ast_port, c->server->ast_events);
+ }
+
+ c = c->next;
+ }
+ s->output->write(s, &m);
+ return 0;
}
void *proxyaction_do(char *proxyaction, struct message *m, struct mansession *s)
{
- if (!strcasecmp(proxyaction,"SetOutputFormat"))
- ProxySetOutputFormat(s, m);
- else if (!strcasecmp(proxyaction,"SetAutoFilter"))
- ProxySetAutoFilter(s, m);
- else if (!strcasecmp(proxyaction,"ListSessions"))
- ProxyListSessions(s);
- else if (!strcasecmp(proxyaction,"AddServer"))
- ProxyAddServer(s, m);
- else if (!strcasecmp(proxyaction,"DropServer"))
- ProxyDropServer(s, m);
- else if (!strcasecmp(proxyaction,"ListServers"))
- ProxyListServers(s);
- else if (!strcasecmp(proxyaction,"ListIOHandlers"))
- ProxyListIOHandlers(s);
- else if (!strcasecmp(proxyaction,"Logoff"))
- ProxyLogoff(s);
- else
+ if (!strcasecmp(proxyaction,"SetOutputFormat"))
+ ProxySetOutputFormat(s, m);
+ else if (!strcasecmp(proxyaction,"SetAutoFilter"))
+ ProxySetAutoFilter(s, m);
+ else if (!strcasecmp(proxyaction,"ListSessions"))
+ ProxyListSessions(s);
+ else if (!strcasecmp(proxyaction,"AddServer"))
+ ProxyAddServer(s, m);
+ else if (!strcasecmp(proxyaction,"DropServer"))
+ ProxyDropServer(s, m);
+ else if (!strcasecmp(proxyaction,"ListServers"))
+ ProxyListServers(s);
+ else if (!strcasecmp(proxyaction,"ListIOHandlers"))
+ ProxyListIOHandlers(s);
+ else if (!strcasecmp(proxyaction,"Logoff"))
+ ProxyLogoff(s);
+ else
proxyerror_do(s, "Invalid Proxy Action");
- return 0;
+ return 0;
}
int proxyerror_do(struct mansession *s, char *err)
{
- struct message mo;
+ struct message mo;
- memset(&mo, 0, sizeof(struct message));
- AddHeader(&mo, "ProxyResponse: Error");
- AddHeader(&mo, "Message: %s", err);
+ memset(&mo, 0, sizeof(struct message));
+ AddHeader(&mo, "ProxyResponse: Error");
+ AddHeader(&mo, "Message: %s", err);
- s->output->write(s, &mo);
+ s->output->write(s, &mo);
- return 0;
+ return 0;
}
int ValidateAction(struct message *m, struct mansession *s, int inbound) {
- char *channel, *channel1, *channel2;
- char *context;
- char *uchannel;
- char *ucontext;
-
- if( pc.authrequired && !s->authenticated )
- return 0;
-
- if( inbound )
- ucontext = s->user.icontext;
- else
- ucontext = s->user.ocontext;
- uchannel = s->user.channel;
-
- channel = astman_get_header(m, "Channel");
- if( channel[0] != '\0' && uchannel[0] != '\0' )
- if( strncasecmp( channel, uchannel, strlen(uchannel) ) ) {
- if( debug )
- debugmsg("Message filtered (chan): %s != %s", channel, uchannel);
- return 0;
- }
-
- channel1 = astman_get_header(m, "Channel1");
- channel2 = astman_get_header(m, "Channel2");
- if( (channel1[0] != '\0' || channel2[0] != '\0') && uchannel[0] != '\0' )
- if( !(strncasecmp( channel1, uchannel, strlen(uchannel) ) == 0 ||
- strncasecmp( channel2, uchannel, strlen(uchannel) ) == 0) ) {
- if( debug )
- debugmsg("Message filtered (chan): %s/%s != %s", channel1, channel2, uchannel);
- return 0;
- }
-
- context = astman_get_header(m, "Context");
- if( context[0] != '\0' && ucontext[0] != '\0' )
- if( strcasecmp( context, ucontext ) ) {
- if( debug )
- debugmsg("Message filtered (ctxt): %s != %s", context, ucontext);
- return 0;
- }
-
- return 1;
+ char *channel, *channel1, *channel2;
+ char *context;
+ char *uchannel;
+ char *ucontext;
+
+ if( pc.authrequired && !s->authenticated )
+ return 0;
+
+ if( inbound )
+ ucontext = s->user.icontext;
+ else
+ ucontext = s->user.ocontext;
+ uchannel = s->user.channel;
+
+ channel = astman_get_header(m, "Channel");
+ if( channel[0] != '\0' && uchannel[0] != '\0' )
+ if( strncasecmp( channel, uchannel, strlen(uchannel) ) ) {
+ if( debug )
+ debugmsg("Message filtered (chan): %s != %s", channel, uchannel);
+ return 0;
+ }
+
+ channel1 = astman_get_header(m, "Channel1");
+ channel2 = astman_get_header(m, "Channel2");
+ if( (channel1[0] != '\0' || channel2[0] != '\0') && uchannel[0] != '\0' )
+ if( !(strncasecmp( channel1, uchannel, strlen(uchannel) ) == 0 ||
+ strncasecmp( channel2, uchannel, strlen(uchannel) ) == 0) ) {
+ if( debug )
+ debugmsg("Message filtered (chan): %s/%s != %s", channel1, channel2, uchannel);
+ return 0;
+ }
+
+ context = astman_get_header(m, "Context");
+ if( context[0] != '\0' && ucontext[0] != '\0' )
+ if( strcasecmp( context, ucontext ) ) {
+ if( debug )
+ debugmsg("Message filtered (ctxt): %s != %s", context, ucontext);
+ return 0;
+ }
+
+ return 1;
}
void *SendError(struct mansession *s, char *errmsg) {
- struct message m;
+ struct message m;
- memset(&m, 0, sizeof(struct message));
- AddHeader(&m, "Response: Error");
- AddHeader(&m, "Message: %s", errmsg);
+ memset(&m, 0, sizeof(struct message));
+ AddHeader(&m, "Response: Error");
+ AddHeader(&m, "Message: %s", errmsg);
- s->output->write(s, &m);
+ s->output->write(s, &m);
- return 0;
+ return 0;
}
diff --git a/src/ssl.c b/src/ssl.c
index 19b9828..40115b1 100644
--- a/src/ssl.c
+++ b/src/ssl.c
@@ -14,24 +14,8 @@
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
- */
-/*! \file
- *
- * \brief SSL for The Asterisk Management Interface - AMI
- *
- * Channel Management and more
- *
- * \author Remco Treffkorn(Architect) and Mahesh Karoshi(Senior Software Developer)
- * \ref amiconf
- */
-
-/*! \addtogroup Group_AMI AMI functions
-*/
-/*! @{
- Doxygen group */
-
-/*! \note We use negative file descriptors for secure channels. The file descriptor
+ We use negative file descriptors for secure channels. The file descriptor
-1 is reseved for errors. -2 to -... are secure file descriptors. 0 to ...
are regular file descriptors.
@@ -66,7 +50,7 @@ static int ssl_initialized;
Initializes all the ssl related stuff here. */
int init_secure(char *certfile)
{
- SSL_METHOD *meth;
+ SSL_METHOD *meth;
SSLeay_add_ssl_algorithms();
SSL_load_error_strings();
@@ -95,23 +79,23 @@ int init_secure(char *certfile)
}
-/* Initializes all the client-side ssl related stuff here.
+/* Initializes all the client-side ssl related stuff here.
*/
int client_init_secure(void)
{
- SSL_METHOD *meth;
+ SSL_METHOD *meth;
- /* client init */
- SSLeay_add_ssl_algorithms();
- meth = SSLv23_client_method();
- SSL_load_error_strings();
- cctx = SSL_CTX_new (meth);
+ /* client init */
+ SSLeay_add_ssl_algorithms();
+ meth = SSLv23_client_method();
+ SSL_load_error_strings();
+ cctx = SSL_CTX_new (meth);
- if (!cctx)
- debugmsg("Failed to create a client ssl context!");
+ if (!cctx)
+ debugmsg("Failed to create a client ssl context!");
else
debugmsg("Client SSL Context Initialized");
- return 0;
+ return 0;
}
/*! \brief Takes the negative ssl fd and returns the positive fd recieved from the os.
@@ -122,16 +106,16 @@ int get_real_fd(int fd)
if (fd<-1) {
fd = -fd - 2;
if (fd>=0 && fd <SEC_MAX)
- fd = sec_channel[fd].fd;
+ fd = sec_channel[fd].fd;
else fd = -1;
}
return fd;
}
-/*! \brief Returns the SSL pointer from the fd. This structure is filled when we accept
- * the ssl connection and used
- * for reading and writing through ssl.
+/*! \brief Returns the SSL pointer from the fd. This structure is filled when we accept
+ * the ssl connection and used
+ * for reading and writing through ssl.
*/
SSL *get_ssl(int fd)
{
@@ -145,7 +129,7 @@ SSL *get_ssl(int fd)
return ssl;
}
-/*! \brief Returns the empty ssl slot. Used to save ssl information.
+/*! \brief Returns the empty ssl slot. Used to save ssl information.
*/
int sec_getslot(void)
{
@@ -153,7 +137,7 @@ int sec_getslot(void)
for (i=0; i<SEC_MAX; i++) {
if(sec_channel[i].ssl==NULL)
- break;
+ break;
}
if (i==SEC_MAX)
@@ -161,7 +145,7 @@ int sec_getslot(void)
return i;
}
-/*! \brief Accepts the ssl connection. Returns the negative fd. negative fd's are
+/*! \brief Accepts the ssl connection. Returns the negative fd. negative fd's are
* chosen to differentiate between ssl and non-ssl connections. Positive
* fd's are used for non-ssl connections and negative fd's are used for ssl
* connections. So we purposefully calculate and return negative fds.
@@ -195,9 +179,9 @@ int saccept(int s)
fd = -(fd+2);
if (err!=1 || !ssl) {
- /* it did not work */
- sec_channel[fd].ssl = NULL; /* free the slot */
- fd = -1;
+ /* it did not work */
+ sec_channel[fd].ssl = NULL; /* free the slot */
+ fd = -1;
}
}
return fd;
@@ -269,7 +253,7 @@ int close_sock(int socket)
*/
int errexit(char s[])
{
- debugmsg("SSL critical error: %s", s);
+ debugmsg("SSL critical error: %s", s);
return -1;
}
@@ -282,107 +266,107 @@ int errexit(char s[])
*/
int is_encrypt_request(int sslclhellotimeout, int fd)
{
- fd_set listeners;
- struct timeval tv;
- char buf[1024];
- int ready_fdescriptors;
- int ret;
-
- tv.tv_sec = 0;
- tv.tv_usec = sslclhellotimeout * 1000;
-
- FD_ZERO(&listeners);
- FD_SET(fd, &listeners);
-
- ready_fdescriptors = select (fd + 1, &listeners, NULL, NULL, &tv);
-
- if (ready_fdescriptors < 0 ) {
- debugmsg("is_encrypt_request: select returned error, This should not happen:");
- return 0;
- } else if (ready_fdescriptors == 0) {
- return 0;
- }
- ret = recv(fd, buf, 100, MSG_PEEK);
- if(ret > 0) {
- /* check for sslv3 or tls*/
- if ((buf[0x00] == 0x16) && (buf[0x01] == 0x03) &&
+ fd_set listeners;
+ struct timeval tv;
+ char buf[1024];
+ int ready_fdescriptors;
+ int ret;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = sslclhellotimeout * 1000;
+
+ FD_ZERO(&listeners);
+ FD_SET(fd, &listeners);
+
+ ready_fdescriptors = select (fd + 1, &listeners, NULL, NULL, &tv);
+
+ if (ready_fdescriptors < 0 ) {
+ debugmsg("is_encrypt_request: select returned error, This should not happen:");
+ return 0;
+ } else if (ready_fdescriptors == 0) {
+ return 0;
+ }
+ ret = recv(fd, buf, 100, MSG_PEEK);
+ if(ret > 0) {
+ /* check for sslv3 or tls*/
+ if ((buf[0x00] == 0x16) && (buf[0x01] == 0x03) &&
/* for tls buf[0x02] = 0x01 and ssl v3 buf[0x02] = 0x02 */
((buf[0x02] == 0x00) || (buf[0x02] == 0x01))) {
if (debug)
- debugmsg("Received a SSL request");
+ debugmsg("Received a SSL request");
return 1;
/* check for sslv23_client_method */
} else if ((buf[0x02] == 0x01) && (buf[0x03] == 0x03) && (buf[0x04] == 0x01)) {
if (debug)
- debugmsg("Received a SSL request for SSLv23_client_method()");
+ debugmsg("Received a SSL request for SSLv23_client_method()");
return 1;
}
/* check for sslv2 and return -1 */
else if ((buf[0x02] == 0x01) && (buf[0x03] == 0x00) && (buf[0x04] == 0x02)) {
if (debug)
- debugmsg("Received a SSLv2 request()");
- return -1;
+ debugmsg("Received a SSLv2 request()");
+ return -1;
}
- }
- return 0;
+ }
+ return 0;
}
/* Connects to an asterisk server either plain or SSL as appropriate
*/
int ast_connect(struct mansession *a) {
- int s, err=-1, fd;
- SSL* ssl;
-
- fd = connect_nonb(a);
- if ( fd < 0 )
- return -1;
-
- if (a->server->use_ssl) {
- debugmsg("initiating ssl connection");
- if ((s=sec_getslot())!=-1) { /* find a slot for the ssl handle */
- sec_channel[s].fd = fd; /* remember the real fd */
-
- if((ssl=SSL_new(cctx))) { /* get a new ssl */
- sec_channel[s].ssl = ssl;
- SSL_set_fd(ssl, fd); /* and attach the real fd */
- err = SSL_connect(ssl); /* now try and connect */
- } else
+ int s, err=-1, fd;
+ SSL* ssl;
+
+ fd = connect_nonb(a);
+ if ( fd < 0 )
+ return -1;
+
+ if (a->server->use_ssl) {
+ debugmsg("initiating ssl connection");
+ if ((s=sec_getslot())!=-1) { /* find a slot for the ssl handle */
+ sec_channel[s].fd = fd; /* remember the real fd */
+
+ if((ssl=SSL_new(cctx))) { /* get a new ssl */
+ sec_channel[s].ssl = ssl;
+ SSL_set_fd(ssl, fd); /* and attach the real fd */
+ err = SSL_connect(ssl); /* now try and connect */
+ } else
debugmsg("couldn't create ssl client context");
- fd = -(s+2); /* offset by two and negate */
- /* this tells us it is a ssl fd */
- } else
+ fd = -(s+2); /* offset by two and negate */
+ /* this tells us it is a ssl fd */
+ } else
debugmsg("couldn't get SSL slot!");
- if (err==-1) {
- close_sock(fd); /* that frees the ssl too */
- fd = -1;
- }
- }
+ if (err==-1) {
+ close_sock(fd); /* that frees the ssl too */
+ fd = -1;
+ }
+ }
- debugmsg("returning ast_connect with %d", fd);
- pthread_mutex_lock(&a->lock);
- a->fd = fd;
- pthread_mutex_unlock(&a->lock);
+ debugmsg("returning ast_connect with %d", fd);
+ pthread_mutex_lock(&a->lock);
+ a->fd = fd;
+ pthread_mutex_unlock(&a->lock);
- return fd;
+ return fd;
}
int connect_nonb(struct mansession *a)
{
- int flags, n, error;
- socklen_t len;
- fd_set rset, wset;
- struct timeval tval;
+ int flags, n, error;
+ socklen_t len;
+ fd_set rset, wset;
+ struct timeval tval;
int nsec = 1, sockfd;
sockfd = get_real_fd(a->fd);
- flags = fcntl(sockfd, F_GETFL, 0);
- fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
+ flags = fcntl(sockfd, F_GETFL, 0);
+ fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
- error = 0;
- if ( (n = connect(sockfd, (struct sockaddr *) &a->sin, sizeof(a->sin)) ) < 0 ) {
+ error = 0;
+ if ( (n = connect(sockfd, (struct sockaddr *) &a->sin, sizeof(a->sin)) ) < 0 ) {
/* TODO: This seems like the nine pound hammer to me... */
/* perhaps something a bit more elegant; errno seems to change too */
if (errno == EISCONN || errno == 103 || errno==111) {
@@ -394,45 +378,45 @@ int connect_nonb(struct mansession *a)
pthread_mutex_unlock(&a->lock);
return(-1);
}
- if (errno != EINPROGRESS)
- return(-1);
+ if (errno != EINPROGRESS)
+ return(-1);
}
- /* Do whatever we want while the connect is taking place. */
-
- if (n == 0)
- goto done; /* connect completed immediately */
-
- FD_ZERO(&rset);
- FD_SET(sockfd, &rset);
- wset = rset;
- tval.tv_sec = nsec;
- tval.tv_usec = 0;
-
- if ( (n = select(sockfd+1, &rset, &wset, NULL,
- nsec ? &tval : NULL)) == 0) {
- /*close(sockfd);*/ /* we want to retry */
- errno = ETIMEDOUT;
- return(-1);
- }
-
- if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
- len = sizeof(error);
- if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
- return(-1); /* Solaris pending error */
- } else {
- /*err_quit("select error: sockfd not set");*/
- logmsg("select error: sockfd not set");
- return(-1);
- }
+ /* Do whatever we want while the connect is taking place. */
+
+ if (n == 0)
+ goto done; /* connect completed immediately */
+
+ FD_ZERO(&rset);
+ FD_SET(sockfd, &rset);
+ wset = rset;
+ tval.tv_sec = nsec;
+ tval.tv_usec = 0;
+
+ if ( (n = select(sockfd+1, &rset, &wset, NULL,
+ nsec ? &tval : NULL)) == 0) {
+ /*close(sockfd);*/ /* we want to retry */
+ errno = ETIMEDOUT;
+ return(-1);
+ }
+
+ if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
+ len = sizeof(error);
+ if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
+ return(-1); /* Solaris pending error */
+ } else {
+ /*err_quit("select error: sockfd not set");*/
+ logmsg("select error: sockfd not set");
+ return(-1);
+ }
done:
- fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
-
- if (error) {
- /* close(sockfd); */ /* disable for now, we want to retry... */
- errno = error;
- return(-1);
- }
- return(sockfd);
+ fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
+
+ if (error) {
+ /* close(sockfd); */ /* disable for now, we want to retry... */
+ errno = error;
+ return(-1);
+ }
+ return(sockfd);
}
diff --git a/src/standard.c b/src/standard.c
index 9e8f200..f377bec 100644
--- a/src/standard.c
+++ b/src/standard.c
@@ -1,10 +1,11 @@
-/* Asterisk Manager Proxy
- Copyright (c) 2005 David C. Troy <dave@popvox.com>
+/* Asterisk Manager Proxy
+ Copyright (c) 2005-2006 David C. Troy <dave@popvox.com>
- This program is free software, distributed under the terms of
- the GNU General Public License.
+ This program is free software, distributed under the terms of
+ the GNU General Public License.
- Standard I/O Handler
+ standard.c
+ Standard I/O Handler
*/
#include "astmanproxy.h"
@@ -13,58 +14,57 @@ extern struct mansession *sessions;
/* Return a fully formed message block to session_do for processing */
int _read(struct mansession *s, struct message *m) {
- int res;
-
- for (;;) {
- res = get_input(s, m->headers[m->hdrcount]);
-
- /*fprintf(stderr, "-------> %s\n", m->headers[m->hdrcount]);*/
- if (strstr(m->headers[m->hdrcount], "--END COMMAND--")) {
- if (debug) debugmsg("Found END COMMAND");
- m->in_command = 0;
- }
- if (strstr(m->headers[m->hdrcount], "Response: Follows")) {
- if (debug) debugmsg("Found Response Follows");
- m->in_command = 1;
- }
- if (res > 0) {
- if (!m->in_command && *(m->headers[m->hdrcount]) == '\0' ) {
- break;
- } else if (m->hdrcount < MAX_HEADERS - 1) {
- m->hdrcount++;
- } else {
- m->in_command = 0; // reset when block full
- }
- } else if (res < 0)
- break;
- }
-
- return res;
+ int res;
+
+ for (;;) {
+ res = get_input(s, m->headers[m->hdrcount]);
+
+ if (strstr(m->headers[m->hdrcount], "--END COMMAND--")) {
+ if (debug) debugmsg("Found END COMMAND");
+ m->in_command = 0;
+ }
+ if (strstr(m->headers[m->hdrcount], "Response: Follows")) {
+ if (debug) debugmsg("Found Response Follows");
+ m->in_command = 1;
+ }
+ if (res > 0) {
+ if (!m->in_command && *(m->headers[m->hdrcount]) == '\0' ) {
+ break;
+ } else if (m->hdrcount < MAX_HEADERS - 1) {
+ m->hdrcount++;
+ } else {
+ m->in_command = 0; // reset when block full
+ }
+ } else if (res < 0)
+ break;
+ }
+
+ return res;
}
int _write(struct mansession *s, struct message *m) {
- int i;
+ int i;
- pthread_mutex_lock(&s->lock);
- for (i=0; i<m->hdrcount; i++) {
+ pthread_mutex_lock(&s->lock);
+ for (i=0; i<m->hdrcount; i++) {
ast_carefulwrite(s->fd, m->headers[i], strlen(m->headers[i]) , s->writetimeout);
- ast_carefulwrite(s->fd, "\r\n", 2, s->writetimeout);
- }
- ast_carefulwrite(s->fd, "\r\n", 2, s->writetimeout);
- pthread_mutex_unlock(&s->lock);
+ ast_carefulwrite(s->fd, "\r\n", 2, s->writetimeout);
+ }
+ ast_carefulwrite(s->fd, "\r\n", 2, s->writetimeout);
+ pthread_mutex_unlock(&s->lock);
- return 0;
+ return 0;
}
int _onconnect(struct mansession *s, struct message *m) {
- char banner[100];
+ char banner[100];
- sprintf(banner, "%s/%s\r\n", PROXY_BANNER, PROXY_VERSION);
- pthread_mutex_lock(&s->lock);
- ast_carefulwrite(s->fd, banner, strlen(banner), s->writetimeout);
- pthread_mutex_unlock(&s->lock);
+ sprintf(banner, "%s/%s\r\n", PROXY_BANNER, PROXY_VERSION);
+ pthread_mutex_lock(&s->lock);
+ ast_carefulwrite(s->fd, banner, strlen(banner), s->writetimeout);
+ pthread_mutex_unlock(&s->lock);
- return 0;
+ return 0;
}
diff --git a/src/xml.c b/src/xml.c
index b5865f0..f068b73 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -1,10 +1,11 @@
-/* Asterisk Manager Proxy
- Copyright (c) 2005 David C. Troy <dave@popvox.com>
+/* Asterisk Manager Proxy
+ Copyright (c) 2005-2006 David C. Troy <dave@popvox.com>
- This program is free software, distributed under the terms of
- the GNU General Public License.
+ This program is free software, distributed under the terms of
+ the GNU General Public License.
- XML I/O Handler
+ xml.c
+ XML I/O Handler
*/
#include "astmanproxy.h"
@@ -21,138 +22,138 @@ int ParseXMLInput(char *xb, struct message *m);
int _read(struct mansession *s, struct message *m) {
- /* Note: No single line may be longer than MAX_LEN/s->inbuf, as per get_input */
- /* No XML Input may be longer than BUFSIZE */
+ /* Note: No single line may be longer than MAX_LEN/s->inbuf, as per get_input */
+ /* No XML Input may be longer than BUFSIZE */
- char line[MAX_LEN], xmlbuf[BUFSIZE];
- int res;
+ char line[MAX_LEN], xmlbuf[BUFSIZE];
+ int res;
- /* first let's read the whole xml block into our buffer */
- memset(xmlbuf, 0, sizeof xmlbuf);
- for (;;) {
- memset(line, 0, sizeof line);
- res = get_input(s, line);
+ /* first let's read the whole xml block into our buffer */
+ memset(xmlbuf, 0, sizeof xmlbuf);
+ for (;;) {
+ memset(line, 0, sizeof line);
+ res = get_input(s, line);
- if (res > 0) {
- if (*line == '\0' ) {
- break;
- } else if (strlen(xmlbuf) < (BUFSIZE - strlen(line)) )
- strcat(xmlbuf, line);
- } else if (res < 0)
- return res;
- }
+ if (res > 0) {
+ if (*line == '\0' ) {
+ break;
+ } else if (strlen(xmlbuf) < (BUFSIZE - strlen(line)) )
+ strcat(xmlbuf, line);
+ } else if (res < 0)
+ return res;
+ }
- /* now, let's transform and copy into a standard message block */
- debugmsg("Got xml: %s", xmlbuf);
- res = ParseXMLInput(xmlbuf, m);
+ /* now, let's transform and copy into a standard message block */
+ debugmsg("Got xml: %s", xmlbuf);
+ res = ParseXMLInput(xmlbuf, m);
- if (res < 0)
- proxyerror_do(s, "Invalid XML Input");
+ if (res < 0)
+ proxyerror_do(s, "Invalid XML Input");
- /* Return res>0 to process block, return res<0 to kill client, res=0, continue */
- return res;
+ /* Return res>0 to process block, return res<0 to kill client, res=0, continue */
+ return res;
}
void *setdoctag(char *tag, struct mansession *s) {
- /* if message came from a server, say so; otherwise it must be from proxy */
- /* right now there is no such thing as client<->client comms */
- if (s && s->server)
- strcpy(tag, XML_SERVERTAG);
- else
- strcpy(tag, XML_PROXYTAG);
+ /* if message came from a server, say so; otherwise it must be from proxy */
+ /* right now there is no such thing as client<->client comms */
+ if (s && s->server)
+ strcpy(tag, XML_SERVERTAG);
+ else
+ strcpy(tag, XML_PROXYTAG);
- return 0;
+ return 0;
}
int _write(struct mansession *s, struct message *m) {
- int i;
- char buf[BUFSIZE], outstring[MAX_LEN*3], xmlescaped[MAX_LEN*3], xmldoctag[MAX_LEN];
- char *dpos, *lpos;
-
- setdoctag(xmldoctag, m->session);
- sprintf(buf, "<%s>\r\n", xmldoctag);
-
- pthread_mutex_lock(&s->lock);
- ast_carefulwrite(s->fd, buf, strlen(buf), s->writetimeout);
-
- for (i=0; i<m->hdrcount; i++) {
- memset(xmlescaped, 0, sizeof xmlescaped);
- xml_quote_string(m->headers[i], xmlescaped);
- lpos = xmlescaped;
- dpos = strstr(lpos, ": ");
- if (dpos && *(lpos)!= ' ' && strlen(xmlescaped)<30 ) {
- strcpy(outstring, " <");
- strncat(outstring, lpos, dpos-lpos);
- strcat(outstring, " Value=\"");
- strncat(outstring, dpos+2, strlen(dpos)-2);
- strcat(outstring, "\"/>\r\n");
- } else
- sprintf(outstring, " <%s Value=\"%s\"/>\r\n", XML_UNPARSED, lpos);
- ast_carefulwrite(s->fd, outstring, strlen(outstring), s->writetimeout);
- }
- sprintf(buf, "</%s>\r\n\r\n", xmldoctag);
- ast_carefulwrite(s->fd, buf, strlen(buf), s->writetimeout);
- pthread_mutex_unlock(&s->lock);
-
- return 0;
+ int i;
+ char buf[BUFSIZE], outstring[MAX_LEN*3], xmlescaped[MAX_LEN*3], xmldoctag[MAX_LEN];
+ char *dpos, *lpos;
+
+ setdoctag(xmldoctag, m->session);
+ sprintf(buf, "<%s>\r\n", xmldoctag);
+
+ pthread_mutex_lock(&s->lock);
+ ast_carefulwrite(s->fd, buf, strlen(buf), s->writetimeout);
+
+ for (i=0; i<m->hdrcount; i++) {
+ memset(xmlescaped, 0, sizeof xmlescaped);
+ xml_quote_string(m->headers[i], xmlescaped);
+ lpos = xmlescaped;
+ dpos = strstr(lpos, ": ");
+ if (dpos && *(lpos)!= ' ' && strlen(xmlescaped)<30 ) {
+ strcpy(outstring, " <");
+ strncat(outstring, lpos, dpos-lpos);
+ strcat(outstring, " Value=\"");
+ strncat(outstring, dpos+2, strlen(dpos)-2);
+ strcat(outstring, "\"/>\r\n");
+ } else
+ sprintf(outstring, " <%s Value=\"%s\"/>\r\n", XML_UNPARSED, lpos);
+ ast_carefulwrite(s->fd, outstring, strlen(outstring), s->writetimeout);
+ }
+ sprintf(buf, "</%s>\r\n\r\n", xmldoctag);
+ ast_carefulwrite(s->fd, buf, strlen(buf), s->writetimeout);
+ pthread_mutex_unlock(&s->lock);
+
+ return 0;
}
/* Takes a single manager header line and converts xml entities */
void xml_quote_string(char *s, char *o) {
- char *c;
- c = s;
-
- do {
- if (*c == '<')
- strcat(o, "&lt;");
- else if (*c == '>')
- strcat(o, "&gt;");
- else if (*c == '&')
- strcat(o, "&amp;");
- else if (*c == '"')
- strcat(o, "&quot;");
- else if (*c == '\n')
- strcat(o, " ");
- else
- strncat(o, c, 1);
- } while (*(c++));
-
- return;
+ char *c;
+ c = s;
+
+ do {
+ if (*c == '<')
+ strcat(o, "&lt;");
+ else if (*c == '>')
+ strcat(o, "&gt;");
+ else if (*c == '&')
+ strcat(o, "&amp;");
+ else if (*c == '"')
+ strcat(o, "&quot;");
+ else if (*c == '\n')
+ strcat(o, " ");
+ else
+ strncat(o, c, 1);
+ } while (*(c++));
+
+ return;
}
int ParseXMLInput(char *xb, struct message *m) {
- char *b, *e, *bt, *et, tag[MAX_LEN], *i;
- int res = 0;
-
- /* just an empty block; go home */
- if ( !(*xb) )
- return 0;
-
- /* initialize message block */
- memset(m, 0, sizeof(struct message) );
-
- b = strstr(xb, XML_BEGIN_INPUT);
- e = strstr(xb, XML_END_INPUT);
- if (b && e) {
- bt = strstr((char *)(b + strlen(XML_BEGIN_INPUT) + 1), "<");
- while (bt < e) {
- et = strstr(bt+1, "<");
- memset(tag, 0, sizeof tag);
- strncpy(tag, bt, (et-bt) );
- bt = et;
-
- strncpy( m->headers[m->hdrcount], tag+1, strstr(tag+1," ")-(tag+1) );
- strcat(m->headers[m->hdrcount], ": ");
- i = strstr(tag+1, "\"") + 1;
- strncat( m->headers[m->hdrcount], i, strstr(i, "\"") - i );
- debugmsg("parsed: %s", m->headers[m->hdrcount]);
- m->hdrcount++;
- }
- res = 1;
- } else
- res = -1;
-
- return res;
+ char *b, *e, *bt, *et, tag[MAX_LEN], *i;
+ int res = 0;
+
+ /* just an empty block; go home */
+ if ( !(*xb) )
+ return 0;
+
+ /* initialize message block */
+ memset(m, 0, sizeof(struct message) );
+
+ b = strstr(xb, XML_BEGIN_INPUT);
+ e = strstr(xb, XML_END_INPUT);
+ if (b && e) {
+ bt = strstr((char *)(b + strlen(XML_BEGIN_INPUT) + 1), "<");
+ while (bt < e) {
+ et = strstr(bt+1, "<");
+ memset(tag, 0, sizeof tag);
+ strncpy(tag, bt, (et-bt) );
+ bt = et;
+
+ strncpy( m->headers[m->hdrcount], tag+1, strstr(tag+1," ")-(tag+1) );
+ strcat(m->headers[m->hdrcount], ": ");
+ i = strstr(tag+1, "\"") + 1;
+ strncat( m->headers[m->hdrcount], i, strstr(i, "\"") - i );
+ debugmsg("parsed: %s", m->headers[m->hdrcount]);
+ m->hdrcount++;
+ }
+ res = 1;
+ } else
+ res = -1;
+
+ return res;
}