aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--UPGRADE.txt10
-rw-r--r--apps/app_dial.c4
-rw-r--r--apps/app_osplookup.c627
-rw-r--r--channels/chan_sip.c161
-rw-r--r--configs/osp.conf.sample8
-rw-r--r--doc/channelvariables.txt18
-rw-r--r--include/asterisk/astosp.h110
-rw-r--r--res/res_osp.c1554
8 files changed, 1476 insertions, 1016 deletions
diff --git a/UPGRADE.txt b/UPGRADE.txt
index 6f9af4348..a5f9cf659 100644
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -29,6 +29,8 @@ Applications:
"noanswer" will not work. Use s or n. Also there is a new feature i, for
using indication tones, so typing in skip would give you unexpected results.
+* OSPAuth is added to authenticate OSP tokens in in_bound call setup messages.
+
Variables:
* The builtin variables ${CALLERID}, ${CALLERIDNAME}, ${CALLERIDNUM},
@@ -40,6 +42,10 @@ Variables:
* The CDR-CSV variables uniqueid, userfield, and basing time on GMT are now
adjustable from cdr.conf, instead of recompiling.
+* OSP applications exports several new variables, ${OSPINHANDLE},
+ ${OSPOUTHANDLE}, ${OSPINTOKEN}, ${OSPOUTTOKEN}, ${OSPCALLING},
+ ${OSPINTIMELIMIT}, and ${OSPOUTTIMELIMIT}
+
Functions:
* The function ${CHECK_MD5()} has been deprecated in favor of using an
@@ -66,6 +72,10 @@ The SIP channel:
* The "incominglimit" setting is replaced by the "call-limit" setting in sip.conf.
+* OSP support code is removed from SIP channel to OSP applications. ospauth
+ option in sip.conf is removed to osp.conf as authpolicy. allowguest option
+ in sip.conf cannot be set as osp anymore.
+
Installation:
* On BSD systems, the installation directories have changed to more "FreeBSDish" directories. On startup, Asterisk will look for the main configuration in /usr/local/etc/asterisk/asterisk.conf
diff --git a/apps/app_dial.c b/apps/app_dial.c
index 198790879..ba6ea7042 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -1189,10 +1189,6 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
}
if (peer) {
time(&answer_time);
-#ifdef OSP_SUPPORT
- /* Once call is answered, ditch the OSP Handle */
- pbx_builtin_setvar_helper(chan, "_OSPHANDLE", "");
-#endif
strcpy(status, "ANSWER");
/* Ah ha! Someone answered within the desired timeframe. Of course after this
we will always return with -1 so that it is hung up properly after the
diff --git a/apps/app_osplookup.c b/apps/app_osplookup.c
index 266c66dda..374564aa8 100644
--- a/apps/app_osplookup.c
+++ b/apps/app_osplookup.c
@@ -16,9 +16,9 @@
* at the top of the source tree.
*/
-/*! \file
- *
- * \brief Open Settlement Protocol Lookup
+/*!
+ * \file
+ * \brief Open Settlement Protocol Applications
*
* \author Mark Spencer <markster@digium.com>
*
@@ -49,44 +49,55 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/options.h"
-static char *tdesc = "OSP Lookup";
-
-static char *app = "OSPLookup";
-static char *app2 = "OSPNext";
-static char *app3 = "OSPFinish";
-
-static char *synopsis = "Lookup number in OSP";
-static char *synopsis2 = "Lookup next OSP entry";
-static char *synopsis3 = "Record OSP entry";
+static char *app1= "OSPAuth";
+static char *synopsis1 = "OSP authentication";
+static char *descrip1 =
+" OSPAuth([provider[|options]]): Authenticate a SIP INVITE by OSP and sets\n"
+"the variables:\n"
+" ${OSPINHANDLE}: The in_bound call transaction handle\n"
+" ${OSPINTIMELIMIT}: The in_bound call duration limit in seconds\n"
+"\n"
+"The option string may contain the following character:\n"
+" 'j' -- jump to n+101 priority if the authentication was NOT successful\n"
+"This application sets the following channel variable upon completion:\n"
+" OSPAUTHSTATUS The status of the OSP Auth attempt as a text string, one of\n"
+" SUCCESS | FAILED | ERROR\n";
-static char *descrip =
+static char *app2= "OSPLookup";
+static char *synopsis2 = "Lookup destination by OSP";
+static char *descrip2 =
" OSPLookup(exten[|provider[|options]]): Looks up an extension via OSP and sets\n"
"the variables, where 'n' is the number of the result beginning with 1:\n"
-" ${OSPTECH}: The technology to use for the call\n"
-" ${OSPDEST}: The destination to use for the call\n"
-" ${OSPTOKEN}: The actual OSP token as a string\n"
-" ${OSPHANDLE}: The OSP Handle for anything remaining\n"
-" ${OSPRESULTS}: The number of OSP results total remaining\n"
+" ${OSPOUTHANDLE}: The OSP Handle for anything remaining\n"
+" ${OSPTECH}: The technology to use for the call\n"
+" ${OSPDEST}: The destination to use for the call\n"
+" ${OSPCALLING}: The calling number to use for the call\n"
+" ${OSPOUTTOKEN}: The actual OSP token as a string\n"
+" ${OSPOUTTIMELIMIT}: The out_bound call duration limit in seconds\n"
+" ${OSPRESULTS}: The number of OSP results total remaining\n"
"\n"
"The option string may contain the following character:\n"
" 'j' -- jump to n+101 priority if the lookup was NOT successful\n"
"This application sets the following channel variable upon completion:\n"
" OSPLOOKUPSTATUS The status of the OSP Lookup attempt as a text string, one of\n"
-" SUCCESS | FAILED \n";
-
+" SUCCESS | FAILED | ERROR\n";
-static char *descrip2 =
-" OSPNext(cause[|options]): Looks up the next OSP Destination for ${OSPHANDLE}\n"
+static char *app3 = "OSPNext";
+static char *synopsis3 = "Lookup next destination by OSP";
+static char *descrip3 =
+" OSPNext(cause[|options]): Looks up the next OSP Destination for ${OSPOUTHANDLE}\n"
"See OSPLookup for more information\n"
"\n"
"The option string may contain the following character:\n"
" 'j' -- jump to n+101 priority if the lookup was NOT successful\n"
"This application sets the following channel variable upon completion:\n"
" OSPNEXTSTATUS The status of the OSP Next attempt as a text string, one of\n"
-" SUCCESS | FAILED \n";
+" SUCCESS | FAILED |ERROR\n";
-static char *descrip3 =
-" OSPFinish(status[|options]): Records call state for ${OSPHANDLE}, according to\n"
+static char *app4 = "OSPFinish";
+static char *synopsis4 = "Record OSP entry";
+static char *descrip4 =
+" OSPFinish([status[|options]]): Records call state for ${OSPINHANDLE}, according to\n"
"status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or CHANUNAVAIL\n"
"or coincidentally, just what the Dial application stores in its ${DIALSTATUS}.\n"
"\n"
@@ -94,278 +105,546 @@ static char *descrip3 =
" 'j' -- jump to n+101 priority if the finish attempt was NOT successful\n"
"This application sets the following channel variable upon completion:\n"
" OSPFINISHSTATUS The status of the OSP Finish attempt as a text string, one of\n"
-" SUCCESS | FAILED \n";
+" SUCCESS | FAILED |ERROR \n";
LOCAL_USER_DECL;
-static int str2cause(char *cause)
+static int ospauth_exec(struct ast_channel *chan, void *data)
{
- if (!strcasecmp(cause, "BUSY"))
- return AST_CAUSE_BUSY;
- if (!strcasecmp(cause, "CONGESTION"))
- return AST_CAUSE_CONGESTION;
- if (!strcasecmp(cause, "ANSWER"))
- return AST_CAUSE_NORMAL;
- if (!strcasecmp(cause, "CANCEL"))
- return AST_CAUSE_NORMAL;
- if (!strcasecmp(cause, "NOANSWER"))
- return AST_CAUSE_NOANSWER;
- if (!strcasecmp(cause, "NOCHANAVAIL"))
- return AST_CAUSE_CONGESTION;
- ast_log(LOG_WARNING, "Unknown cause '%s', using NORMAL\n", cause);
- return AST_CAUSE_NORMAL;
+ int res = 0;
+ struct localuser* u;
+ char* provider = OSP_DEF_PROVIDER;
+ int priority_jump = 0;
+ struct varshead* headp;
+ struct ast_var_t* current;
+ const char* source = "";
+ const char* token = "";
+ int handle;
+ unsigned int timelimit;
+ char* tmp;
+ char buffer[OSP_INTSTR_SIZE];
+ char* status;
+
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(provider);
+ AST_APP_ARG(options);
+ );
+
+ LOCAL_USER_ADD(u);
+
+ if (!(tmp = ast_strdupa(data))) {
+ ast_log(LOG_ERROR, "Out of memory\n");
+ LOCAL_USER_REMOVE(u);
+ return(-1);
+ }
+
+ AST_STANDARD_APP_ARGS(args, tmp);
+
+ if (!ast_strlen_zero(args.provider)) {
+ provider = args.provider;
+ }
+ ast_log(LOG_DEBUG, "OSPAuth: provider '%s'\n", provider);
+
+ if (args.options) {
+ if (strchr(args.options, 'j')) {
+ priority_jump = 1;
+ }
+ }
+ ast_log(LOG_DEBUG, "OSPAuth: priority jump '%d'\n", priority_jump);
+
+ headp = &chan->varshead;
+ AST_LIST_TRAVERSE(headp, current, entries) {
+ if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
+ source = ast_var_value(current);
+ } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
+ token = ast_var_value(current);
+ }
+ }
+ ast_log(LOG_DEBUG, "OSPAuth: source '%s'\n", source);
+ ast_log(LOG_DEBUG, "OSPAuth: token size '%d'\n", strlen(token));
+
+ res = ast_osp_auth(provider, &handle, source, chan->cid.cid_num, chan->exten, token, &timelimit);
+ if (res > 0) {
+ status = OSP_APP_SUCCESS;
+ } else {
+ timelimit = OSP_DEF_TIMELIMIT;
+ if (!res) {
+ status = OSP_APP_FAILED;
+ } else {
+ handle = OSP_INVALID_HANDLE;
+ status = OSP_APP_ERROR;
+ }
+ }
+
+ snprintf(buffer, sizeof(buffer), "%d", handle);
+ pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
+ ast_log(LOG_DEBUG, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
+ snprintf(buffer, sizeof(buffer), "%d", timelimit);
+ pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
+ ast_log(LOG_DEBUG, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
+ pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
+ ast_log(LOG_DEBUG, "OSPAuth: %s\n", status);
+
+ if(!res) {
+ if (priority_jump || ast_opt_priority_jumping) {
+ ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
+ } else {
+ res = -1;
+ }
+ } else if (res > 0) {
+ res = 0;
+ }
+
+ LOCAL_USER_REMOVE(u);
+
+ return(res);
}
static int osplookup_exec(struct ast_channel *chan, void *data)
{
- int res=0;
- struct localuser *u;
- char *temp;
- struct ast_osp_result result;
+ int res = 0;
+ struct localuser* u;
+ char* provider = OSP_DEF_PROVIDER;
int priority_jump = 0;
+ struct varshead* headp;
+ struct ast_var_t* current;
+ const char* srcdev = "";
+ char* tmp;
+ char buffer[OSP_TOKSTR_SIZE];
+ struct ast_osp_result result;
+ char* status;
+
AST_DECLARE_APP_ARGS(args,
- AST_APP_ARG(extension);
+ AST_APP_ARG(exten);
AST_APP_ARG(provider);
AST_APP_ARG(options);
);
if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "OSPLookup requires an argument OSPLookup(exten[|provider[|options]])\n");
- return -1;
+ ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[|provider[|options]])\n");
+ return(-1);
}
LOCAL_USER_ADD(u);
- if (!(temp = ast_strdupa(data))) {
+ if (!(tmp = ast_strdupa(data))) {
+ ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
- return -1;
+ return(-1);
}
- AST_STANDARD_APP_ARGS(args, temp);
+ AST_STANDARD_APP_ARGS(args, tmp);
+
+ ast_log(LOG_DEBUG, "OSPLookup: exten '%s'\n", args.exten);
+
+ if (!ast_strlen_zero(args.provider)) {
+ provider = args.provider;
+ }
+ ast_log(LOG_DEBUG, "OSPlookup: provider '%s'\n", provider);
if (args.options) {
- if (strchr(args.options, 'j'))
+ if (strchr(args.options, 'j')) {
priority_jump = 1;
+ }
}
+ ast_log(LOG_DEBUG, "OSPLookup: priority jump '%d'\n", priority_jump);
+
+ result.inhandle = OSP_INVALID_HANDLE;
+
+ headp = &chan->varshead;
+ AST_LIST_TRAVERSE(headp, current, entries) {
+ if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
+ if (sscanf(ast_var_value(current), "%d", &result.inhandle) != 1) {
+ result.inhandle = OSP_INVALID_HANDLE;
+ }
+ } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
+ if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) {
+ result.intimelimit = OSP_DEF_TIMELIMIT;
+ }
+ } else if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
+ srcdev = ast_var_value(current);
+ }
+ }
+ ast_log(LOG_DEBUG, "OSPLookup: OSPINHANDLE '%d'\n", result.inhandle);
+ ast_log(LOG_DEBUG, "OSPLookup: OSPINTIMELIMIT '%d'\n", result.intimelimit);
+ ast_log(LOG_DEBUG, "OSPLookup: source device '%s'\n", srcdev);
- ast_log(LOG_DEBUG, "Whoo hoo, looking up OSP on '%s' via '%s'\n", args.extension, args.provider ? args.provider : "<default>");
- if ((res = ast_osp_lookup(chan, args.provider, args.extension, chan->cid.cid_num, &result)) > 0) {
- char tmp[80];
- snprintf(tmp, sizeof(tmp), "%d", result.handle);
- pbx_builtin_setvar_helper(chan, "_OSPHANDLE", tmp);
- pbx_builtin_setvar_helper(chan, "_OSPTECH", result.tech);
- pbx_builtin_setvar_helper(chan, "_OSPDEST", result.dest);
- pbx_builtin_setvar_helper(chan, "_OSPTOKEN", result.token);
- snprintf(tmp, sizeof(tmp), "%d", result.numresults);
- pbx_builtin_setvar_helper(chan, "_OSPRESULTS", tmp);
- pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", "SUCCESS");
-
+ res = ast_osp_lookup(provider, srcdev, chan->cid.cid_num, args.exten, &result);
+ if (res > 0) {
+ status = OSP_APP_SUCCESS;
} else {
+ result.tech[0] = '\0';
+ result.dest[0] = '\0';
+ result.calling[0] = '\0';
+ result.token[0] = '\0';
+ result.numresults = 0;
+ result.outtimelimit = OSP_DEF_TIMELIMIT;
if (!res) {
- ast_log(LOG_NOTICE, "OSP Lookup failed for '%s' (provider '%s')\n", args.extension, args.provider ? args.provider : "<default>");
- pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", "FAILED");
- } else
- ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Lookup for '%s' (provider '%s')!\n", chan->name, args.extension, args.provider ? args.provider : "<default>" );
+ status = OSP_APP_FAILED;
+ } else {
+ result.outhandle = OSP_INVALID_HANDLE;
+ status = OSP_APP_ERROR;
+ }
+ }
+
+ snprintf(buffer, sizeof(buffer), "%d", result.outhandle);
+ pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
+ ast_log(LOG_DEBUG, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
+ pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
+ ast_log(LOG_DEBUG, "OSPLookup: OSPTECH '%s'\n", result.tech);
+ pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
+ ast_log(LOG_DEBUG, "OSPLookup: OSPDEST '%s'\n", result.dest);
+ pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
+ ast_log(LOG_DEBUG, "OSPLookup: OSPCALLING '%s'\n", result.calling);
+ pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
+ ast_log(LOG_DEBUG, "OSPLookup: OSPOUTTOKEN size '%d'\n", strlen(result.token));
+ if (!ast_strlen_zero(result.token)) {
+ snprintf(buffer, sizeof(buffer), "P-OSP-Auth-Token: %s", result.token);
+ pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
+ ast_log(LOG_DEBUG, "OSPLookup: SIPADDHEADER size '%d'\n", strlen(buffer));
}
- if (!res) {
- /* Look for a "busy" place */
- if (priority_jump || ast_opt_priority_jumping)
+ snprintf(buffer, sizeof(buffer), "%d", result.numresults);
+ pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
+ ast_log(LOG_DEBUG, "OSPLookup: OSPRESULTS '%s'\n", buffer);
+ snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
+ pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
+ ast_log(LOG_DEBUG, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
+ pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
+ ast_log(LOG_DEBUG, "OSPLookup: %s\n", status);
+
+ if(!res) {
+ if (priority_jump || ast_opt_priority_jumping) {
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
- } else if (res > 0)
+ } else {
+ res = -1;
+ }
+ } else if (res > 0) {
res = 0;
+ }
+
LOCAL_USER_REMOVE(u);
- return res;
+
+ return(res);
+}
+
+static int str2cause(char *str)
+{
+ int cause = AST_CAUSE_NORMAL;
+
+ if (ast_strlen_zero(str)) {
+ cause = AST_CAUSE_NOTDEFINED;
+ } else if (!strcasecmp(str, "BUSY")) {
+ cause = AST_CAUSE_BUSY;
+ } else if (!strcasecmp(str, "CONGESTION")) {
+ cause = AST_CAUSE_CONGESTION;
+ } else if (!strcasecmp(str, "ANSWER")) {
+ cause = AST_CAUSE_NORMAL;
+ } else if (!strcasecmp(str, "CANCEL")) {
+ cause = AST_CAUSE_NORMAL;
+ } else if (!strcasecmp(str, "NOANSWER")) {
+ cause = AST_CAUSE_NOANSWER;
+ } else if (!strcasecmp(str, "NOCHANAVAIL")) {
+ cause = AST_CAUSE_CONGESTION;
+ } else {
+ ast_log(LOG_WARNING, "OSP: Unknown cause '%s', using NORMAL\n", str);
+ }
+
+ return(cause);
}
static int ospnext_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
- char *temp;
- const char *val;
+ int priority_jump = 0;
int cause;
+ struct varshead* headp;
+ struct ast_var_t* current;
struct ast_osp_result result;
- int priority_jump = 0;
+ char *tmp;
+ char buffer[OSP_TOKSTR_SIZE];
+ char* status;
+
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(cause);
AST_APP_ARG(options);
);
if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "OSPNext should have an argument (cause[|options])\n");
- return -1;
+ ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[|options])\n");
+ return(-1);
}
LOCAL_USER_ADD(u);
- if (!(temp = ast_strdupa(data))) {
+ if (!(tmp = ast_strdupa(data))) {
+ ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
- return -1;
+ return(-1);
}
- AST_STANDARD_APP_ARGS(args, temp);
+ AST_STANDARD_APP_ARGS(args, tmp);
+
+ cause = str2cause(args.cause);
+ ast_log(LOG_DEBUG, "OSPNext: cause '%d'\n", cause);
if (args.options) {
if (strchr(args.options, 'j'))
priority_jump = 1;
}
-
- cause = str2cause(args.cause);
- val = pbx_builtin_getvar_helper(chan, "OSPHANDLE");
- result.handle = -1;
- if (!ast_strlen_zero(val) && (sscanf(val, "%d", &result.handle) == 1) && (result.handle > -1)) {
- val = pbx_builtin_getvar_helper(chan, "OSPRESULTS");
- if (ast_strlen_zero(val) || (sscanf(val, "%d", &result.numresults) != 1)) {
- result.numresults = 0;
- }
- if ((res = ast_osp_next(&result, cause)) > 0) {
- char tmp[80];
- snprintf(tmp, sizeof(tmp), "%d", result.handle);
- pbx_builtin_setvar_helper(chan, "_OSPHANDLE", tmp);
- pbx_builtin_setvar_helper(chan, "_OSPTECH", result.tech);
- pbx_builtin_setvar_helper(chan, "_OSPDEST", result.dest);
- pbx_builtin_setvar_helper(chan, "_OSPTOKEN", result.token);
- snprintf(tmp, sizeof(tmp), "%d", result.numresults);
- pbx_builtin_setvar_helper(chan, "_OSPRESULTS", tmp);
- pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", "SUCCESS");
+ ast_log(LOG_DEBUG, "OSPNext: priority jump '%d'\n", priority_jump);
+
+ result.inhandle = OSP_INVALID_HANDLE;
+ result.outhandle = OSP_INVALID_HANDLE;
+ result.numresults = 0;
+
+ headp = &chan->varshead;
+ AST_LIST_TRAVERSE(headp, current, entries) {
+ if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
+ if (sscanf(ast_var_value(current), "%d", &result.inhandle) != 1) {
+ result.inhandle = OSP_INVALID_HANDLE;
+ }
+ } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
+ if (sscanf(ast_var_value(current), "%d", &result.outhandle) != 1) {
+ result.outhandle = OSP_INVALID_HANDLE;
+ }
+ } else if (!strcasecmp(ast_var_name(current), "OSPINTIMEOUT")) {
+ if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) {
+ result.intimelimit = OSP_DEF_TIMELIMIT;
+ }
+ } else if (!strcasecmp(ast_var_name(current), "OSPRESULTS")) {
+ if (sscanf(ast_var_value(current), "%d", &result.numresults) != 1) {
+ result.numresults = 0;
+ }
}
+ }
+ ast_log(LOG_DEBUG, "OSPNext: OSPINHANDLE '%d'\n", result.inhandle);
+ ast_log(LOG_DEBUG, "OSPNext: OSPOUTHANDLE '%d'\n", result.outhandle);
+ ast_log(LOG_DEBUG, "OSPNext: OSPINTIMELIMIT '%d'\n", result.intimelimit);
+ ast_log(LOG_DEBUG, "OSPNext: OSPRESULTS '%d'\n", result.numresults);
+
+ if ((res = ast_osp_next(cause, &result)) > 0) {
+ status = OSP_APP_SUCCESS;
} else {
+ result.tech[0] = '\0';
+ result.dest[0] = '\0';
+ result.calling[0] = '\0';
+ result.token[0] = '\0';
+ result.numresults = 0;
+ result.outtimelimit = OSP_DEF_TIMELIMIT;
if (!res) {
- if (result.handle < 0)
- ast_log(LOG_NOTICE, "OSP Lookup Next failed for handle '%d'\n", result.handle);
- else
- ast_log(LOG_DEBUG, "No OSP handle specified\n");
- pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", "FAILED");
- } else
- ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Next!\n", chan->name);
+ status = OSP_APP_FAILED;
+ } else {
+ result.outhandle = OSP_INVALID_HANDLE;
+ status = OSP_APP_ERROR;
+ }
+ }
+
+ pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
+ ast_log(LOG_DEBUG, "OSPNext: OSPTECH '%s'\n", result.tech);
+ pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
+ ast_log(LOG_DEBUG, "OSPNext: OSPDEST '%s'\n", result.dest);
+ pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
+ ast_log(LOG_DEBUG, "OSPNext: OSPCALLING '%s'\n", result.calling);
+ pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
+ ast_log(LOG_DEBUG, "OSPNext: OSPOUTTOKEN size '%d'\n", strlen(result.token));
+ if (!ast_strlen_zero(result.token)) {
+ snprintf(buffer, sizeof(buffer), "P-OSP-Auth-Token: %s", result.token);
+ pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
+ ast_log(LOG_DEBUG, "OSPNext: SIPADDHEADER size '%d'\n", strlen(buffer));
}
- if (!res) {
- /* Look for a "busy" place */
- if (priority_jump || ast_opt_priority_jumping)
+ snprintf(buffer, sizeof(buffer), "%d", result.numresults);
+ pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
+ ast_log(LOG_DEBUG, "OSPNext: OSPRESULTS '%s'\n", buffer);
+ snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
+ pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
+ ast_log(LOG_DEBUG, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
+ pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
+ ast_log(LOG_DEBUG, "OSPNext: %s\n", status);
+
+ if(!res) {
+ if (priority_jump || ast_opt_priority_jumping) {
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
- } else if (res > 0)
+ } else {
+ res = -1;
+ }
+ } else if (res > 0) {
res = 0;
+ }
+
LOCAL_USER_REMOVE(u);
- return res;
+
+ return(res);
}
static int ospfinished_exec(struct ast_channel *chan, void *data)
{
- int res=0;
- struct localuser *u;
- char *temp;
- const char *val;
- int cause;
- time_t start=0, duration=0;
- struct ast_osp_result result;
+ int res = 1;
+ struct localuser* u;
int priority_jump = 0;
+ int cause;
+ struct varshead* headp;
+ struct ast_var_t* current;
+ int inhandle = OSP_INVALID_HANDLE;
+ int outhandle = OSP_INVALID_HANDLE;
+ int recorded = 0;
+ time_t start, connect, end;
+ char* tmp;
+ char* str = "";
+ char buffer[OSP_INTSTR_SIZE];
+ char* status;
+
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(status);
AST_APP_ARG(options);
);
- if (ast_strlen_zero(data)) {
- ast_log(LOG_WARNING, "OSPFinish should have an argument (status[|options])\n");
- return -1;
- }
-
LOCAL_USER_ADD(u);
- if (!(temp = ast_strdupa(data))) {
+ if (!(tmp = ast_strdupa(data))) {
+ ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
- return -1;
+ return(-1);
}
- AST_STANDARD_APP_ARGS(args, temp);
+ AST_STANDARD_APP_ARGS(args, tmp);
if (args.options) {
if (strchr(args.options, 'j'))
priority_jump = 1;
}
+ ast_log(LOG_DEBUG, "OSPFinish: priority jump '%d'\n", priority_jump);
+
+ headp = &chan->varshead;
+ AST_LIST_TRAVERSE(headp, current, entries) {
+ if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
+ if (sscanf(ast_var_value(current), "%d", &inhandle) != 1) {
+ inhandle = OSP_INVALID_HANDLE;
+ }
+ } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
+ if (sscanf(ast_var_value(current), "%d", &outhandle) != 1) {
+ outhandle = OSP_INVALID_HANDLE;
+ }
+ } else if (!recorded &&
+ (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") ||
+ !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") ||
+ !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS")))
+ {
+ if (strcasecmp(ast_var_value(current), OSP_APP_SUCCESS)) {
+ recorded = 1;
+ }
+ }
+ }
+ ast_log(LOG_DEBUG, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
+ ast_log(LOG_DEBUG, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
+ ast_log(LOG_DEBUG, "OSPFinish: recorded '%d'\n", recorded);
+
+ if (!recorded) {
+ str = args.status;
+ }
+ cause = str2cause(str);
+ ast_log(LOG_DEBUG, "OSPFinish: cause '%d'\n", cause);
if (chan->cdr) {
- start = chan->cdr->answer.tv_sec;
- if (start)
- duration = time(NULL) - start;
- else
- duration = 0;
- } else
- ast_log(LOG_WARNING, "OSPFinish called on channel '%s' with no CDR!\n", chan->name);
-
- cause = str2cause(args.status);
- val = pbx_builtin_getvar_helper(chan, "OSPHANDLE");
- result.handle = -1;
- if (!ast_strlen_zero(val) && (sscanf(val, "%d", &result.handle) == 1) && (result.handle > -1)) {
- if (!ast_osp_terminate(result.handle, cause, start, duration)) {
- pbx_builtin_setvar_helper(chan, "_OSPHANDLE", "");
- pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", "SUCCESS");
- res = 1;
+ start = chan->cdr->start.tv_sec;
+ connect = chan->cdr->answer.tv_sec;
+ if (connect) {
+ end = time(NULL);
+ } else {
+ end = connect;
}
} else {
- if (!res) {
- if (result.handle > -1)
- ast_log(LOG_NOTICE, "OSP Finish failed for handle '%d'\n", result.handle);
- else
- ast_log(LOG_DEBUG, "No OSP handle specified\n");
- pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", "FAILED");
- } else
- ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Terminate!\n", chan->name);
+ start = 0;
+ connect = 0;
+ end = 0;
+ }
+ ast_log(LOG_DEBUG, "OSPFinish: start '%ld'\n", start);
+ ast_log(LOG_DEBUG, "OSPFinish: connect '%ld'\n", connect);
+ ast_log(LOG_DEBUG, "OSPFinish: end '%ld'\n", end);
+
+ if (ast_osp_finish(outhandle, cause, start, connect, end) <= 0) {
+ ast_log(LOG_DEBUG, "OSPFinish: Unable to report usage for out_bound call\n");
+ }
+ if (ast_osp_finish(inhandle, cause, start, connect, end) <= 0) {
+ ast_log(LOG_DEBUG, "OSPFinish: Unable to report usage for in_bound call\n");
+ }
+ snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
+ pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
+ pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
+
+ if (res > 0) {
+ status = OSP_APP_SUCCESS;
+ } else if (!res) {
+ status = OSP_APP_FAILED;
+ } else {
+ status = OSP_APP_ERROR;
}
- if (!res) {
- /* Look for a "busy" place */
- if (priority_jump || ast_opt_priority_jumping)
+ pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
+
+ if(!res) {
+ if (priority_jump || ast_opt_priority_jumping) {
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
- } else if (res > 0)
+ } else {
+ res = -1;
+ }
+ } else if (res > 0) {
res = 0;
+ }
+
LOCAL_USER_REMOVE(u);
- return res;
-}
+ return(res);
+}
-int unload_module(void)
+int load_module(void)
{
int res;
- res = ast_unregister_application(app3);
- res |= ast_unregister_application(app2);
- res |= ast_unregister_application(app);
+ ast_osp_adduse();
- STANDARD_HANGUP_LOCALUSERS;
+ res = ast_register_application(app1, ospauth_exec, synopsis1, descrip1);
+ res |= ast_register_application(app2, osplookup_exec, synopsis2, descrip2);
+ res |= ast_register_application(app3, ospnext_exec, synopsis3, descrip3);
+ res |= ast_register_application(app4, ospfinished_exec, synopsis4, descrip4);
- return res;
+ return(res);
}
-int load_module(void)
+int unload_module(void)
{
int res;
- res = ast_register_application(app, osplookup_exec, synopsis, descrip);
- res |= ast_register_application(app2, ospnext_exec, synopsis2, descrip2);
- res |= ast_register_application(app3, ospfinished_exec, synopsis3, descrip3);
-
- return res;
+ res = ast_unregister_application(app4);
+ res |= ast_unregister_application(app3);
+ res |= ast_unregister_application(app2);
+ res |= ast_unregister_application(app1);
+
+ STANDARD_HANGUP_LOCALUSERS;
+
+ ast_osp_deluse();
+
+ return(res);
}
int reload(void)
{
- return 0;
+ return(0);
}
-
char *description(void)
{
- return tdesc;
+ return("Open Settlement Protocol Applications");
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
- return res;
+ return(res);
}
char *key()
{
- return ASTERISK_GPL_KEY;
+ return(ASTERISK_GPL_KEY);
}
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 7b2d58a3d..196e60f08 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -93,10 +93,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stringfields.h"
#include "asterisk/monitor.h"
-#ifdef OSP_SUPPORT
-#include "asterisk/astosp.h"
-#endif
-
#ifndef FALSE
#define FALSE 0
#endif
@@ -506,7 +502,6 @@ struct sip_pkt;
/*! \brief Parameters to the transmit_invite function */
struct sip_invite_param {
const char *distinctive_ring; /*!< Distinctive ring header */
- const char *osptoken; /*!< OSP token for this call */
int addsipheaders; /*!< Add extra SIP headers */
const char *uri_options; /*!< URI options to add to the URI */
const char *vxml_url; /*!< VXML url for Cisco phones */
@@ -596,20 +591,14 @@ struct sip_auth {
#define SIP_PROG_INBAND_NEVER (0 << 24)
#define SIP_PROG_INBAND_NO (1 << 24)
#define SIP_PROG_INBAND_YES (2 << 24)
-/* Open Settlement Protocol authentication */
-#define SIP_OSPAUTH (3 << 26) /*!< four settings, uses two bits */
-#define SIP_OSPAUTH_NO (0 << 26)
-#define SIP_OSPAUTH_GATEWAY (1 << 26)
-#define SIP_OSPAUTH_PROXY (2 << 26)
-#define SIP_OSPAUTH_EXCLUSIVE (3 << 26)
-#define SIP_CALL_ONHOLD (1 << 28) /*!< Call states */
-#define SIP_CALL_LIMIT (1 << 29) /*!< Call limit enforced for this call */
-#define SIP_SENDRPID (1 << 30) /*!< Remote Party-ID Support */
-#define SIP_INC_COUNT (1 << 31) /*!< Did this connection increment the counter of in-use calls? */
+#define SIP_CALL_ONHOLD (1 << 26) /*!< Call states */
+#define SIP_CALL_LIMIT (1 << 27) /*!< Call limit enforced for this call */
+#define SIP_SENDRPID (1 << 28) /*!< Remote Party-ID Support */
+#define SIP_INC_COUNT (1 << 29) /*!< Did this connection increment the counter of in-use calls? */
#define SIP_FLAGS_TO_COPY \
(SIP_PROMISCREDIR | SIP_TRUSTRPID | SIP_SENDRPID | SIP_DTMF | SIP_REINVITE | \
- SIP_PROG_INBAND | SIP_OSPAUTH | SIP_USECLIENTCODE | SIP_NAT | \
+ SIP_PROG_INBAND | SIP_USECLIENTCODE | SIP_NAT | \
SIP_USEREQPHONE | SIP_INSECURE_PORT | SIP_INSECURE_INVITE)
/* a new page of flags for peers */
@@ -721,11 +710,6 @@ static struct sip_pvt {
char lastmsg[256]; /*!< Last Message sent/received */
int amaflags; /*!< AMA Flags */
int pendinginvite; /*!< Any pending invite */
-#ifdef OSP_SUPPORT
- int osphandle; /*!< OSP Handle for call */
- time_t ospstart; /*!< OSP Start time */
- unsigned int osptimelimit; /*!< OSP call duration limit */
-#endif
struct sip_request initreq; /*!< Initial request that opened the SIP dialog */
int maxtime; /*!< Max time for first response */
@@ -2066,9 +2050,6 @@ static int sip_call(struct ast_channel *ast, char *dest, int timeout)
{
int res;
struct sip_pvt *p;
-#ifdef OSP_SUPPORT
- const char *osphandle = NULL;
-#endif
struct varshead *headp;
struct ast_var_t *current;
@@ -2093,29 +2074,10 @@ static int sip_call(struct ast_channel *ast, char *dest, int timeout)
/* Check whether there is a variable with a name starting with SIPADDHEADER */
p->options->addsipheaders = 1;
}
-
-
-#ifdef OSP_SUPPORT
- else if (!p->options->osptoken && !strcasecmp(ast_var_name(current), "OSPTOKEN")) {
- p->options->osptoken = ast_var_value(current);
- } else if (!osphandle && !strcasecmp(ast_var_name(current), "OSPHANDLE")) {
- osphandle = ast_var_value(current);
- }
-#endif
}
res = 0;
ast_set_flag(&p->flags[0], SIP_OUTGOING);
-#ifdef OSP_SUPPORT
- if (!p->options->osptoken || !osphandle || (sscanf(osphandle, "%d", &p->osphandle) != 1)) {
- /* Force Disable OSP support */
- if (option_debug)
- ast_log(LOG_DEBUG, "Disabling OSP support for this call. osptoken = %s, osphandle = %s\n", p->options->osptoken, osphandle);
- p->options->osptoken = NULL;
- osphandle = NULL;
- p->osphandle = -1;
- }
-#endif
ast_log(LOG_DEBUG, "Outgoing Call for %s\n", p->username);
res = update_call_counter(p, INC_CALL_LIMIT);
if ( res != -1 ) {
@@ -2530,11 +2492,6 @@ static int sip_hangup(struct ast_channel *ast)
ast_log(LOG_DEBUG, "Hangup call %s, SIP callid %s)\n", ast->name, p->callid);
ast_mutex_lock(&p->lock);
-#ifdef OSP_SUPPORT
- if ((p->osphandle > -1) && (ast->_state == AST_STATE_UP)) {
- ast_osp_terminate(p->osphandle, AST_CAUSE_NORMAL, p->ospstart, time(NULL) - p->ospstart);
- }
-#endif
if (option_debug && sipdebug)
ast_log(LOG_DEBUG, "update_call_counter(%s) - decrement call limit counter on hangup\n", p->username);
update_call_counter(p, DEC_CALL_LIMIT);
@@ -2638,9 +2595,6 @@ static int sip_answer(struct ast_channel *ast)
ast_mutex_lock(&p->lock);
if (ast->_state != AST_STATE_UP) {
-#ifdef OSP_SUPPORT
- time(&p->ospstart);
-#endif
try_suggested_sip_codec(p);
ast_setstate(ast, AST_STATE_UP);
@@ -2868,10 +2822,6 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
struct ast_variable *v = NULL;
int fmt;
int what;
-#ifdef OSP_SUPPORT
- char iabuf[INET_ADDRSTRLEN];
- char peer[MAXHOSTNAMELEN];
-#endif
ast_mutex_unlock(&i->lock);
/* Don't hold a sip pvt lock while we allocate a channel */
@@ -2961,10 +2911,6 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
if (!ast_strlen_zero(i->callid)) {
pbx_builtin_setvar_helper(tmp, "SIPCALLID", i->callid);
}
-#ifdef OSP_SUPPORT
- snprintf(peer, sizeof(peer), "[%s]:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), i->sa.sin_addr), ntohs(i->sa.sin_port));
- pbx_builtin_setvar_helper(tmp, "OSPPEER", peer);
-#endif
ast_setstate(tmp, state);
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(tmp)) {
@@ -3212,10 +3158,6 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si
if (intended_method != SIP_OPTIONS) /* Peerpoke has it's own system */
p->timer_t1 = 500; /* Default SIP retransmission timer T1 (RFC 3261) */
-#ifdef OSP_SUPPORT
- p->osphandle = -1;
- p->osptimelimit = 0;
-#endif
if (sin) {
p->sa = *sin;
if (ast_sip_ouraddrfor(&p->sa.sin_addr,&p->ourip))
@@ -5076,12 +5018,6 @@ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init)
if (!ast_strlen_zero(p->referred_by))
add_header(&req, "Referred-By", p->referred_by);
}
-#ifdef OSP_SUPPORT
- if ((req.method != SIP_OPTIONS) && p->options && !ast_strlen_zero(p->options->osptoken)) {
- ast_log(LOG_DEBUG,"Adding OSP Token: %s\n", p->options->osptoken);
- add_header(&req, "P-OSP-Auth-Token", p->options->osptoken);
- }
-#endif
if (p->options && !ast_strlen_zero(p->options->distinctive_ring))
{
add_header(&req, "Alert-Info", p->options->distinctive_ring);
@@ -6286,21 +6222,6 @@ static void build_route(struct sip_pvt *p, struct sip_request *req, int backward
list_route(p->route);
}
-#ifdef OSP_SUPPORT
-/*! \brief Validate OSP token for user authorization */
-static int check_osptoken (struct sip_pvt *p, char *token)
-{
- char tmp[80];
-
- if (ast_osp_validate (NULL, token, &p->osphandle, &p->osptimelimit, p->cid_num, p->sa.sin_addr, p->exten) < 1) {
- return -1;
- } else {
- snprintf (tmp, sizeof (tmp), "%d", p->osphandle);
- pbx_builtin_setvar_helper (p->owner, "_OSPHANDLE", tmp);
- return 0;
- }
-}
-#endif
/*! \brief Check user authorization from peer definition
Some actions, like REGISTER and INVITEs from peers require
@@ -6318,12 +6239,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, const char *us
const char *authtoken;
/* Always OK if no secret */
- if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)
-#ifdef OSP_SUPPORT
- && !ast_test_flag(&p->flags[0], SIP_OSPAUTH)
- && global_allowguest != 2
-#endif
- )
+ if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret))
return 0;
if (sipmethod == SIP_REGISTER || sipmethod == SIP_SUBSCRIBE) {
/* On a REGISTER, we have to use 401 and its family of headers instead of 407 and its family
@@ -6333,38 +6249,6 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, const char *us
reqheader = "Authorization";
respheader = "WWW-Authenticate";
}
-#ifdef OSP_SUPPORT
- else {
- char *osptoken;
- if (option_debug)
- ast_log (LOG_DEBUG, "Checking OSP Authentication!\n");
- osptoken = get_header (req, "P-OSP-Auth-Token");
- switch (ast_test_flag(&p->flags[0], SIP_OSPAUTH)) {
- case SIP_OSPAUTH_NO:
- break;
- case SIP_OSPAUTH_GATEWAY:
- if (ast_strlen_zero(osptoken)) {
- if (ast_strlen_zero(secret) && ast_strlen_zero (md5secret))
- return 0;
- } else {
- return check_osptoken(p, osptoken);
- }
- break;
- case SIP_OSPAUTH_PROXY:
- if (ast_strlen_zero(osptoken))
- return 0;
- return check_osptoken(p, osptoken);
- break;
- case SIP_OSPAUTH_EXCLUSIVE:
- if (ast_strlen_zero(osptoken))
- return -1;
- return check_osptoken(p, osptoken);
- break;
- default:
- return -1;
- }
- }
-#endif
authtoken = get_header(req, reqheader);
if (ignore && !ast_strlen_zero(p->randdata) && ast_strlen_zero(authtoken)) {
/* This is a retransmitted invite/register/etc, don't reconstruct authentication
@@ -7447,12 +7331,6 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
/* do we allow guests? */
if (!global_allowguest)
res = -1; /* we don't want any guests, authentication will fail */
-#ifdef OSP_SUPPORT
- else if (global_allowguest == 2) {
- ast_copy_flags(&p->flags[0], &global_flags[0], SIP_OSPAUTH);
- res = check_auth(p, req, "", "", "", sipmethod, uri, reliable, ignore);
- }
-#endif
}
}
@@ -8456,11 +8334,6 @@ static int sip_show_settings(int fd, int argc, char *argv[])
ast_cli(fd, " IP ToS SIP: %s\n", ast_tos2str(global_tos_sip));
ast_cli(fd, " IP ToS RTP audio: %s\n", ast_tos2str(global_tos_audio));
ast_cli(fd, " IP ToS RTP video: %s\n", ast_tos2str(global_tos_video));
-#ifdef OSP_SUPPORT
- ast_cli(fd, " OSP Support: Yes\n");
-#else
- ast_cli(fd, " OSP Support: No\n");
-#endif
if (!realtimepeers && !realtimeusers)
ast_cli(fd, " SIP realtime: Disabled\n" );
else
@@ -9777,9 +9650,6 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
if (!ignore && p->owner) {
if (p->owner->_state != AST_STATE_UP) {
-#ifdef OSP_SUPPORT
- time(&p->ospstart);
-#endif
ast_queue_control(p->owner, AST_CONTROL_ANSWER);
} else { /* RE-invite */
ast_queue_frame(p->owner, &ast_null_frame);
@@ -10926,9 +10796,6 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
if (!ignore && p)
p->lastinvite = seqno;
if (c) {
-#ifdef OSP_SUPPORT
- ast_channel_setwhentohangup (c, p->osptimelimit);
-#endif
switch(c->_state) {
case AST_STATE_DOWN:
transmit_response(p, "100 Trying", req);
@@ -12281,26 +12148,10 @@ static int handle_common_options(struct ast_flags *flags, struct ast_flags *mask
else if (strcasecmp(v->value, "never"))
ast_set_flag(&flags[0], SIP_PROG_INBAND_NO);
} else if (!strcasecmp(v->name, "allowguest")) {
-#ifdef OSP_SUPPORT
- if (!strcasecmp(v->value, "osp"))
- global_allowguest = 2;
- else
-#endif
if (ast_true(v->value))
global_allowguest = 1;
else
global_allowguest = 0;
-#ifdef OSP_SUPPORT
- } else if (!strcasecmp(v->name, "ospauth")) {
- ast_set_flag(&mask[0], SIP_OSPAUTH);
- ast_clear_flag(&flags[0], SIP_OSPAUTH);
- if (!strcasecmp(v->value, "proxy"))
- ast_set_flag(&flags[0], SIP_OSPAUTH_PROXY);
- else if (!strcasecmp(v->value, "gateway"))
- ast_set_flag(&flags[0], SIP_OSPAUTH_GATEWAY);
- else if(!strcasecmp (v->value, "exclusive"))
- ast_set_flag(&flags[0], SIP_OSPAUTH_EXCLUSIVE);
-#endif
} else if (!strcasecmp(v->name, "promiscredir")) {
ast_set_flag(&mask[0], SIP_PROMISCREDIR);
ast_set2_flag(&flags[0], ast_true(v->value), SIP_PROMISCREDIR);
diff --git a/configs/osp.conf.sample b/configs/osp.conf.sample
index e7e04036a..75545716f 100644
--- a/configs/osp.conf.sample
+++ b/configs/osp.conf.sample
@@ -62,3 +62,11 @@
; Set the "source" for requesting authorization
;
;source=foo
+;
+; Set the authentication policy.
+; 0 - NO
+; 1 - YES
+; 2 - EXCLUSIVE
+; Default is 1, validate token but allow no token.
+;
+;authpolicy=1
diff --git a/doc/channelvariables.txt b/doc/channelvariables.txt
index 3b3a742b6..d2befa33b 100644
--- a/doc/channelvariables.txt
+++ b/doc/channelvariables.txt
@@ -612,6 +612,7 @@ ${DBGETSTATUS} * dbget()
${ENUMSTATUS} * enumlookup()
${HASVMSTATUS} * hasnewvoicemail()
${LOOKUPBLSTATUS} * lookupblacklist()
+${OSPAUTHSTATUS} * ospauth()
${OSPLOOKUPSTATUS} * osplookup()
${OSPNEXTSTATUS} * ospnext()
${OSPFINISHSTATUS} * ospfinish()
@@ -754,14 +755,17 @@ ${MACRO_CONTEXT} * The calling context
${MACRO_PRIORITY} * The calling priority
${MACRO_OFFSET} Offset to add to priority at return from macro
-If you compile with OSP support in the SIP channel, these
-variables are used:
+If you compile with OSP support, these variables are used:
---------------------------------------------------------
-${OSPHANDLE} Handle from the OSP Library
-${OSPTECH} OSP Technology from Library
-${OSPDEST} OSP Destination from Library
-${OSPTOKEN} OSP Token to use for call from Library
-${OSPRESULTS} Number of OSP results
+${OSPINHANDLE} OSP handle of in_bound call
+${OSPINTIMELIMIT} Duration limit for in_bound call
+${OSPOUTHANDLE} OSP handle of out_bound call
+${OSPTECH} OSP technology
+${OSPDEST} OSP destination
+${OSPCALLING} OSP calling number
+${OSPOUTTOKEN} OSP token to use for out_bound call
+${OSPOUTTIMELIMIT} Duration limit for out_bound call
+${OSPRESULTS} Number of remained destinations
____________________________________
CDR Variables
diff --git a/include/asterisk/astosp.h b/include/asterisk/astosp.h
index 9781ca639..b7ef46598 100644
--- a/include/asterisk/astosp.h
+++ b/include/asterisk/astosp.h
@@ -16,33 +16,111 @@
* at the top of the source tree.
*/
-/*! \file
+/*!
+ * \file
* \brief OSP support (Open Settlement Protocol)
*/
#ifndef _ASTERISK_OSP_H
#define _ASTERISK_OSP_H
-#include "asterisk/channel.h"
-#include <netinet/in.h>
#include <time.h>
+#include <netinet/in.h>
-struct ast_osp_result {
- int handle;
- int numresults;
- char tech[20];
- char dest[256];
- char token[4096];
-};
+#include "asterisk/channel.h"
-/* Note: Channel will be auto-serviced if specified. Returns -1 on hangup,
- 0 if nothing found, or 1 if something is found */
-int ast_osp_lookup(struct ast_channel *chan, char *provider, char *extension, char *callerid, struct ast_osp_result *result);
+#define OSP_DEF_PROVIDER ((char*)"default") /* Default provider context name */
+#define OSP_INVALID_HANDLE ((int)-1) /* Invalid OSP handle, provider, transaction etc. */
+#define OSP_DEF_TIMELIMIT ((unsigned int)0) /* Default duration limit, no limit */
-int ast_osp_next(struct ast_osp_result *result, int cause);
+#define OSP_INTSTR_SIZE ((unsigned int)16) /* Signed/unsigned int string buffer size */
+#define OSP_NORSTR_SIZE ((unsigned int)256) /* Normal string buffer size */
+#define OSP_TOKSTR_SIZE ((unsigned int)4096) /* Token string buffer size */
-int ast_osp_terminate(int handle, int cause, time_t start, time_t duration);
+#define OSP_APP_SUCCESS ((char*)"SUCCESS") /* Return status, success */
+#define OSP_APP_FAILED ((char*)"FAILED") /* Return status, failed */
+#define OSP_APP_ERROR ((char*)"ERROR") /* Return status, error */
-int ast_osp_validate(char *provider, char *token, int *handle, unsigned int *timeout, const char *callerid, struct in_addr addr, const char *extension);
+struct ast_osp_result {
+ int inhandle;
+ int outhandle;
+ unsigned int intimelimit;
+ unsigned int outtimelimit;
+ char tech[20];
+ char dest[OSP_NORSTR_SIZE];
+ char calling[OSP_NORSTR_SIZE];
+ char token[OSP_TOKSTR_SIZE];
+ int numresults;
+};
+
+/*!
+ * \brief OSP Increase Use Count function
+ */
+void ast_osp_adduse(void);
+/*!
+ * \brief OSP Decrease Use Count function
+ */
+void ast_osp_deluse(void);
+/*!
+ * \brief OSP Authentication function
+ * \param provider OSP provider context name
+ * \param transaction OSP transaction handle, output
+ * \param source Source of in_bound call
+ * \param calling Calling number
+ * \param called Called number
+ * \param token OSP token, may be empty
+ * \param timelimit Call duration limit, output
+ * \return 1 Authenricated, 0 Unauthenticated, -1 Error
+ */
+int ast_osp_auth(
+ const char* provider, /* OSP provider context name */
+ int* transaction, /* OSP transaction handle, output */
+ const char* source, /* Source of in_bound call */
+ const char* calling, /* Calling number */
+ const char* called, /* Called number */
+ const char* token, /* OSP token, may be empty */
+ unsigned int* timelimit /* Call duration limit, output */
+);
+/*!
+ * \brief OSP Lookup function
+ * \param provider OSP provider context name
+ * \param srcdev Source device of out_bound call
+ * \param calling Calling number
+ * \param called Called number
+ * \param result Lookup results
+ * \return 1 Found , 0 No route, -1 Error
+ */
+int ast_osp_lookup(
+ const char* provider, /* OSP provider conttext name */
+ const char* srcdev, /* Source device of out_bound call */
+ const char* calling, /* Calling number */
+ const char* called, /* Called number */
+ struct ast_osp_result* result /* OSP lookup results, in/output */
+);
+/*!
+ * \brief OSP Next function
+ * \param reason Last destination failure reason
+ * \param result Lookup results, in/output
+ * \return 1 Found , 0 No route, -1 Error
+ */
+int ast_osp_next(
+ int reason, /* Last destination failure reason */
+ struct ast_osp_result *result /* OSP lookup results, in/output */
+);
+/*!
+ * \brief OSP Finish function
+ * \param handle OSP in/out_bound transaction handle
+ * \param reason Last destination failure reason
+ * \param start Call start time
+ * \param duration Call duration
+ * \return 1 Success, 0 Failed, -1 Error
+ */
+int ast_osp_finish(
+ int handle, /* OSP in/out_bound transaction handle */
+ int reason, /* Last destination failure reason */
+ time_t start, /* Call start time */
+ time_t connect, /* Call connect time */
+ time_t end /* Call end time */
+);
#endif /* _ASTERISK_OSP_H */
diff --git a/res/res_osp.c b/res/res_osp.c
index 65b6a575a..43cb403f1 100644
--- a/res/res_osp.c
+++ b/res/res_osp.c
@@ -16,17 +16,18 @@
* at the top of the source tree.
*/
-/*! \file
- *
+/*!
+ * \file
* \brief Provide Open Settlement Protocol capability
*
* \author Mark Spencer <markster@digium.com>
*
- * \arg See also: \ref chan_sip.c
+ * \arg See also: \ref app_osplookup.c
*/
#include <sys/types.h>
#include <osp.h>
+#include <osputils.h>
#include <openssl/err.h>
#include <stdio.h>
#include <dirent.h>
@@ -61,809 +62,1042 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/callerid.h"
#include "asterisk/pbx.h"
-#define MAX_CERTS 10
-#define MAX_SERVICEPOINTS 10
-#define OSP_MAX 256
-
-#define OSP_DEFAULT_MAX_CONNECTIONS 20
-#define OSP_DEFAULT_RETRY_DELAY 0
-#define OSP_DEFAULT_RETRY_LIMIT 2
-#define OSP_DEFAULT_TIMEOUT 500
-
-static int loadPemCert(unsigned char *FileName, unsigned char *buffer, int *len);
-static int loadPemPrivateKey(unsigned char *FileName, unsigned char *buffer, int *len);
-
-AST_MUTEX_DEFINE_STATIC(osplock);
+/* OSP Authentication Policy */
+enum osp_authpolicy {
+ OSP_AUTH_NO,
+ OSP_AUTH_YES,
+ OSP_AUTH_EXCLUSIVE
+};
-static int initialized = 0;
-static int hardware = 0;
-static unsigned tokenformat = TOKEN_ALGO_SIGNED;
+#define OSP_CONFIG_FILE ((char*)"osp.conf")
+#define OSP_GENERAL_CAT ((char*)"general")
+#define OSP_MAX_CERTS ((unsigned int)10)
+#define OSP_MAX_SRVS ((unsigned int)10)
+#define OSP_DEF_MAXCONNECTIONS ((unsigned int)20)
+#define OSP_MIN_MAXCONNECTIONS ((unsigned int)1)
+#define OSP_MAX_MAXCONNECTIONS ((unsigned int)1000)
+#define OSP_DEF_RETRYDELAY ((unsigned int)0)
+#define OSP_MIN_RETRYDELAY ((unsigned int)0)
+#define OSP_MAX_RETRYDELAY ((unsigned int)10)
+#define OSP_DEF_RETRYLIMIT ((unsigned int)2)
+#define OSP_MIN_RETRYLIMIT ((unsigned int)0)
+#define OSP_MAX_RETRYLIMIT ((unsigned int)100)
+#define OSP_DEF_TIMEOUT ((unsigned int)500)
+#define OSP_MIN_TIMEOUT ((unsigned int)200)
+#define OSP_MAX_TIMEOUT ((unsigned int)10000)
+#define OSP_DEF_AUTHPOLICY ((enum osp_authpolicy)OSP_AUTH_YES)
+#define OSP_AUDIT_URL ((char*)"localhost")
+#define OSP_LOCAL_VALIDATION ((int)1)
+#define OSP_SSL_LIFETIME ((unsigned int)300)
+#define OSP_HTTP_PERSISTENCE ((int)1)
+#define OSP_CUSTOMER_ID ((char*)"")
+#define OSP_DEVICE_ID ((char*)"")
+#define OSP_DEF_DESTINATIONS ((unsigned int)5)
struct osp_provider {
- char name[OSP_MAX];
- char localpvtkey[OSP_MAX];
- char localcert[OSP_MAX];
- char cacerts[MAX_CERTS][OSP_MAX];
- int cacount;
- char servicepoints[MAX_SERVICEPOINTS][OSP_MAX];
- char source[OSP_MAX];
- int spcount;
- int dead;
+ char name[OSP_NORSTR_SIZE];
+ char privatekey[OSP_NORSTR_SIZE];
+ char localcert[OSP_NORSTR_SIZE];
+ unsigned int cacount;
+ char cacerts[OSP_MAX_CERTS][OSP_NORSTR_SIZE];
+ unsigned int spcount;
+ char srvpoints[OSP_MAX_SRVS][OSP_NORSTR_SIZE];
int maxconnections;
int retrydelay;
int retrylimit;
int timeout;
+ char source[OSP_NORSTR_SIZE];
+ enum osp_authpolicy authpolicy;
OSPTPROVHANDLE handle;
struct osp_provider *next;
};
-static struct osp_provider *providers;
-static int osp_build(struct ast_config *cfg, char *cat)
+AST_MUTEX_DEFINE_STATIC(osplock);
+static unsigned int osp_usecount = 0;
+static int osp_initialized = 0;
+static int osp_hardware = 0;
+static struct osp_provider* ospproviders = NULL;
+static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED;
+
+static int osp_buildProvider(
+ struct ast_config* cfg, /* OSP configuration */
+ char* provider); /* OSP provider context name */
+static int osp_getPolicy(
+ const char* provider, /* OSP provider context name */
+ int* policy); /* OSP authentication policy, output */
+static int osp_genTransaction(
+ const char* provider, /* OSP provider context name */
+ int* transaction, /* OSP transaction handle, output */
+ unsigned int sourcesize, /* Size of source buffer, in/output */
+ char* source); /* Source of provider context, output */
+static int osp_valToken(
+ int transaction, /* OSP transaction handle */
+ const char* source, /* Source of in_bound call */
+ const char* dest, /* Destination of in_bound call */
+ const char* calling, /* Calling number */
+ const char* called, /* Called number */
+ const char* token, /* OSP token, may be empty */
+ unsigned int* timelimit); /* Call duration limit, output */
+static unsigned int osp_choTimelimit(
+ unsigned int in, /* In_bound OSP timelimit */
+ unsigned int out); /* Out_bound OSP timelimit */
+static enum OSPEFAILREASON reason2cause(
+ int reason); /* Last call failure reason */
+static int osp_chkDest(
+ const char* callednum, /* Called number */
+ const char* callingnum, /* Calling number */
+ char* destination, /* Destination IP in OSP format */
+ unsigned int tokenlen, /* OSP token length */
+ const char* token, /* OSP token */
+ enum OSPEFAILREASON* cause, /* Failure cause, output */
+ struct ast_osp_result* result); /* OSP lookup results, in/output */
+
+static int osp_load(void);
+static int osp_unload(void);
+static int osp_show(int fd, int argc, char *argv[]);
+
+static int osp_buildProvider(
+ struct ast_config *cfg, /* OSP configuration */
+ char* provider) /* OSP provider context name */
{
- OSPTCERT TheAuthCert[MAX_CERTS];
- unsigned char Reqbuf[4096],LocalBuf[4096],AuthBuf[MAX_CERTS][4096];
- struct ast_variable *v;
- struct osp_provider *osp;
- int x,length,errorcode=0;
- int mallocd=0,i;
- char *cacerts[MAX_CERTS];
- const char *servicepoints[MAX_SERVICEPOINTS];
+ int res;
+ unsigned int t, i, j;
+ struct osp_provider* p;
+ struct ast_variable* v;
OSPTPRIVATEKEY privatekey;
OSPTCERT localcert;
- OSPTCERT *authCerts[MAX_CERTS];
+ const char* psrvpoints[OSP_MAX_SRVS];
+ OSPTCERT cacerts[OSP_MAX_CERTS];
+ const OSPTCERT* pcacerts[OSP_MAX_CERTS];
+ int error = OSPC_ERR_NO_ERROR;
-
-
- ast_mutex_lock(&osplock);
- osp = providers;
- while(osp) {
- if (!strcasecmp(osp->name, cat))
- break;
- osp = osp->next;
+ p = ast_calloc(1, sizeof(*p));
+ if (!p) {
+ ast_log(LOG_ERROR, "Out of memory\n");
+ return(-1);
}
- ast_mutex_unlock(&osplock);
- if (!osp) {
- mallocd = 1;
- if (!(osp = ast_calloc(1, sizeof(*osp)))) {
- return -1;
- }
- osp->handle = -1;
- }
- ast_copy_string(osp->name, cat, sizeof(osp->name));
- snprintf(osp->localpvtkey, sizeof(osp->localpvtkey) ,"%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, cat);
- snprintf(osp->localcert, sizeof(osp->localpvtkey), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, cat);
- osp->maxconnections=OSP_DEFAULT_MAX_CONNECTIONS;
- osp->retrydelay = OSP_DEFAULT_RETRY_DELAY;
- osp->retrylimit = OSP_DEFAULT_RETRY_LIMIT;
- osp->timeout = OSP_DEFAULT_TIMEOUT;
- osp->source[0] = '\0';
- ast_log(LOG_DEBUG, "Building OSP Provider '%s'\n", cat);
- v = ast_variable_browse(cfg, cat);
+
+ ast_copy_string(p->name, provider, sizeof(p->name));
+ p->handle = OSP_INVALID_HANDLE;
+ snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, provider);
+ snprintf(p->localcert, sizeof(p->localcert), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, provider);
+ p->maxconnections = OSP_DEF_MAXCONNECTIONS;
+ p->retrydelay = OSP_DEF_RETRYDELAY;
+ p->retrylimit = OSP_DEF_RETRYLIMIT;
+ p->timeout = OSP_DEF_TIMEOUT;
+ p->authpolicy = OSP_DEF_AUTHPOLICY;
+
+ v = ast_variable_browse(cfg, provider);
while(v) {
if (!strcasecmp(v->name, "privatekey")) {
- if (v->value[0] == '/')
- ast_copy_string(osp->localpvtkey, v->value, sizeof(osp->localpvtkey));
- else
- snprintf(osp->localpvtkey, sizeof(osp->localpvtkey), "%s/%s", ast_config_AST_KEY_DIR , v->value);
+ if (v->value[0] == '/') {
+ ast_copy_string(p->privatekey, v->value, sizeof(p->privatekey));
+ } else {
+ snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s", ast_config_AST_KEY_DIR, v->value);
+ }
+ ast_log(LOG_DEBUG, "OSP: privatekey '%s'\n", p->privatekey);
} else if (!strcasecmp(v->name, "localcert")) {
- if (v->value[0] == '/')
- ast_copy_string(osp->localcert, v->value, sizeof(osp->localcert));
- else
- snprintf(osp->localcert, sizeof(osp->localcert), "%s/%s", ast_config_AST_KEY_DIR, v->value);
+ if (v->value[0] == '/') {
+ ast_copy_string(p->localcert, v->value, sizeof(p->localcert));
+ } else {
+ snprintf(p->localcert, sizeof(p->localcert), "%s/%s", ast_config_AST_KEY_DIR, v->value);
+ }
+ ast_log(LOG_DEBUG, "OSP: localcert '%s'\n", p->localcert);
} else if (!strcasecmp(v->name, "cacert")) {
- if (osp->cacount < MAX_CERTS) {
- if (v->value[0] == '/')
- ast_copy_string(osp->cacerts[osp->cacount], v->value, sizeof(osp->cacerts[0]));
- else
- snprintf(osp->cacerts[osp->cacount], sizeof(osp->cacerts[0]), "%s/%s", ast_config_AST_KEY_DIR, v->value);
- osp->cacount++;
- } else
- ast_log(LOG_WARNING, "Too many CA Certificates at line %d\n", v->lineno);
+ if (p->cacount < OSP_MAX_CERTS) {
+ if (v->value[0] == '/') {
+ ast_copy_string(p->cacerts[p->cacount], v->value, sizeof(p->cacerts[0]));
+ } else {
+ snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s", ast_config_AST_KEY_DIR, v->value);
+ }
+ ast_log(LOG_DEBUG, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
+ p->cacount++;
+ } else {
+ ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", v->lineno);
+ }
} else if (!strcasecmp(v->name, "servicepoint")) {
- if (osp->spcount < MAX_SERVICEPOINTS) {
- ast_copy_string(osp->servicepoints[osp->spcount], v->value, sizeof(osp->servicepoints[0]));
- osp->spcount++;
- } else
- ast_log(LOG_WARNING, "Too many Service points at line %d\n", v->lineno);
+ if (p->spcount < OSP_MAX_SRVS) {
+ ast_copy_string(p->srvpoints[p->spcount], v->value, sizeof(p->srvpoints[0]));
+ ast_log(LOG_DEBUG, "OSP: servicepoint[%d]: '%s'\n", p->spcount, p->srvpoints[p->spcount]);
+ p->spcount++;
+ } else {
+ ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", v->lineno);
+ }
} else if (!strcasecmp(v->name, "maxconnections")) {
- if ((sscanf(v->value, "%d", &x) == 1) && (x > 0) && (x <= 1000)) {
- osp->maxconnections = x;
- } else
- ast_log(LOG_WARNING, "maxconnections should be an integer from 1 to 1000, not '%s' at line %d\n", v->value, v->lineno);
+ if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_MAXCONNECTIONS) && (t <= OSP_MAX_MAXCONNECTIONS)) {
+ p->maxconnections = t;
+ ast_log(LOG_DEBUG, "OSP: maxconnections '%d'\n", t);
+ } else {
+ ast_log(LOG_WARNING, "OSP: maxconnections should be an integer from %d to %d, not '%s' at line %d\n",
+ OSP_MIN_MAXCONNECTIONS, OSP_MAX_MAXCONNECTIONS, v->value, v->lineno);
+ }
} else if (!strcasecmp(v->name, "retrydelay")) {
- if ((sscanf(v->value, "%d", &x) == 1) && (x >= 0) && (x <= 10)) {
- osp->retrydelay = x;
- } else
- ast_log(LOG_WARNING, "retrydelay should be an integer from 0 to 10, not '%s' at line %d\n", v->value, v->lineno);
+ if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_RETRYDELAY) && (t <= OSP_MAX_RETRYDELAY)) {
+ p->retrydelay = t;
+ ast_log(LOG_DEBUG, "OSP: retrydelay '%d'\n", t);
+ } else {
+ ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n",
+ OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY, v->value, v->lineno);
+ }
} else if (!strcasecmp(v->name, "retrylimit")) {
- if ((sscanf(v->value, "%d", &x) == 1) && (x >= 0) && (x <= 100)) {
- osp->retrylimit = x;
- } else
- ast_log(LOG_WARNING, "retrylimit should be an integer from 0 to 100, not '%s' at line %d\n", v->value, v->lineno);
+ if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_RETRYLIMIT) && (t <= OSP_MAX_RETRYLIMIT)) {
+ p->retrylimit = t;
+ ast_log(LOG_DEBUG, "OSP: retrylimit '%d'\n", t);
+ } else {
+ ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n",
+ OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT, v->value, v->lineno);
+ }
} else if (!strcasecmp(v->name, "timeout")) {
- if ((sscanf(v->value, "%d", &x) == 1) && (x >= 200) && (x <= 10000)) {
- osp->timeout = x;
- } else
- ast_log(LOG_WARNING, "timeout should be an integer from 200 to 10000, not '%s' at line %d\n", v->value, v->lineno);
+ if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_TIMEOUT) && (t <= OSP_MAX_TIMEOUT)) {
+ p->timeout = t;
+ ast_log(LOG_DEBUG, "OSP: timeout '%d'\n", t);
+ } else {
+ ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n",
+ OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT, v->value, v->lineno);
+ }
} else if (!strcasecmp(v->name, "source")) {
- ast_copy_string(osp->source, v->value, sizeof(osp->source));
+ ast_copy_string(p->source, v->value, sizeof(p->source));
+ ast_log(LOG_DEBUG, "OSP: source '%s'\n", p->source);
+ } else if (!strcasecmp(v->name, "authpolicy")) {
+ if ((sscanf(v->value, "%d", &t) == 1) && ((t == OSP_AUTH_NO) || (t == OSP_AUTH_YES) || (t == OSP_AUTH_EXCLUSIVE))) {
+ p->authpolicy = t;
+ ast_log(LOG_DEBUG, "OSP: authpolicy '%d'\n", t);
+ } else {
+ ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n",
+ OSP_AUTH_NO, OSP_AUTH_YES, OSP_AUTH_EXCLUSIVE, v->value, v->lineno);
+ }
}
v = v->next;
}
- if (osp->cacount < 1) {
- snprintf(osp->cacerts[osp->cacount], sizeof(osp->cacerts[0]), "%s/%s-cacert.pem", ast_config_AST_KEY_DIR, cat);
- osp->cacount++;
+
+ error = OSPPUtilLoadPEMPrivateKey(p->privatekey, &privatekey);
+ if (error != OSPC_ERR_NO_ERROR) {
+ ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s'\n", p->privatekey);
+ free(p);
+ return(-1);
}
- for (x=0;x<osp->cacount;x++)
- cacerts[x] = osp->cacerts[x];
- for (x=0;x<osp->spcount;x++)
- servicepoints[x] = osp->servicepoints[x];
-
- ast_mutex_lock(&osplock);
- osp->dead = 0;
- if (osp->handle > -1) {
- ast_log(LOG_DEBUG, "Deleting old handle for '%s'\n", osp->name);
- OSPPProviderDelete(osp->handle, 0);
- }
-
-
- length = 0;
- ast_log(LOG_DEBUG, "Loading private key for '%s' (%s)\n", osp->name, osp->localpvtkey);
- errorcode = loadPemPrivateKey(osp->localpvtkey,Reqbuf,&length);
- if (errorcode == 0)
- {
- privatekey.PrivateKeyData = Reqbuf;
- privatekey.PrivateKeyLength = length;
- }
- else
- {
- return -1;
- }
-
- length = 0;
- ast_log(LOG_DEBUG, "Loading local cert for '%s' (%s)\n", osp->name, osp->localcert);
- errorcode = loadPemCert(osp->localcert,LocalBuf,&length);
- if (errorcode == 0)
- {
- localcert.CertData = LocalBuf;
- localcert.CertDataLength = length;
- }
- else
- {
- return -1;
- }
-
- for (i=0;i<osp->cacount;i++)
- {
- length = 0;
- ast_log(LOG_DEBUG, "Loading CA cert %d for '%s' (%s)\n", i + 1, osp->name, osp->cacerts[i]);
- errorcode = loadPemCert(osp->cacerts[i],AuthBuf[i],&length);
- if (errorcode == 0)
- {
- TheAuthCert[i].CertData = AuthBuf[i];
- TheAuthCert[i].CertDataLength = length;
- authCerts[i] = &(TheAuthCert[i]);
- }
- else
- {
- return -1;
+
+ error = OSPPUtilLoadPEMCert(p->localcert, &localcert);
+ if (error != OSPC_ERR_NO_ERROR) {
+ ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s'\n", p->localcert);
+ if (privatekey.PrivateKeyData) {
+ free(privatekey.PrivateKeyData);
}
- }
-
- ast_log(LOG_DEBUG, "Creating provider handle for '%s'\n", osp->name);
-
- ast_log(LOG_DEBUG, "Service point '%s %d'\n", servicepoints[0], osp->spcount);
-
- if (OSPPProviderNew(osp->spcount,
- servicepoints,
- NULL,
- "localhost",
- &privatekey,
- &localcert,
- osp->cacount,
- (const OSPTCERT **)authCerts,
- 1,
- 300,
- osp->maxconnections,
- 1,
- osp->retrydelay,
- osp->retrylimit,
- osp->timeout,
- "",
- "",
- &osp->handle)) {
- ast_log(LOG_WARNING, "Unable to initialize provider '%s'\n", cat);
- osp->dead = 1;
+ free(p);
+ return(-1);
+ }
+
+ if (p->cacount < 1) {
+ snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s-cacert.pem", ast_config_AST_KEY_DIR, provider);
+ ast_log(LOG_DEBUG, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
+ p->cacount++;
+ }
+ for (i = 0; i < p->cacount; i++) {
+ error = OSPPUtilLoadPEMCert(p->cacerts[i], &cacerts[i]);
+ if (error != OSPC_ERR_NO_ERROR) {
+ ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s'\n", p->cacerts[i]);
+ for (j = 0; j < i; j++) {
+ if (cacerts[j].CertData) {
+ free(cacerts[j].CertData);
+ }
+ }
+ if (localcert.CertData) {
+ free(localcert.CertData);
+ }
+ if (privatekey.PrivateKeyData) {
+ free(privatekey.PrivateKeyData);
+ }
+ free(p);
+ return(-1);
+ }
+ pcacerts[i] = &cacerts[i];
}
- if (mallocd) {
- osp->next = providers;
- providers = osp;
+ for (i = 0; i < p->spcount; i++) {
+ psrvpoints[i] = p->srvpoints[i];
}
- ast_mutex_unlock(&osplock);
- return 0;
-}
-static int show_osp(int fd, int argc, char *argv[])
-{
- struct osp_provider *osp;
- char *search = NULL;
- int x;
- int found = 0;
- char *tokenalgo;
-
- if ((argc < 2) || (argc > 3))
- return RESULT_SHOWUSAGE;
- if (argc > 2)
- search = argv[2];
- if (!search) {
- switch (tokenformat) {
- case TOKEN_ALGO_BOTH:
- tokenalgo = "Both";
- break;
- case TOKEN_ALGO_UNSIGNED:
- tokenalgo = "Unsigned";
- break;
- case TOKEN_ALGO_SIGNED:
- default:
- tokenalgo = "Signed";
- break;
- }
- ast_cli(fd, "OSP: %s %s %s\n", initialized ? "Initialized" : "Uninitialized", hardware ? "Accelerated" : "Normal", tokenalgo);
+ error = OSPPProviderNew(
+ p->spcount, psrvpoints,
+ NULL,
+ OSP_AUDIT_URL,
+ &privatekey,
+ &localcert,
+ p->cacount, pcacerts,
+ OSP_LOCAL_VALIDATION,
+ OSP_SSL_LIFETIME,
+ p->maxconnections,
+ OSP_HTTP_PERSISTENCE,
+ p->retrydelay,
+ p->retrylimit,
+ p->timeout,
+ OSP_CUSTOMER_ID,
+ OSP_DEVICE_ID,
+ &p->handle);
+ if (error != OSPC_ERR_NO_ERROR) {
+ ast_log(LOG_WARNING, "OSP: Unable to initialize provider '%s'\n", provider);
+ free(p);
+ res = -1;
+ } else {
+ ast_log(LOG_DEBUG, "OSP: provider '%s'\n", provider);
+ ast_mutex_lock(&osplock);
+ p->next = ospproviders;
+ ospproviders = p;
+ ast_mutex_unlock(&osplock);
+ res = 0;
}
- ast_mutex_lock(&osplock);
- osp = providers;
- while(osp) {
- if (!search || !strcasecmp(osp->name, search)) {
- if (found)
- ast_cli(fd, "\n");
- ast_cli(fd, " == OSP Provider '%s' ==\n", osp->name);
- ast_cli(fd, "Local Private Key: %s\n", osp->localpvtkey);
- ast_cli(fd, "Local Certificate: %s\n", osp->localcert);
- for (x=0;x<osp->cacount;x++)
- ast_cli(fd, "CA Certificate %d: %s\n", x + 1, osp->cacerts[x]);
- for (x=0;x<osp->spcount;x++)
- ast_cli(fd, "Service Point %d: %s\n", x + 1, osp->servicepoints[x]);
- ast_cli(fd, "Max Connections: %d\n", osp->maxconnections);
- ast_cli(fd, "Retry Delay: %d seconds\n", osp->retrydelay);
- ast_cli(fd, "Retry Limit: %d\n", osp->retrylimit);
- ast_cli(fd, "Timeout: %d milliseconds\n", osp->timeout);
- ast_cli(fd, "Source: %s\n", strlen(osp->source) ? osp->source : "<unspecified>");
- ast_cli(fd, "OSP Handle: %d\n", osp->handle);
- found++;
+ for (i = 0; i < p->cacount; i++) {
+ if (cacerts[i].CertData) {
+ free(cacerts[i].CertData);
}
- osp = osp->next;
}
- ast_mutex_unlock(&osplock);
- if (!found) {
- if (search)
- ast_cli(fd, "Unable to find OSP provider '%s'\n", search);
- else
- ast_cli(fd, "No OSP providers configured\n");
+ if (localcert.CertData) {
+ free(localcert.CertData);
+ }
+ if (privatekey.PrivateKeyData) {
+ free(privatekey.PrivateKeyData);
}
- return RESULT_SUCCESS;
-}
-
-/*----------------------------------------------*
- * Loads the Certificate *
- *----------------------------------------------*/
-static int loadPemCert(unsigned char *FileName, unsigned char *buffer, int *len)
-{
- int length = 0;
- unsigned char *temp;
- BIO *bioIn = NULL;
- X509 *cert=NULL;
- int retVal = OSPC_ERR_NO_ERROR;
-
- temp = buffer;
- bioIn = BIO_new_file((const char*)FileName,"r");
- if (bioIn == NULL)
- {
- ast_log(LOG_WARNING,"Failed to find the File - %s \n",FileName);
- return -1;
- }
- else
- {
- cert = PEM_read_bio_X509(bioIn,NULL,NULL,NULL);
- if (cert == NULL)
- {
- ast_log(LOG_WARNING,"Failed to parse the Certificate from the File - %s \n",FileName);
- return -1;
- }
- else
- {
- length = i2d_X509(cert,&temp);
- if (cert == 0)
- {
- ast_log(LOG_WARNING,"Failed to parse the Certificate from the File - %s, Length=0 \n",FileName);
- return -1;
- }
- else
- {
- *len = length;
- }
- }
- }
-
- if (bioIn != NULL)
- {
- BIO_free(bioIn);
- }
-
- if (cert != NULL)
- {
- X509_free(cert);
- }
- return retVal;
+ return(res);
}
-/*----------------------------------------------*
- * Loads the Private Key *
- *----------------------------------------------*/
-static int loadPemPrivateKey(unsigned char *FileName, unsigned char *buffer, int *len)
+static int osp_getPolicy(
+ const char* provider, /* OSP provider context name */
+ int* policy) /* OSP authentication policy, output */
{
- int length = 0;
- unsigned char *temp;
- BIO *bioIn = NULL;
- RSA *pKey = NULL;
- int retVal = OSPC_ERR_NO_ERROR;
-
- temp = buffer;
-
- bioIn = BIO_new_file((const char*)FileName,"r");
- if (bioIn == NULL)
- {
- ast_log(LOG_WARNING,"Failed to find the File - %s \n",FileName);
- return -1;
- }
- else
- {
- pKey = PEM_read_bio_RSAPrivateKey(bioIn,NULL,NULL,NULL);
- if (pKey == NULL)
- {
- ast_log(LOG_WARNING,"Failed to parse the Private Key from the File - %s \n",FileName);
- return -1;
- }
- else
- {
- length = i2d_RSAPrivateKey(pKey,&temp);
- if (length == 0)
- {
- ast_log(LOG_WARNING,"Failed to parse the Private Key from the File - %s, Length=0 \n",FileName);
- return -1;
- }
- else
- {
- *len = length;
- }
- }
- }
- if (bioIn != NULL)
- {
- BIO_free(bioIn);
- }
-
- if (pKey != NULL)
- {
- RSA_free(pKey);
- }
- return retVal;
+ int res = 0;
+ struct osp_provider* p;
+
+ ast_mutex_lock(&osplock);
+ p = ospproviders;
+ while(p) {
+ if (!strcasecmp(p->name, provider)) {
+ *policy = p->authpolicy;
+ ast_log(LOG_DEBUG, "OSP: authpolicy '%d'\n", *policy);
+ res = 1;
+ break;
+ }
+ p = p->next;
+ }
+ ast_mutex_unlock(&osplock);
+
+ return(res);
}
-int ast_osp_validate(char *provider, char *token, int *handle, unsigned int *timelimit, const char *callerid, struct in_addr addr, const char *extension)
+static int osp_genTransaction(
+ const char* provider, /* OSP provider context name */
+ int* transaction, /* OSP transaction handle, output */
+ unsigned int sourcesize, /* Size of source buffer, in/output */
+ char* source) /* Source of provider context, output */
{
- char tmp[256]="", *l, *n;
- char iabuf[INET_ADDRSTRLEN];
- char source[OSP_MAX] = ""; /* Same length as osp->source */
- char *token2;
- int tokenlen;
- struct osp_provider *osp;
int res = 0;
- unsigned int authorised, dummy;
-
- if (!provider || !strlen(provider))
- provider = "default";
-
- token2 = ast_strdupa(token);
- if (!token2)
- return -1;
- tokenlen = ast_base64decode(token2, token, strlen(token));
- *handle = -1;
- if (!callerid)
- callerid = "";
- ast_copy_string(tmp, callerid, sizeof(tmp));
- ast_callerid_parse(tmp, &n, &l);
- if (!l)
- l = "";
- else {
- ast_shrink_phone_number(l);
- if (!ast_isphonenumber(l))
- l = "";
- }
- callerid = l;
+ struct osp_provider *p;
+ int error;
+
ast_mutex_lock(&osplock);
- ast_inet_ntoa(iabuf, sizeof(iabuf), addr);
- osp = providers;
- while(osp) {
- if (!strcasecmp(osp->name, provider)) {
- if (OSPPTransactionNew(osp->handle, handle)) {
- ast_log(LOG_WARNING, "Unable to create OSP Transaction handle!\n");
- } else {
- ast_copy_string(source, osp->source, sizeof(source));
+ p = ospproviders;
+ while(p) {
+ if (!strcasecmp(p->name, provider)) {
+ error = OSPPTransactionNew(p->handle, transaction);
+ if (error == OSPC_ERR_NO_ERROR) {
+ ast_log(LOG_DEBUG, "OSP: transaction '%d'\n", *transaction);
+ ast_copy_string(source, p->source, sourcesize);
+ ast_log(LOG_DEBUG, "OSP: source '%s'\n", source);
res = 1;
+ } else {
+ *transaction = OSP_INVALID_HANDLE;
+ ast_log(LOG_WARNING, "OSP: Unable to create transaction handle\n");
+ res = -1;
}
break;
}
- osp = osp->next;
+ p = p->next;
}
ast_mutex_unlock(&osplock);
- if (res) {
- res = 0;
- dummy = 0;
- if (!OSPPTransactionValidateAuthorisation(*handle, iabuf, source, NULL, NULL,
- callerid, OSPC_E164, extension, OSPC_E164, 0, "", tokenlen, token2, &authorised, timelimit, &dummy, NULL, tokenformat)) {
- if (authorised) {
- ast_log(LOG_DEBUG, "Validated token for '%s' from '%s@%s'\n", extension, callerid, iabuf);
+
+ return(res);
+}
+
+static int osp_valToken(
+ int transaction, /* OSP transaction handle */
+ const char* source, /* Source of in_bound call */
+ const char* dest, /* Destination of in_bound call */
+ const char* calling, /* Calling number */
+ const char* called, /* Called number */
+ const char* token, /* OSP token, may be empty */
+ unsigned int* timelimit) /* Call duration limit, output */
+{
+ int res = 0;
+ char tokenstr[OSP_TOKSTR_SIZE];
+ int tokenlen;
+ unsigned int authorised;
+ unsigned int dummy = 0;
+ int error;
+
+ tokenlen = ast_base64decode(tokenstr, token, strlen(token));
+ error = OSPPTransactionValidateAuthorisation(
+ transaction,
+ source, dest, NULL, NULL,
+ calling ? calling : "", OSPC_E164,
+ called, OSPC_E164,
+ 0, NULL,
+ tokenlen, tokenstr,
+ &authorised,
+ timelimit,
+ &dummy, NULL,
+ osp_tokenformat);
+ if (error == OSPC_ERR_NO_ERROR) {
+ if (authorised) {
+ ast_log(LOG_DEBUG, "OSP: Authorised\n");
+ res = 1;
+ }
+ }
+ return(res);
+}
+
+int ast_osp_auth(
+ const char* provider, /* OSP provider context name */
+ int* transaction, /* OSP transaction handle, output */
+ const char* source, /* Source of in_bound call */
+ const char* calling, /* Calling number */
+ const char* called, /* Called number */
+ const char* token, /* OSP token, may be empty */
+ unsigned int* timelimit) /* Call duration limit, output */
+{
+ int res;
+ char dest[OSP_NORSTR_SIZE];
+ int policy = OSP_AUTH_YES;
+
+ *transaction = OSP_INVALID_HANDLE;
+ *timelimit = OSP_DEF_TIMELIMIT;
+
+ res = osp_getPolicy(provider, &policy);
+ if (!res) {
+ ast_log(LOG_WARNING, "OSP: Unabe to find authentication policy\n");
+ return(-1);
+ }
+
+ switch (policy) {
+ case OSP_AUTH_NO:
+ res = 1;
+ break;
+ case OSP_AUTH_EXCLUSIVE:
+ if (ast_strlen_zero(token)) {
+ res = 0;
+ } else if ((res = osp_genTransaction(provider, transaction, sizeof(dest), dest)) <= 0) {
+ *transaction = OSP_INVALID_HANDLE;
+ ast_log(LOG_WARNING, "OSP: Unable to generate transaction handle\n");
+ res = -1;
+ } else {
+ res = osp_valToken(*transaction, source, dest, calling, called, token, timelimit);
+ }
+ break;
+ case OSP_AUTH_YES:
+ default:
+ if (ast_strlen_zero(token)) {
res = 1;
+ } else if ((res = osp_genTransaction(provider, transaction, sizeof(dest), dest)) <= 0) {
+ *transaction = OSP_INVALID_HANDLE;
+ ast_log(LOG_WARNING, "OSP: Unable to generate transaction handle\n");
+ res = -1;
+ } else {
+ res = osp_valToken(*transaction, source, dest, calling, called, token, timelimit);
}
- }
+ break;
+ }
+
+ if (!res) {
+ OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
+ }
+
+ return(res);
+}
+
+static unsigned int osp_choTimelimit(
+ unsigned int in, /* In_bound OSP timelimit */
+ unsigned int out) /* Out_bound OSP timelimit */
+{
+ if (in == OSP_DEF_TIMELIMIT) {
+ return (out);
+ } else if (out == OSP_DEF_TIMELIMIT) {
+ return (in);
+ } else {
+ return(in < out ? in : out);
}
- return res;
}
-static int check_dest(struct ast_osp_result *result, char *token, int tokensize)
+static int osp_chkDest(
+ const char* callednum, /* Called number */
+ const char* callingnum, /* Calling number */
+ char* destination, /* Destination IP in OSP format */
+ unsigned int tokenlen, /* OSP token length */
+ const char* token, /* OSP token */
+ enum OSPEFAILREASON* cause, /* Failure cause, output */
+ struct ast_osp_result* result) /* OSP lookup results, in/output */
{
+ int res = 0;
OSPE_DEST_OSP_ENABLED enabled;
- OSPE_DEST_PROT prot;
- int res = 1;
+ OSPE_DEST_PROT protocol;
+ int error;
- /* Check destination OSP version */
- if (!OSPPTransactionIsDestOSPEnabled(result->handle, &enabled) && (enabled == OSPE_OSP_FALSE)) {
- result->token[0] = 0;
+ if (strlen(destination) <= 2) {
+ *cause = OSPC_FAIL_INCOMPATIBLE_DEST;
} else {
- ast_base64encode(result->token, token, tokensize, sizeof(result->token) - 1);
- }
-
- /* Check destination protocol */
- if (OSPPTransactionGetDestProtocol(result->handle, &prot)) {
- prot = OSPE_DEST_PROT_UNDEFINED;
- }
- switch(prot) {
- case OSPE_DEST_PROT_UNDEFINED: /* Protocol is not configured, use SIP as default */
- case OSPE_DEST_PROT_SIP:
- ast_copy_string(result->tech, "SIP", sizeof(result->tech));
- break;
- case OSPE_DEST_PROT_H323_SETUP:
- ast_copy_string(result->tech, "H323", sizeof(result->tech));
- break;
- case OSPE_DEST_PROT_IAX:
- ast_copy_string(result->tech, "IAX", sizeof(result->tech));
- break;
- case OSPE_DEST_PROT_H323_LRQ:
- case OSPE_DEST_PROT_UNKNOWN:
- default:
- ast_log(LOG_DEBUG, "Unknown destination protocol '%d', skipping...\n", prot);
- res = 0;
- }
+ error = OSPPTransactionIsDestOSPEnabled(result->outhandle, &enabled);
+ if ((error == OSPC_ERR_NO_ERROR) && (enabled == OSPE_OSP_FALSE)) {
+ result->token[0] = '\0';
+ } else {
+ ast_base64encode(result->token, token, tokenlen, sizeof(result->token) - 1);
+ }
- return res;
+ error = OSPPTransactionGetDestProtocol(result->outhandle, &protocol);
+ if (error != OSPC_ERR_NO_ERROR) {
+ *cause = OSPC_FAIL_PROTOCOL_ERROR;
+ } else {
+ res = 1;
+ /* Strip leading and trailing brackets */
+ destination[strlen(destination) - 1] = '\0';
+ switch(protocol) {
+ case OSPE_DEST_PROT_H323_SETUP:
+ ast_copy_string(result->tech, "H323", sizeof(result->tech));
+ ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol);
+ snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
+ ast_copy_string(result->calling, callingnum, sizeof(result->calling));
+ break;
+ case OSPE_DEST_PROT_SIP:
+ ast_copy_string(result->tech, "SIP", sizeof(result->tech));
+ ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol);
+ snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
+ ast_copy_string(result->calling, callingnum, sizeof(result->calling));
+ break;
+ case OSPE_DEST_PROT_IAX:
+ ast_copy_string(result->tech, "IAX", sizeof(result->tech));
+ ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol);
+ snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
+ ast_copy_string(result->calling, callingnum, sizeof(result->calling));
+ break;
+ default:
+ ast_log(LOG_DEBUG, "OSP: Unknown protocol '%d'\n", protocol);
+ *cause = OSPC_FAIL_PROTOCOL_ERROR;
+ res = 0;
+ }
+ }
+ }
+ return(res);
}
-int ast_osp_lookup(struct ast_channel *chan, char *provider, char *extension, char *callerid, struct ast_osp_result *result)
+int ast_osp_lookup(
+ const char* provider, /* OSP provider conttext name */
+ const char* srcdev, /* Source device of out_bound call */
+ const char* calling, /* Calling number */
+ const char* called, /* Called number */
+ struct ast_osp_result* result) /* OSP lookup results, in/output */
{
- int cres;
- int res = 0;
- int counts;
- int tokenlen;
- unsigned int dummy=0;
- unsigned int timelimit;
+ int res;
+ char source[OSP_NORSTR_SIZE];
unsigned int callidlen;
- char callidstr[OSPC_CALLID_MAXSIZE] = "";
- struct osp_provider *osp;
- char source[OSP_MAX] = ""; /* Same length as osp->source */
- char callednum[2048]="";
- char callingnum[2048]="";
- char destination[2048]="";
- char token[2000];
- char tmp[256]="", *l, *n;
- const char *devinfo = NULL;
-
- result->handle = -1;
- result->numresults = 0;
+ char callidstr[OSPC_CALLID_MAXSIZE];
+ char callingnum[OSP_NORSTR_SIZE];
+ char callednum[OSP_NORSTR_SIZE];
+ char destination[OSP_NORSTR_SIZE];
+ unsigned int tokenlen;
+ char token[OSP_TOKSTR_SIZE];
+ unsigned int dummy = 0;
+ enum OSPEFAILREASON cause;
+ int error;
+
+ result->outhandle = OSP_INVALID_HANDLE;
result->tech[0] = '\0';
result->dest[0] = '\0';
+ result->calling[0] = '\0';
result->token[0] = '\0';
+ result->numresults = 0;
+ result->outtimelimit = OSP_DEF_TIMELIMIT;
- if (!provider || !strlen(provider))
- provider = "default";
-
- if (!callerid)
- callerid = "";
- ast_copy_string(tmp, callerid, sizeof(tmp));
- ast_callerid_parse(tmp, &n, &l);
- if (!l)
- l = "";
- else {
- ast_shrink_phone_number(l);
- if (!ast_isphonenumber(l))
- l = "";
+ if ((res = osp_genTransaction(provider, &result->outhandle, sizeof(source), source)) <= 0) {
+ result->outhandle = OSP_INVALID_HANDLE;
+ if (result->inhandle != OSP_INVALID_HANDLE) {
+ OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
+ }
+ ast_log(LOG_WARNING, "OSP: Unable to generate transaction handle\n");
+ return(-1);
}
- callerid = l;
- if (chan) {
- cres = ast_autoservice_start(chan);
- if (cres < 0)
- return cres;
+ res = 0;
+ dummy = 0;
+ result->numresults = OSP_DEF_DESTINATIONS;
+ error = OSPPTransactionRequestAuthorisation(
+ result->outhandle,
+ source, srcdev,
+ calling ? calling : "", OSPC_E164,
+ called, OSPC_E164,
+ NULL,
+ 0, NULL,
+ NULL,
+ &result->numresults,
+ &dummy, NULL);
+ if (error != OSPC_ERR_NO_ERROR) {
+ result->numresults = 0;
+ OSPPTransactionRecordFailure(result->outhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
+ if (result->inhandle != OSP_INVALID_HANDLE) {
+ OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
+ }
+ return(res);
}
- ast_mutex_lock(&osplock);
- osp = providers;
- while(osp) {
- if (!strcasecmp(osp->name, provider)) {
- if (OSPPTransactionNew(osp->handle, &result->handle)) {
- ast_log(LOG_WARNING, "Unable to create OSP Transaction handle!\n");
- } else {
- ast_copy_string(source, osp->source, sizeof(source));
- res = 1;
- }
- break;
+
+ if (!result->numresults) {
+ result->numresults = 0;
+ OSPPTransactionRecordFailure(result->outhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
+ if (result->inhandle != OSP_INVALID_HANDLE) {
+ OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
}
- osp = osp->next;
+ return(res);
}
- ast_mutex_unlock(&osplock);
- if (res) {
- res = 0;
- /* No more than 10 back */
- counts = 10;
- dummy = 0;
- devinfo = pbx_builtin_getvar_helper (chan, "OSPPEER");
- if (!devinfo) {
- devinfo = "";
+
+ callidlen = sizeof(callidstr);
+ tokenlen = sizeof(token);
+ error = OSPPTransactionGetFirstDestination(
+ result->outhandle,
+ 0, NULL, NULL,
+ &result->outtimelimit,
+ &callidlen, callidstr,
+ sizeof(callednum), callednum,
+ sizeof(callingnum), callingnum,
+ sizeof(destination), destination,
+ 0, NULL,
+ &tokenlen, token);
+ if (error != OSPC_ERR_NO_ERROR) {
+ result->token[0] = '\0';
+ result->numresults = 0;
+ result->outtimelimit = OSP_DEF_TIMELIMIT;
+ OSPPTransactionRecordFailure(result->outhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
+ if (result->inhandle != OSP_INVALID_HANDLE) {
+ OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
}
- if (!OSPPTransactionRequestAuthorisation(result->handle, source, devinfo,
- callerid,OSPC_E164, extension, OSPC_E164, NULL, 0, NULL, NULL, &counts, &dummy, NULL)) {
- if (counts) {
- tokenlen = sizeof(token);
- result->numresults = counts - 1;
+ ast_log(LOG_DEBUG, "OSP: Unable to get first route\n");
+ return(res);
+ }
+
+ do {
+ result->outtimelimit = osp_choTimelimit(result->intimelimit, result->outtimelimit);
+ ast_log(LOG_DEBUG, "OSP: outtimelimit '%d'\n", result->outtimelimit);
+ ast_log(LOG_DEBUG, "OSP: called '%s'\n", callednum);
+ ast_log(LOG_DEBUG, "OSP: calling '%s'\n", callingnum);
+ ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination);
+ ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen);
+
+ res = osp_chkDest(callednum, callingnum, destination, tokenlen, token, &cause, result);
+ if (!res) {
+ result->numresults--;
+ if (result->numresults) {
callidlen = sizeof(callidstr);
- if (!OSPPTransactionGetFirstDestination(result->handle, 0, NULL, NULL, &timelimit, &callidlen, callidstr,
- sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
- ast_log(LOG_DEBUG, "Got destination '%s' and called: '%s' calling: '%s' for '%s' (provider '%s')\n",
- destination, callednum, callingnum, extension, provider);
- /* Only support OSP server with only one duration limit */
- if (ast_channel_cmpwhentohangup (chan, timelimit) < 0) {
- ast_channel_setwhentohangup (chan, timelimit);
+ tokenlen = sizeof(token);
+ error = OSPPTransactionGetNextDestination(
+ result->outhandle,
+ cause,
+ 0, NULL, NULL,
+ &result->outtimelimit,
+ &callidlen, callidstr,
+ sizeof(callednum), callednum,
+ sizeof(callingnum), callingnum,
+ sizeof(destination), destination,
+ 0, NULL,
+ &tokenlen, token);
+ if (error != OSPC_ERR_NO_ERROR) {
+ result->token[0] = '\0';
+ result->numresults = 0;
+ result->outtimelimit = OSP_DEF_TIMELIMIT;
+ OSPPTransactionRecordFailure(result->outhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
+ if (result->inhandle != OSP_INVALID_HANDLE) {
+ OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
}
- do {
- if ((strlen(destination) > 2) && (check_dest(result, token, tokenlen))) {
- /* Strip leading and trailing brackets */
- destination[strlen(destination) - 1] = '\0';
- snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
- res = 1;
- } else {
- if(result->numresults) {
- result->numresults--;
- callidlen = sizeof(callidstr);
- if (!OSPPTransactionGetNextDestination(result->handle, OSPC_FAIL_INCOMPATIBLE_DEST, 0, NULL, NULL, &timelimit, &callidlen,
- callidstr, sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL,
- &tokenlen, token))
- {
- continue;
- }
- }
- }
- break;
- } while (1);
+ break;
+ }
+ } else {
+ result->token[0] = '\0';
+ result->numresults = 0;
+ result->outtimelimit = OSP_DEF_TIMELIMIT;
+ OSPPTransactionRecordFailure(result->outhandle, cause);
+ if (result->inhandle != OSP_INVALID_HANDLE) {
+ OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
}
}
+ } else {
+ result->numresults--;
}
- if (!res) {
- OSPPTransactionDelete(result->handle);
- result->handle = -1;
- }
-
- }
- if (!osp)
- ast_log(LOG_NOTICE, "OSP Provider '%s' does not exist!\n", provider);
- if (chan) {
- cres = ast_autoservice_stop(chan);
- if (cres < 0)
- return cres;
+ } while(!res && result->numresults);
+
+ return(res);
+}
+
+static enum OSPEFAILREASON reason2cause(
+ int reason) /* Last call failure reason */
+{
+ enum OSPEFAILREASON cause;
+
+ switch(reason) {
+ case AST_CAUSE_NOTDEFINED:
+ cause = OSPC_FAIL_NONE;
+ break;
+ case AST_CAUSE_BUSY:
+ cause = OSPC_FAIL_USER_BUSY;
+ break;
+ case AST_CAUSE_CONGESTION:
+ cause = OSPC_FAIL_SWITCHING_EQUIPMENT_CONGESTION;
+ break;
+ case AST_CAUSE_UNALLOCATED:
+ cause = OSPC_FAIL_UNALLOC_NUMBER;
+ break;
+ case AST_CAUSE_NOANSWER:
+ cause = OSPC_FAIL_NO_ANSWER_FROM_USER;
+ break;
+ case AST_CAUSE_NORMAL:
+ default:
+ cause = OSPC_FAIL_NORMAL_CALL_CLEARING;
+ break;
}
- return res;
+
+ return(cause);
}
-int ast_osp_next(struct ast_osp_result *result, int cause)
+int ast_osp_next(
+ int reason, /* Last desintaion failure reason */
+ struct ast_osp_result *result) /* OSP lookup results, output */
{
int res = 0;
- int tokenlen;
- unsigned int timelimit;
unsigned int callidlen;
- char callidstr[OSPC_CALLID_MAXSIZE] = "";
- char callednum[2048]="";
- char callingnum[2048]="";
- char destination[2048]="";
- char token[2000];
+ char callidstr[OSPC_CALLID_MAXSIZE];
+ char callingnum[OSP_NORSTR_SIZE];
+ char callednum[OSP_NORSTR_SIZE];
+ char destination[OSP_NORSTR_SIZE];
+ unsigned int tokenlen;
+ char token[OSP_TOKSTR_SIZE];
+ enum OSPEFAILREASON cause;
+ int error;
result->tech[0] = '\0';
result->dest[0] = '\0';
+ result->calling[0] = '\0';
result->token[0] = '\0';
+ result->outtimelimit = OSP_DEF_TIMELIMIT;
- if (result->handle > -1) {
- if (result->numresults) {
- tokenlen = sizeof(token);
- while(!res && result->numresults) {
- result->numresults--;
- callidlen = sizeof(callidstr);
- if (!OSPPTransactionGetNextDestination(result->handle, OSPC_FAIL_INCOMPATIBLE_DEST, 0, NULL, NULL, &timelimit, &callidlen, callidstr,
- sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token))
- {
- if ((strlen(destination) > 2) && check_dest(result, token, tokenlen)) {
- /* Strip leading and trailing brackets */
- destination[strlen(destination) - 1] = '\0';
- snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
- res = 1;
- }
- }
- }
+ if (result->outhandle == OSP_INVALID_HANDLE) {
+ result->numresults = 0;
+ if (result->inhandle != OSP_INVALID_HANDLE) {
+ OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
}
- if (!res) {
- OSPPTransactionDelete(result->handle);
- result->handle = -1;
+ ast_log(LOG_WARNING, "OSP: Transaction handle undefined\n");
+ return(-1);
+ }
+
+ cause = reason2cause(reason);
+ if (!result->numresults) {
+ OSPPTransactionRecordFailure(result->outhandle, cause);
+ if (result->inhandle != OSP_INVALID_HANDLE) {
+ OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
}
+ ast_log(LOG_DEBUG, "OSP: No more destination\n");
+ return(res);
}
- return res;
-}
-static enum OSPEFAILREASON cause2reason(int cause)
-{
- switch(cause) {
- case AST_CAUSE_BUSY:
- return OSPC_FAIL_USER_BUSY;
- case AST_CAUSE_CONGESTION:
- return OSPC_FAIL_SWITCHING_EQUIPMENT_CONGESTION;
- case AST_CAUSE_UNALLOCATED:
- return OSPC_FAIL_UNALLOC_NUMBER;
- case AST_CAUSE_NOTDEFINED:
- return OSPC_FAIL_NORMAL_UNSPECIFIED;
- case AST_CAUSE_NOANSWER:
- return OSPC_FAIL_NO_ANSWER_FROM_USER;
- case AST_CAUSE_NORMAL:
- default:
- return OSPC_FAIL_NORMAL_CALL_CLEARING;
+ while(!res && result->numresults) {
+ result->numresults--;
+ callidlen = sizeof(callidstr);
+ tokenlen = sizeof(token);
+ error = OSPPTransactionGetNextDestination(
+ result->outhandle,
+ cause,
+ 0, NULL, NULL,
+ &result->outtimelimit,
+ &callidlen, callidstr,
+ sizeof(callednum), callednum,
+ sizeof(callingnum), callingnum,
+ sizeof(destination), destination,
+ 0, NULL,
+ &tokenlen, token);
+ if (error == OSPC_ERR_NO_ERROR) {
+ result->outtimelimit = osp_choTimelimit(result->intimelimit, result->outtimelimit);
+ ast_log(LOG_DEBUG, "OSP: outtimelimit '%d'\n", result->outtimelimit);
+ ast_log(LOG_DEBUG, "OSP: called '%s'\n", callednum);
+ ast_log(LOG_DEBUG, "OSP: calling '%s'\n", callingnum);
+ ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination);
+ ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen);
+
+ res = osp_chkDest(callednum, callingnum, destination, tokenlen, token, &cause, result);
+ if (!res && !result->numresults) {
+ OSPPTransactionRecordFailure(result->outhandle, cause);
+ if (result->inhandle != OSP_INVALID_HANDLE) {
+ OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
+ }
+ }
+ } else {
+ result->token[0] = '\0';
+ result->numresults = 0;
+ result->outtimelimit = OSP_DEF_TIMELIMIT;
+ OSPPTransactionRecordFailure(result->outhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
+ if (result->inhandle != OSP_INVALID_HANDLE) {
+ OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
+ }
+ }
}
+
+ return(res);
}
-int ast_osp_terminate(int handle, int cause, time_t start, time_t duration)
+int ast_osp_finish(
+ int handle, /* OSP in/out_bound transaction handle */
+ int reason, /* Last destination failure reason */
+ time_t start, /* Call start time */
+ time_t connect, /* Call connect time */
+ time_t end) /* Call end time*/
{
+ int res = 1;
unsigned int dummy = 0;
- int res = -1;
- enum OSPEFAILREASON reason;
-
- time_t endTime = 0;
- time_t alertTime = 0;
- time_t connectTime = 0;
+ enum OSPEFAILREASON cause;
+ time_t alert = 0;
unsigned isPddInfoPresent = 0;
unsigned pdd = 0;
unsigned releaseSource = 0;
unsigned char *confId = "";
+ int error;
- reason = cause2reason(cause);
- if (OSPPTransactionRecordFailure(handle, reason))
- ast_log(LOG_WARNING, "Failed to record call termination for handle %d\n", handle);
- else if (OSPPTransactionReportUsage(handle, duration, start,
- endTime,alertTime,connectTime,isPddInfoPresent,pdd,releaseSource,confId,
- 0, 0, 0, 0, &dummy, NULL))
- ast_log(LOG_WARNING, "Failed to report duration for handle %d\n", handle);
- else {
- ast_log(LOG_DEBUG, "Completed recording handle %d\n", handle);
- OSPPTransactionDelete(handle);
+ if (handle == OSP_INVALID_HANDLE) {
+ return(res);
+ }
+
+ if ((cause = reason2cause(reason)) != OSPC_FAIL_NONE) {
+ OSPPTransactionRecordFailure(handle, cause);
+ }
+ error = OSPPTransactionReportUsage(
+ handle,
+ difftime(end, connect), start, end, alert, connect,
+ isPddInfoPresent, pdd,
+ releaseSource,
+ confId,
+ 0, 0, 0, 0,
+ &dummy, NULL);
+ if (error == OSPC_ERR_NO_ERROR) {
+ ast_log(LOG_DEBUG, "OSP: Usage reported\n");
+ res = 1;
+ } else {
+ ast_log(LOG_DEBUG, "OSP: Unable to report usage, error = %d\n", error);
res = 0;
}
- return res;
+ OSPPTransactionDelete(handle);
+
+ return(res);
}
-static int config_load(void)
+void ast_osp_adduse(void)
{
- struct ast_config *cfg;
- char *cat;
- struct osp_provider *osp, *prev = NULL, *next;
- ast_mutex_lock(&osplock);
- osp = providers;
- while(osp) {
- osp->dead = 1;
- osp = osp->next;
+ osp_usecount++;
+}
+
+void ast_osp_deluse(void)
+{
+ if (osp_usecount > 0) {
+ osp_usecount--;
}
- ast_mutex_unlock(&osplock);
- cfg = ast_config_load("osp.conf");
+}
+
+static char osp_usage[] =
+"Usage: show osp\n"
+" Displays information on Open Settlement Protocol support\n";
+
+static struct ast_cli_entry osp_cli = {
+ {"show", "osp", NULL},
+ osp_show,
+ "Displays OSP information",
+ osp_usage
+};
+
+static int osp_load(void)
+{
+ char* t;
+ unsigned int v;
+ struct ast_config* cfg;
+ int error = OSPC_ERR_NO_ERROR;
+
+ cfg = ast_config_load(OSP_CONFIG_FILE);
if (cfg) {
- if (!initialized) {
- cat = ast_variable_retrieve(cfg, "general", "accelerate");
- if (cat && ast_true(cat))
- if (OSPPInit(1)) {
- ast_log(LOG_WARNING, "Failed to enable hardware accelleration, falling back to software mode\n");
- OSPPInit(0);
- } else
- hardware = 1;
- else
+ t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate");
+ if (t && ast_true(t)) {
+ if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
+ ast_log(LOG_WARNING, "OSP: Unable to enable hardware accelleration\n");
OSPPInit(0);
- initialized = 1;
+ } else {
+ osp_hardware = 1;
+ }
+ } else {
+ OSPPInit(0);
}
- cat = ast_variable_retrieve(cfg, "general", "tokenformat");
- if (cat) {
- if ((sscanf(cat, "%d", &tokenformat) != 1) || (tokenformat < TOKEN_ALGO_SIGNED) || (tokenformat > TOKEN_ALGO_BOTH)) {
- tokenformat = TOKEN_ALGO_SIGNED;
- ast_log(LOG_WARNING, "tokenformat should be an integer from 0 to 2, not '%s'\n", cat);
+ ast_log(LOG_DEBUG, "OSP: osp_hardware '%d'\n", osp_hardware);
+
+ t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat");
+ if (t) {
+ if ((sscanf(t, "%d", &v) == 1) &&
+ ((v == TOKEN_ALGO_SIGNED) || (v == TOKEN_ALGO_UNSIGNED) || (v == TOKEN_ALGO_BOTH)))
+ {
+ osp_tokenformat = v;
+ } else {
+ ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n",
+ TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, t);
}
}
- cat = ast_category_browse(cfg, NULL);
- while(cat) {
- if (strcasecmp(cat, "general"))
- osp_build(cfg, cat);
- cat = ast_category_browse(cfg, cat);
+ ast_log(LOG_DEBUG, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
+
+ t = ast_category_browse(cfg, NULL);
+ while(t) {
+ if (strcasecmp(t, OSP_GENERAL_CAT)) {
+ osp_buildProvider(cfg, t);
+ }
+ t = ast_category_browse(cfg, t);
}
+
+ osp_initialized = 1;
+
ast_config_destroy(cfg);
- } else
- ast_log(LOG_NOTICE, "No OSP configuration found. OSP support disabled\n");
- ast_mutex_lock(&osplock);
- osp = providers;
- while(osp) {
- next = osp->next;
- if (osp->dead) {
- if (prev)
- prev->next = next;
- else
- providers = next;
- /* XXX Cleanup OSP structure first XXX */
- free(osp);
- } else
- prev = osp;
- osp = next;
+ } else {
+ ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
}
- ast_mutex_unlock(&osplock);
- return 0;
+ ast_log(LOG_DEBUG, "OSP: osp_initialized '%d'\n", osp_initialized);
+
+ return(0);
}
-static char show_osp_usage[] =
-"Usage: show osp\n"
-" Displays information on Open Settlement Protocol\n";
+static int osp_unload(void)
+{
+ struct osp_provider* p;
+ struct osp_provider* next;
+
+ if (osp_initialized) {
+ ast_mutex_lock(&osplock);
+ p = ospproviders;
+ while(p) {
+ next = p->next;
+ OSPPProviderDelete(p->handle, 0);
+ free(p);
+ p = next;
+ }
+ ospproviders = NULL;
+ ast_mutex_unlock(&osplock);
-static struct ast_cli_entry cli_show_osp =
-{ { "show", "osp", NULL }, show_osp, "Displays OSP information", show_osp_usage };
+ OSPPCleanup();
-int reload(void)
+ osp_usecount = 0;
+ osp_tokenformat = TOKEN_ALGO_SIGNED;
+ osp_hardware = 0;
+ osp_initialized = 0;
+ }
+ return(0);
+}
+
+static int osp_show(int fd, int argc, char *argv[])
{
- config_load();
- ast_log(LOG_NOTICE, "XXX Should reload OSP config XXX\n");
- return 0;
+ int i;
+ int found = 0;
+ struct osp_provider* p;
+ char* provider = NULL;
+ char* tokenalgo;
+
+ if ((argc < 2) || (argc > 3)) {
+ return(RESULT_SHOWUSAGE);
+ }
+ if (argc > 2) {
+ provider = argv[2];
+ }
+ if (!provider) {
+ switch (osp_tokenformat) {
+ case TOKEN_ALGO_BOTH:
+ tokenalgo = "Both";
+ break;
+ case TOKEN_ALGO_UNSIGNED:
+ tokenalgo = "Unsigned";
+ break;
+ case TOKEN_ALGO_SIGNED:
+ default:
+ tokenalgo = "Signed";
+ break;
+ }
+ ast_cli(fd, "OSP: %s %s %s\n",
+ osp_initialized ? "Initialized" : "Uninitialized", osp_hardware ? "Accelerated" : "Normal", tokenalgo);
+ }
+
+ ast_mutex_lock(&osplock);
+ p = ospproviders;
+ while(p) {
+ if (!provider || !strcasecmp(p->name, provider)) {
+ if (found) {
+ ast_cli(fd, "\n");
+ }
+ ast_cli(fd, " == OSP Provider '%s' == \n", p->name);
+ ast_cli(fd, "Local Private Key: %s\n", p->privatekey);
+ ast_cli(fd, "Local Certificate: %s\n", p->localcert);
+ for (i = 0; i < p->cacount; i++) {
+ ast_cli(fd, "CA Certificate %d: %s\n", i + 1, p->cacerts[i]);
+ }
+ for (i = 0; i < p->spcount; i++) {
+ ast_cli(fd, "Service Point %d: %s\n", i + 1, p->srvpoints[i]);
+ }
+ ast_cli(fd, "Max Connections: %d\n", p->maxconnections);
+ ast_cli(fd, "Retry Delay: %d seconds\n", p->retrydelay);
+ ast_cli(fd, "Retry Limit: %d\n", p->retrylimit);
+ ast_cli(fd, "Timeout: %d milliseconds\n", p->timeout);
+ ast_cli(fd, "Source: %s\n", strlen(p->source) ? p->source : "<unspecified>");
+ ast_cli(fd, "Auth Policy %d\n", p->authpolicy);
+ ast_cli(fd, "OSP Handle: %d\n", p->handle);
+ found++;
+ }
+ p = p->next;
+ }
+ ast_mutex_unlock(&osplock);
+
+ if (!found) {
+ if (provider) {
+ ast_cli(fd, "Unable to find OSP provider '%s'\n", provider);
+ } else {
+ ast_cli(fd, "No OSP providers configured\n");
+ }
+ }
+ return(RESULT_SUCCESS);
}
int load_module(void)
{
- config_load();
- ast_cli_register(&cli_show_osp);
- return 0;
+ osp_load();
+ ast_cli_register(&osp_cli);
+ return(0);
+}
+
+int reload(void)
+{
+ ast_cli_unregister(&osp_cli);
+ osp_unload();
+ osp_load();
+ ast_cli_register(&osp_cli);
+ return(0);
}
int unload_module(void)
{
- /* Can't unload this once we're loaded */
- return -1;
+ ast_cli_unregister(&osp_cli);
+ osp_unload();
+ return(0);
}
char *description(void)
{
- return "Open Settlement Protocol Support";
+ return("Open Settlement Protocol Support");
}
int usecount(void)
{
- /* We should never be unloaded */
- return 1;
+ return(osp_usecount);
}
char *key()
{
- return ASTERISK_GPL_KEY;
+ return(ASTERISK_GPL_KEY);
}
+