Merge "AST-2018-005: Fix tdata leaks when calling pjsip_endpt_send_response(2)"
[asterisk/asterisk.git] / apps / app_osplookup.c
index 72edda8..c42e187 100644 (file)
 /*** MODULEINFO
        <depend>osptk</depend>
        <depend>openssl</depend>
+       <support_level>extended</support_level>
  ***/
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
 #include <osp/osp.h>
 #include <osp/osputils.h>
 #include <osp/ospb64.h>
@@ -131,9 +130,15 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
                        <para>Looks up destination via OSP.</para>
                        <para>Input variables:</para>
                        <variablelist>
+                               <variable name="OSPINACTUALSRC">
+                                       <para>The actual source device IP address in indirect mode.</para>
+                               </variable>
                                <variable name="OSPINPEERIP">
                                        <para>The last hop IP address.</para>
                                </variable>
+                               <variable name="OSPINTECH">
+                                       <para>The inbound channel technology for the call.</para>
+                               </variable>
                                <variable name="OSPINHANDLE">
                                        <para>The inbound call OSP transaction handle.</para>
                                </variable>
@@ -173,12 +178,21 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
                                <variable name="OSPINTOHOST">
                                        <para>The inbound To header host part.</para>
                                </variable>
+                               <variable name="OSPINRPIDUSER">
+                                       <para>The inbound Remote-Party-ID header user part.</para>
+                               </variable>
+                               <variable name="OSPINPAIUSER">
+                                       <para>The inbound P-Asserted-Identify header user part.</para>
+                               </variable>
                                <variable name="OSPINDIVUSER">
                                        <para>The inbound Diversion header user part.</para>
                                </variable>
                                <variable name="OSPINDIVHOST">
                                        <para>The inbound Diversion header host part.</para>
                                </variable>
+                               <variable name="OSPINPCIUSER">
+                                       <para>The inbound P-Charge-Info header user part.</para>
+                               </variable>
                                <variable name="OSPINCUSTOMINFOn">
                                        <para>The inbound custom information, where <literal>n</literal> is the index beginning with <literal>1</literal>
                                        upto <literal>8</literal>.</para>
@@ -461,6 +475,12 @@ enum osp_authpolicy {
        OSP_AUTH_EXC            /* Only accept call with valid OSP token */
 };
 
+/* OSP Work Mode */
+enum osp_workmode {
+       OSP_MODE_DIRECT= 0,     /* Direct */
+       OSP_MODE_INDIRECT       /* Indirect */
+};
+
 /* OSP Service Type */
 enum osp_srvtype {
        OSP_SRV_VOICE = 0,      /* Normal voice service */
@@ -498,9 +518,10 @@ enum osp_srvtype {
 #define OSP_HTTP_PERSISTENCE   ((int)1)                                        /* In seconds */
 #define OSP_CUSTOMER_ID                        ((const char*)"")                       /* OSP customer ID */
 #define OSP_DEVICE_ID                  ((const char*)"")                       /* OSP device ID */
-#define OSP_DEF_MAXDESTS               ((unsigned int)5)                       /* OSP default max number of destinations */
+#define OSP_DEF_MAXDESTS               ((unsigned int)12)                      /* OSP default max number of destinations */
 #define OSP_DEF_TIMELIMIT              ((unsigned int)0)                       /* OSP default duration limit, no limit */
-#define OSP_DEF_PROTOCOL               OSP_PROT_SIP                            /* OSP default destination protocol, SIP */
+#define OSP_DEF_PROTOCOL               OSP_PROT_SIP                            /* OSP default signaling protocol, SIP */
+#define OSP_DEF_WORKMODE               OSP_MODE_DIRECT                         /* OSP default work mode, direct */
 #define OSP_DEF_SRVTYPE                        OSP_SRV_VOICE                           /* OSP default service type, voice */
 #define OSP_MAX_CUSTOMINFO             ((unsigned int)8)                       /* OSP max number of custom info */
 #define OSP_DEF_INTSTATS               ((int)-1)                                       /* OSP default int statistic */
@@ -522,8 +543,9 @@ struct osp_provider {
        unsigned int timeout;                                                   /* Timeout in ms */
        char source[OSP_SIZE_NORSTR];                                   /* IP of self */
        enum osp_authpolicy authpolicy;                                 /* OSP authentication policy */
-       const char* defprotocol;                                                /* OSP default destination protocol */
-       enum osp_srvtype srvtype;                                               /* OSP default service type */
+       const char* defprotocol;                                                /* OSP default signaling protocol */
+       enum osp_workmode workmode;                                             /* OSP work mode */
+       enum osp_srvtype srvtype;                                               /* OSP service type */
        struct osp_provider* next;                                              /* Pointer to next OSP provider */
 };
 
@@ -541,10 +563,13 @@ struct osp_npdata {
        const char* opname[OSPC_OPNAME_NUMBER]; /* Operator Names */
 };
 
-/* SIP Diversion Header Parameters */
-struct osp_diversion {
-       const char* user;                                               /* Diversion header user info */
-       const char* host;                                               /* Diversion header host info */
+/* SIP Header Parameters */
+struct osp_headers {
+       const char* rpiduser;                                   /* Remote-Party-ID header user info */
+       const char* paiuser;                                    /* P-Asserted-Identity header user info */
+       const char* divuser;                                    /* Diversion header user info */
+       const char* divhost;                                    /* Diversion header host info */
+       const char* pciuser;                                    /* P-Charge-Info header user info */
 };
 
 /* OSP Application In/Output Results */
@@ -553,7 +578,8 @@ struct osp_results {
        int outhandle;                                                                          /* Outbound transaction handle */
        unsigned int intimelimit;                                                       /* Inbound duration limit */
        unsigned int outtimelimit;                                                      /* Outbound duration limit */
-       char tech[OSP_SIZE_TECHSTR];                                            /* Outbound Asterisk TECH string */
+       char intech[OSP_SIZE_TECHSTR];                                          /* Inbound Asterisk TECH string */
+       char outtech[OSP_SIZE_TECHSTR];                                         /* Outbound Asterisk TECH string */
        char dest[OSP_SIZE_NORSTR];                                                     /* Outbound destination IP address */
        char calling[OSP_SIZE_NORSTR];                                          /* Outbound calling number, may be translated */
        char called[OSP_SIZE_NORSTR];                                           /* Outbound called number, may be translated */
@@ -586,14 +612,13 @@ struct osp_metrics {
        float min;                      /* Minimum */
        float max;                      /* Maximum */
        float avg;                      /* Average */
-       float ndev;                     /* Normal deviation */
        float sdev;                     /* Standard deviation */
 };
 
 /* OSP Module Global Variables */
 AST_MUTEX_DEFINE_STATIC(osp_lock);                                                     /* Lock of OSP provider list */
 static int osp_initialized = 0;                                                                /* Init flag */
-static int osp_hardware = 0;                                                           /* Hardware accelleration flag */
+static int osp_hardware = 0;                                                           /* Hardware acceleration flag */
 static int osp_security = 0;                                                           /* Using security features flag */
 static struct osp_provider* osp_providers = NULL;                      /* OSP provider list */
 static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED;       /* Token format supported */
@@ -645,6 +670,7 @@ static int osp_create_provider(
        provider->timeout = OSP_DEF_TIMEOUT;
        provider->authpolicy = OSP_DEF_AUTHPOLICY;
        provider->defprotocol = OSP_DEF_PROTOCOL;
+       provider->workmode = OSP_DEF_WORKMODE;
        provider->srvtype = OSP_DEF_SRVTYPE;
 
        for (var = ast_variable_browse(cfg, name); var != NULL; var = var->next) {
@@ -748,6 +774,14 @@ static int osp_create_provider(
                                ast_log(LOG_WARNING, "OSP: default protocol should be %s, %s, %s or %s not '%s' at line %d\n",
                                        OSP_PROT_SIP, OSP_PROT_H323, OSP_PROT_IAX, OSP_PROT_SKYPE, var->value, var->lineno);
                        }
+               } else if (!strcasecmp(var->name, "workmode")) {
+                       if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_MODE_DIRECT) || (num == OSP_MODE_INDIRECT))) {
+                               provider->workmode = num;
+                               ast_debug(1, "OSP: workmode '%d'\n", num);
+                       } else {
+                               ast_log(LOG_WARNING, "OSP: workmode should be %d or %d, not '%s' at line %d\n",
+                                       OSP_MODE_DIRECT, OSP_MODE_INDIRECT, var->value, var->lineno);
+                       }
                } else if (!strcasecmp(var->name, "servicetype")) {
                        if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_SRV_VOICE) || (num == OSP_SRV_NPQUERY))) {
                                provider->srvtype = num;
@@ -879,7 +913,7 @@ static int osp_get_provider(
        int res = OSP_FAILED;
        struct osp_provider* p;
 
-    *provider = NULL;
+       *provider = NULL;
 
        ast_mutex_lock(&osp_lock);
        for (p = osp_providers; p != NULL; p = p->next) {
@@ -1141,7 +1175,7 @@ static int osp_check_destination(
 {
        int res;
        OSPE_DEST_OSPENABLED enabled;
-       OSPE_DEST_PROTOCOL protocol;
+       OSPE_PROTOCOL_NAME protocol;
        char dest[OSP_SIZE_NORSTR];
        OSPE_OPERATOR_NAME type;
        int error;
@@ -1186,7 +1220,7 @@ static int osp_check_destination(
                if (error != OSPC_ERR_NO_ERROR) {
                        ast_debug(1, "OSP: Unable to get operator name of type '%d', error '%d'\n", type, error);
                        results->opname[type][0] = '\0';
-               } 
+               }
        }
 
        if ((error = OSPPTransactionGetDestProtocol(results->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
@@ -1206,48 +1240,48 @@ static int osp_check_destination(
        res = OSP_OK;
        osp_convert_outin(destination, dest, sizeof(dest));
        switch(protocol) {
-       case OSPC_DPROT_SIP:
+       case OSPC_PROTNAME_SIP:
                ast_debug(1, "OSP: protocol SIP\n");
-               ast_copy_string(results->tech, OSP_TECH_SIP, sizeof(results->tech));
+               ast_copy_string(results->outtech, OSP_TECH_SIP, sizeof(results->outtech));
                ast_copy_string(results->dest, dest, sizeof(results->dest));
                ast_copy_string(results->calling, calling, sizeof(results->calling));
                ast_copy_string(results->called, called, sizeof(results->called));
                break;
-       case OSPC_DPROT_Q931:
+       case OSPC_PROTNAME_Q931:
                ast_debug(1, "OSP: protocol Q.931\n");
-               ast_copy_string(results->tech, OSP_TECH_H323, sizeof(results->tech));
+               ast_copy_string(results->outtech, OSP_TECH_H323, sizeof(results->outtech));
                ast_copy_string(results->dest, dest, sizeof(results->dest));
                ast_copy_string(results->calling, calling, sizeof(results->calling));
                ast_copy_string(results->called, called, sizeof(results->called));
                break;
-       case OSPC_DPROT_IAX:
+       case OSPC_PROTNAME_IAX:
                ast_debug(1, "OSP: protocol IAX\n");
-               ast_copy_string(results->tech, OSP_TECH_IAX, sizeof(results->tech));
+               ast_copy_string(results->outtech, OSP_TECH_IAX, sizeof(results->outtech));
                ast_copy_string(results->dest, dest, sizeof(results->dest));
                ast_copy_string(results->calling, calling, sizeof(results->calling));
                ast_copy_string(results->called, called, sizeof(results->called));
                break;
-       case OSPC_DPROT_SKYPE:
+       case OSPC_PROTNAME_SKYPE:
                ast_debug(1, "OSP: protocol Skype\n");
-               ast_copy_string(results->tech, OSP_TECH_SKYPE, sizeof(results->tech));
+               ast_copy_string(results->outtech, OSP_TECH_SKYPE, sizeof(results->outtech));
                ast_copy_string(results->dest, dest, sizeof(results->dest));
                ast_copy_string(results->calling, calling, sizeof(results->calling));
                ast_copy_string(results->called, called, sizeof(results->called));
                break;
-       case OSPC_DPROT_UNDEFINED:
-       case OSPC_DPROT_UNKNOWN:
+       case OSPC_PROTNAME_UNDEFINED:
+       case OSPC_PROTNAME_UNKNOWN:
                ast_debug(1, "OSP: unknown/undefined protocol '%d'\n", protocol);
                ast_debug(1, "OSP: use default protocol '%s'\n", provider->defprotocol);
-               ast_copy_string(results->tech, provider->defprotocol, sizeof(results->tech));
+               ast_copy_string(results->outtech, provider->defprotocol, sizeof(results->outtech));
                ast_copy_string(results->dest, dest, sizeof(results->dest));
                ast_copy_string(results->calling, calling, sizeof(results->calling));
                ast_copy_string(results->called, called, sizeof(results->called));
                break;
-       case OSPC_DPROT_LRQ:
-       case OSPC_DPROT_T37:
-       case OSPC_DPROT_T38:
-       case OSPC_DPROT_SMPP:
-       case OSPC_DPROT_XMPP:
+       case OSPC_PROTNAME_LRQ:
+       case OSPC_PROTNAME_T37:
+       case OSPC_PROTNAME_T38:
+       case OSPC_PROTNAME_SMPP:
+       case OSPC_PROTNAME_XMPP:
        default:
                ast_log(LOG_WARNING, "OSP: unsupported protocol '%d'\n", protocol);
                *reason = OSPC_FAIL_PROTOCOL_ERROR;
@@ -1389,7 +1423,9 @@ static int osp_uuid2str(
        int res;
 
        if ((uuid != NULL) && (bufsize > OSP_SIZE_UUIDSTR)) {
-               snprintf(buffer, bufsize, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+               snprintf(buffer, bufsize, "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-"
+                                         "%02hhx%02hhx-%02hhx%02hhx-"
+                                         "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
                        uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
                        uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
                res = OSP_OK;
@@ -1415,7 +1451,7 @@ static int osp_create_callid(
 
        if (callid == NULL) {
                ast_log(LOG_ERROR, "Invalid parameters\n");
-               res = OSP_ERROR;
+               return OSP_ERROR;
        }
 
        callid->len = sizeof(callid->buf);
@@ -1426,6 +1462,7 @@ static int osp_create_callid(
        case OSP_CALLID_SIP:
        case OSP_CALLID_IAX:
                res = OSP_FAILED;
+               break;
        default:
                res = OSP_ERROR;
                break;
@@ -1443,12 +1480,13 @@ static int osp_create_callid(
  * \brief OSP Lookup function
  * \param name OSP provider context name
  * \param callidtypes Call ID types
+ * \param actualsrc Actual source device in indirect mode
  * \param srcdev Source device of outbound call
  * \param calling Calling number
  * \param called Called number
  * \param snetid Source network ID
  * \param np NP parameters
- * \param div SIP Diversion header parameters
+ * \param headers SIP header parameters
  * \param cinfo Custom info
  * \param results Lookup results
  * \return OSP_OK Found , OSP_FAILED No route, OSP_ERROR Error
@@ -1456,21 +1494,24 @@ static int osp_create_callid(
 static int osp_lookup(
        const char* name,
        unsigned int callidtypes,
+       const char* actualsrc,
        const char* srcdev,
        const char* calling,
        const char* called,
        const char* snetid,
        struct osp_npdata* np,
-       struct osp_diversion* div,
+       struct osp_headers* headers,
        const char* cinfo[],
        struct osp_results* results)
 {
        int res;
        struct osp_provider* provider = NULL;
+       OSPE_PROTOCOL_NAME protocol;
        char source[OSP_SIZE_NORSTR];
        char callingnum[OSP_SIZE_NORSTR];
        char callednum[OSP_SIZE_NORSTR];
        char destination[OSP_SIZE_NORSTR];
+       char* tmp;
        unsigned int tokenlen;
        char token[OSP_SIZE_TOKSTR];
        char src[OSP_SIZE_NORSTR];
@@ -1488,13 +1529,13 @@ static int osp_lookup(
 
        if (results == NULL) {
                ast_log(LOG_ERROR, "Invalid parameters\n");
-               res = OSP_ERROR;
+               return OSP_ERROR;
        }
 
        osp_convert_inout(results->dest, dest, sizeof(dest));
 
        results->outhandle = OSP_INVALID_HANDLE;
-       results->tech[0] = '\0';
+       results->outtech[0] = '\0';
        results->calling[0] = '\0';
        results->called[0] = '\0';
        results->token[0] = '\0';
@@ -1522,6 +1563,19 @@ static int osp_lookup(
                return OSP_ERROR;
        }
 
+       if (!strcasecmp(results->intech, OSP_TECH_SIP)) {
+               protocol = OSPC_PROTNAME_SIP;
+       } else if (!strcasecmp(results->intech, OSP_TECH_H323)) {
+               protocol = OSPC_PROTNAME_Q931;
+       } else if (!strcasecmp(results->intech, OSP_TECH_IAX)) {
+               protocol = OSPC_PROTNAME_IAX;
+       } else if (!strcasecmp(results->intech, OSP_TECH_SKYPE)) {
+               protocol = OSPC_PROTNAME_SKYPE;
+       } else {
+               protocol = OSPC_PROTNAME_SIP;
+       }
+       OSPPTransactionSetProtocol(results->outhandle, OSPC_PROTTYPE_SOURCE, protocol);
+
        if (!ast_strlen_zero(snetid)) {
                OSPPTransactionSetNetworkIds(results->outhandle, snetid, "");
        }
@@ -1532,8 +1586,11 @@ static int osp_lookup(
                OSPPTransactionSetOperatorName(results->outhandle, type, np->opname[type]);
        }
 
-       osp_convert_inout(div->host, host, sizeof(host));
-       OSPPTransactionSetDiversion(results->outhandle, div->user, host);
+    OSPPTransactionSetRemotePartyId(results->outhandle, OSPC_NFORMAT_E164, headers->rpiduser);
+    OSPPTransactionSetAssertedId(results->outhandle, OSPC_NFORMAT_E164, headers->paiuser);
+       osp_convert_inout(headers->divhost, host, sizeof(host));
+       OSPPTransactionSetDiversion(results->outhandle, headers->divuser, host);
+    OSPPTransactionSetChargeInfo(results->outhandle, OSPC_NFORMAT_E164, headers->pciuser);
 
        if (cinfo != NULL) {
                for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
@@ -1543,6 +1600,11 @@ static int osp_lookup(
                }
        }
 
+       ast_copy_string(callednum, called, sizeof(callednum));
+       if((tmp = strchr(callednum, ';')) != NULL) {
+               *tmp = '\0';
+       }
+
        callidnum = 0;
        callids[0] = NULL;
        for (i = 0; i < OSP_CALLID_MAXNUM; i++) {
@@ -1556,8 +1618,18 @@ static int osp_lookup(
                }
        }
 
-       osp_convert_inout(source, src, sizeof(src));
-       osp_convert_inout(srcdev, dev, sizeof(dev));
+       if (provider->workmode == OSP_MODE_INDIRECT) {
+               osp_convert_inout(srcdev, src, sizeof(src));
+               if (ast_strlen_zero(actualsrc)) {
+                       osp_convert_inout(srcdev, dev, sizeof(dev));
+               } else {
+                       osp_convert_inout(actualsrc, dev, sizeof(dev));
+               }
+       } else {
+               osp_convert_inout(source, src, sizeof(src));
+               osp_convert_inout(srcdev, dev, sizeof(dev));
+       }
+
        if (provider->srvtype == OSP_SRV_NPQUERY) {
                OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_NPQUERY);
                if (!ast_strlen_zero(dest)) {
@@ -1568,12 +1640,13 @@ static int osp_lookup(
                OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_VOICE);
                results->numdests = OSP_DEF_MAXDESTS;
        }
+
        error = OSPPTransactionRequestAuthorisation(results->outhandle,
                src,
                dev,
                calling ? calling : "",
                OSPC_NFORMAT_E164,
-               called,
+               callednum,
                OSPC_NFORMAT_E164,
                NULL,
                callidnum,
@@ -1714,7 +1787,7 @@ static int osp_lookup(
 /*!
  * \brief OSP Lookup Next function
  * \param name OSP provider name
- * \param cause Asterisk hangup cuase
+ * \param cause Asterisk hangup cause
  * \param results Lookup results, in/output
  * \return OSP_OK Found , OSP_FAILED No route, OSP_ERROR Error
  */
@@ -1736,10 +1809,10 @@ static int osp_next(
 
        if (results == NULL) {
                ast_log(LOG_ERROR, "Invalid parameters\n");
-               res = OSP_ERROR;
+               return OSP_ERROR;
        }
 
-       results->tech[0] = '\0';
+       results->outtech[0] = '\0';
        results->dest[0] = '\0';
        results->calling[0] = '\0';
        results->called[0] = '\0';
@@ -2022,20 +2095,20 @@ static int osp_report_qos(
                ast_debug(1, "OSP: stdevrtt '%f'\n", rtt.sdev);
 
                if (leg == OSP_CALL_INBOUND) {
-                       OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_DOWNSTREAM, totalpackets[OSP_DIR_RX]);
-                       OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM, totalpackets[OSP_DIR_TX]);
+                       OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SDIR_SRCREP, totalpackets[OSP_DIR_RX]);
+                       OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_DESTREP, totalpackets[OSP_DIR_TX]);
                        if (lost[OSP_DIR_RX].value >= 0) {
                                value = lost[OSP_DIR_RX].value;
                        } else {
                                value = (int)lost[OSP_DIR_RX].avg;
                        }
-                       OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_DOWNSTREAM, value, OSP_DEF_INTSTATS);
+                       OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SDIR_SRCREP, value, OSP_DEF_INTSTATS);
                        if (lost[OSP_DIR_TX].value >= 0) {
                                value = lost[OSP_DIR_TX].value;
                        } else {
                                value = (int)lost[OSP_DIR_TX].avg;
                        }
-                       OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM, value, OSP_DEF_INTSTATS);
+                       OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_DESTREP, value, OSP_DEF_INTSTATS);
                        if (jitter[OSP_DIR_RX].value >= 0) {
                                value = jitter[OSP_DIR_RX].value;
                        } else {
@@ -2043,7 +2116,7 @@ static int osp_report_qos(
                        }
                        OSPPTransactionSetJitter(trans,
                                OSPC_SMETRIC_RTP,
-                               OSPC_SFLOW_DOWNSTREAM,
+                               OSPC_SDIR_SRCREP,
                                OSP_DEF_INTSTATS,
                                (int)jitter[OSP_DIR_RX].min,
                                (int)jitter[OSP_DIR_RX].max,
@@ -2053,13 +2126,13 @@ static int osp_report_qos(
                        } else {
                                value = (int)jitter[OSP_DIR_TX].avg;
                        }
-                       OSPPTransactionSetJitter(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM,
+                       OSPPTransactionSetJitter(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_DESTREP,
                                OSP_DEF_INTSTATS, (int)jitter[OSP_DIR_TX].min, (int)jitter[OSP_DIR_TX].max, value, jitter[OSP_DIR_TX].sdev);
                } else {
-                       OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_UPSTREAM, totalpackets[OSP_DIR_RX]);
-                       OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_DOWNSTREAM, totalpackets[OSP_DIR_TX]);
-                       OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_UPSTREAM, lost[OSP_DIR_RX].value, OSP_DEF_INTSTATS);
-                       OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_DOWNSTREAM, lost[OSP_DIR_TX].value, OSP_DEF_INTSTATS);
+                       OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SDIR_DESTREP, totalpackets[OSP_DIR_RX]);
+                       OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_SRCREP, totalpackets[OSP_DIR_TX]);
+                       OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SDIR_DESTREP, lost[OSP_DIR_RX].value, OSP_DEF_INTSTATS);
+                       OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_SRCREP, lost[OSP_DIR_TX].value, OSP_DEF_INTSTATS);
                        if (jitter[OSP_DIR_RX].value >= 0) {
                                value = jitter[OSP_DIR_RX].value;
                        } else {
@@ -2067,7 +2140,7 @@ static int osp_report_qos(
                        }
                        OSPPTransactionSetJitter(trans,
                                OSPC_SMETRIC_RTP,
-                               OSPC_SFLOW_UPSTREAM,
+                               OSPC_SDIR_DESTREP,
                                OSP_DEF_INTSTATS,
                                (int)jitter[OSP_DIR_RX].min,
                                (int)jitter[OSP_DIR_RX].max,
@@ -2080,19 +2153,13 @@ static int osp_report_qos(
                        }
                        OSPPTransactionSetJitter(trans,
                                OSPC_SMETRIC_RTCP,
-                               OSPC_SFLOW_DOWNSTREAM,
+                               OSPC_SDIR_SRCREP,
                                OSP_DEF_INTSTATS,
                                (int)jitter[OSP_DIR_TX].min,
                                (int)jitter[OSP_DIR_TX].max,
                                value,
                                jitter[OSP_DIR_TX].sdev);
                }
-               if (rtt.value >= 0) {
-                       value = rtt.value;
-               } else {
-                       value = (int)rtt.avg;
-               }
-               OSPPTransactionSetRoundTripDelay(trans, OSP_DEF_INTSTATS, (int)rtt.min, (int)rtt.max, value, rtt.sdev);
 
                res = OSP_OK;
        }
@@ -2136,6 +2203,8 @@ static int osp_finish(
                return OSP_FAILED;
        }
 
+       OSPPTransactionSetRoleInfo(trans, OSPC_RSTATE_STOP, OSPC_RFORMAT_OSP, OSPC_RVENDOR_ASTERISK);
+
        if (!recorded) {
                reason = asterisk2osp(cause);
                OSPPTransactionRecordFailure(trans, reason);
@@ -2201,10 +2270,7 @@ static int ospauth_exec(
                AST_APP_ARG(options);
        );
 
-       if (!(tmp = ast_strdupa(data))) {
-               ast_log(LOG_ERROR, "Out of memory\n");
-               return OSP_AST_ERROR;
-       }
+       tmp = ast_strdupa(data);
 
        AST_STANDARD_APP_ARGS(args, tmp);
 
@@ -2213,11 +2279,11 @@ static int ospauth_exec(
        }
        ast_debug(1, "OSPAuth: provider '%s'\n", provider);
 
-       headp = &chan->varshead;
+       headp = ast_channel_varshead(chan);
        AST_LIST_TRAVERSE(headp, current, entries) {
-               if (!strcasecmp(ast_var_name(current), "OSPINPEERIP")) {
+               if (!strcmp(ast_var_name(current), "OSPINPEERIP")) {
                        source = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINTOKEN")) {
                        token = ast_var_value(current);
                }
        }
@@ -2225,7 +2291,10 @@ static int ospauth_exec(
        ast_debug(1, "OSPAuth: source '%s'\n", source);
        ast_debug(1, "OSPAuth: token size '%zd'\n", strlen(token));
 
-       if ((res = osp_auth(provider, &handle, source, chan->cid.cid_num, chan->exten, token, &timelimit)) > 0) {
+       res = osp_auth(provider, &handle, source,
+               S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
+               ast_channel_exten(chan), token, &timelimit);
+       if (res > 0) {
                status = AST_OSP_SUCCESS;
        } else {
                timelimit = OSP_DEF_TIMELIMIT;
@@ -2264,19 +2333,20 @@ static int osplookup_exec(
        struct ast_channel* chan,
        const char * data)
 {
-       int res, cres;
+       int res;
        const char* provider = OSP_DEF_PROVIDER;
        unsigned int callidtypes = OSP_CALLID_UNDEF;
        struct varshead* headp;
        struct ast_var_t* current;
+       const char* actualsrc = "";
        const char* srcdev = "";
        const char* snetid = "";
        struct osp_npdata np;
        OSPE_OPERATOR_NAME type;
-       struct osp_diversion div;
+       struct osp_headers headers;
        unsigned int i;
        const char* cinfo[OSP_MAX_CUSTOMINFO] = { NULL };
-       char buffer[OSP_SIZE_TOKSTR];
+       char buffer[OSP_SIZE_TOKSTR + strlen(": ") + strlen(OSP_SIP_HEADER)];
        struct osp_results results;
        const char* status;
        char* tmp;
@@ -2292,10 +2362,7 @@ static int osplookup_exec(
                return OSP_AST_ERROR;
        }
 
-       if (!(tmp = ast_strdupa(data))) {
-               ast_log(LOG_ERROR, "Out of memory\n");
-               return OSP_AST_ERROR;
-       }
+       tmp = ast_strdupa(data);
 
        AST_STANDARD_APP_ARGS(args, tmp);
 
@@ -2330,68 +2397,83 @@ static int osplookup_exec(
                np.opname[type] = "";
        }
 
-       div.user = "";
-       div.host = "";
+       headers.rpiduser = "";
+       headers.paiuser = "";
+       headers.divuser = "";
+       headers.divhost = "";
+       headers.pciuser = "";
 
-       headp = &chan->varshead;
+       headp = ast_channel_varshead(chan);
        AST_LIST_TRAVERSE(headp, current, entries) {
-               if (!strcasecmp(ast_var_name(current), "OSPINPEERIP")) {
+               if (!strcmp(ast_var_name(current), "OSPINACTUALSRC")) {
+                       actualsrc = ast_var_value(current);
+               } else if (!strcmp(ast_var_name(current), "OSPINPEERIP")) {
                        srcdev = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINTECH")) {
+                       ast_copy_string(results.intech, ast_var_value(current), sizeof(results.intech));
+               } else if (!strcmp(ast_var_name(current), "OSPINHANDLE")) {
                        if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
                                results.inhandle = OSP_INVALID_HANDLE;
                        }
-               } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINTIMELIMIT")) {
                        if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
                                results.intimelimit = OSP_DEF_TIMELIMIT;
                        }
-               } else if (!strcasecmp(ast_var_name(current), "OSPINNETWORKID")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINNETWORKID")) {
                        snetid = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINNPRN")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINNPRN")) {
                        np.rn = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINNPCIC")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINNPCIC")) {
                        np.cic = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINNPDI")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINNPDI")) {
                        if (ast_true(ast_var_value(current))) {
                                np.npdi = 1;
                        }
-               } else if (!strcasecmp(ast_var_name(current), "OSPINSPID")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINSPID")) {
                        np.opname[OSPC_OPNAME_SPID] = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINOCN")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINOCN")) {
                        np.opname[OSPC_OPNAME_OCN] = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINSPN")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINSPN")) {
                        np.opname[OSPC_OPNAME_SPN] = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINALTSPN")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINALTSPN")) {
                        np.opname[OSPC_OPNAME_ALTSPN] = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINMCC")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINMCC")) {
                        np.opname[OSPC_OPNAME_MCC] = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINMNC")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINMNC")) {
                        np.opname[OSPC_OPNAME_MNC] = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINTOHOST")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINTOHOST")) {
                        ast_copy_string(results.dest, ast_var_value(current), sizeof(results.dest));
-               } else if (!strcasecmp(ast_var_name(current), "OSPINDIVUSER")) {
-                       div.user = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINDIVHOST")) {
-                       div.host = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO1")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINRPIDUSER")) {
+                       headers.rpiduser = ast_var_value(current);
+               } else if (!strcmp(ast_var_name(current), "OSPINPAIUSER")) {
+                       headers.paiuser = ast_var_value(current);
+               } else if (!strcmp(ast_var_name(current), "OSPINDIVUSER")) {
+                       headers.divuser = ast_var_value(current);
+               } else if (!strcmp(ast_var_name(current), "OSPINDIVHOST")) {
+                       headers.divhost = ast_var_value(current);
+               } else if (!strcmp(ast_var_name(current), "OSPINPCIUSER")) {
+                       headers.pciuser = ast_var_value(current);
+               } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO1")) {
                        cinfo[0] = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO2")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO2")) {
                        cinfo[1] = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO3")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO3")) {
                        cinfo[2] = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO4")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO4")) {
                        cinfo[3] = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO5")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO5")) {
                        cinfo[4] = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO6")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO6")) {
                        cinfo[5] = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO7")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO7")) {
                        cinfo[6] = ast_var_value(current);
-               } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO8")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO8")) {
                        cinfo[7] = ast_var_value(current);
                }
        }
+       ast_debug(1, "OSPLookup: actual source device '%s'\n", actualsrc);
        ast_debug(1, "OSPLookup: source device '%s'\n", srcdev);
+       ast_debug(1, "OSPLookup: OSPINTECH '%s'\n", results.intech);
        ast_debug(1, "OSPLookup: OSPINHANDLE '%d'\n", results.inhandle);
        ast_debug(1, "OSPLookup: OSPINTIMELIMIT '%d'\n", results.intimelimit);
        ast_debug(1, "OSPLookup: OSPINNETWORKID '%s'\n", snetid);
@@ -2405,22 +2487,28 @@ static int osplookup_exec(
        ast_debug(1, "OSPLookup: OSPINMCC '%s'\n", np.opname[OSPC_OPNAME_MCC]);
        ast_debug(1, "OSPLookup: OSPINMNC '%s'\n", np.opname[OSPC_OPNAME_MNC]);
        ast_debug(1, "OSPLookup: OSPINTOHOST '%s'\n", results.dest);
-       ast_debug(1, "OSPLookup: OSPINDIVUSER '%s'\n", div.user);
-       ast_debug(1, "OSPLookup: OSPINDIVHOST'%s'\n", div.host);
+       ast_debug(1, "OSPLookup: OSPINRPIDUSER '%s'\n", headers.rpiduser);
+       ast_debug(1, "OSPLookup: OSPINPAIUSER '%s'\n", headers.paiuser);
+       ast_debug(1, "OSPLookup: OSPINDIVUSER '%s'\n", headers.divuser);
+       ast_debug(1, "OSPLookup: OSPINDIVHOST'%s'\n", headers.divhost);
+       ast_debug(1, "OSPLookup: OSPINPCIUSER '%s'\n", headers.pciuser);
        for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
                if (!ast_strlen_zero(cinfo[i])) {
                        ast_debug(1, "OSPLookup: OSPINCUSTOMINFO%d '%s'\n", i, cinfo[i]);
                }
        }
 
-       if ((cres = ast_autoservice_start(chan)) < 0) {
+       if (ast_autoservice_start(chan) < 0) {
                return OSP_AST_ERROR;
        }
 
-       if ((res = osp_lookup(provider, callidtypes, srcdev, chan->cid.cid_num, args.exten, snetid, &np, &div, cinfo, &results)) > 0) {
+       res = osp_lookup(provider, callidtypes, actualsrc, srcdev,
+               S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
+               args.exten, snetid, &np, &headers, cinfo, &results);
+       if (res > 0) {
                status = AST_OSP_SUCCESS;
        } else {
-               results.tech[0] = '\0';
+               results.outtech[0] = '\0';
                results.dest[0] = '\0';
                results.calling[0] = '\0';
                results.called[0] = '\0';
@@ -2446,8 +2534,8 @@ static int osplookup_exec(
        snprintf(buffer, sizeof(buffer), "%d", results.outhandle);
        pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
        ast_debug(1, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
-       pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.tech);
-       ast_debug(1, "OSPLookup: OSPOUTTECH '%s'\n", results.tech);
+       pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.outtech);
+       ast_debug(1, "OSPLookup: OSPOUTTECH '%s'\n", results.outtech);
        pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
        ast_debug(1, "OSPLookup: OSPDESTINATION '%s'\n", results.dest);
        pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
@@ -2489,32 +2577,32 @@ static int osplookup_exec(
        pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
        ast_debug(1, "OSPLookup: %s\n", status);
 
-       if (!strcasecmp(results.tech, OSP_TECH_SIP)) {
-               snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
+       if (!strcasecmp(results.outtech, OSP_TECH_SIP)) {
+               snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.outtech, results.called, results.dest);
                pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
                if (!ast_strlen_zero(results.token)) {
                        snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
                        pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
                        ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
                }
-       } else if (!strcasecmp(results.tech, OSP_TECH_H323)) {
+       } else if (!strcasecmp(results.outtech, OSP_TECH_H323)) {
                if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
                        osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
                } else {
                        buffer[0] = '\0';
                }
                pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
-               snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
+               snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.outtech, results.called, results.dest);
                pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
-       } else if (!strcasecmp(results.tech, OSP_TECH_IAX)) {
-               snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.tech, results.dest, results.called);
+       } else if (!strcasecmp(results.outtech, OSP_TECH_IAX)) {
+               snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.outtech, results.dest, results.called);
                pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
-       } else if (!strcasecmp(results.tech, OSP_TECH_SKYPE)) {
-               snprintf(buffer, sizeof(buffer), "%s/%s", results.tech, results.called);
+       } else if (!strcasecmp(results.outtech, OSP_TECH_SKYPE)) {
+               snprintf(buffer, sizeof(buffer), "%s/%s", results.outtech, results.called);
                pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
        }
 
-       if ((cres = ast_autoservice_stop(chan)) < 0) {
+       if (ast_autoservice_stop(chan) < 0) {
                return OSP_AST_ERROR;
        }
 
@@ -2544,7 +2632,7 @@ static int ospnext_exec(
        struct ast_var_t* current;
        struct osp_results results;
        OSPE_OPERATOR_NAME type;
-       char buffer[OSP_SIZE_TOKSTR];
+       char buffer[OSP_SIZE_TOKSTR + strlen(": ") + strlen(OSP_SIP_HEADER)];
        unsigned int callidtypes = OSP_CALLID_UNDEF;
        const char* status;
        char* tmp;
@@ -2560,10 +2648,7 @@ static int ospnext_exec(
                return OSP_AST_ERROR;
        }
 
-       if (!(tmp = ast_strdupa(data))) {
-               ast_log(LOG_ERROR, "Out of memory\n");
-               return OSP_AST_ERROR;
-       }
+       tmp = ast_strdupa(data);
 
        AST_STANDARD_APP_ARGS(args, tmp);
 
@@ -2582,25 +2667,25 @@ static int ospnext_exec(
        results.intimelimit = OSP_DEF_TIMELIMIT;
        results.numdests = 0;
 
-       headp = &chan->varshead;
+       headp = ast_channel_varshead(chan);
        AST_LIST_TRAVERSE(headp, current, entries) {
-               if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
+               if (!strcmp(ast_var_name(current), "OSPINHANDLE")) {
                        if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
                                results.inhandle = OSP_INVALID_HANDLE;
                        }
-               } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
+               } else if (!strcmp(ast_var_name(current), "OSPOUTHANDLE")) {
                        if (sscanf(ast_var_value(current), "%30d", &results.outhandle) != 1) {
                                results.outhandle = OSP_INVALID_HANDLE;
                        }
-               } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINTIMELIMIT")) {
                        if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
                                results.intimelimit = OSP_DEF_TIMELIMIT;
                        }
-               } else if (!strcasecmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) {
+               } else if (!strcmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) {
                        if (sscanf(ast_var_value(current), "%30d", &callidtypes) != 1) {
                                callidtypes = OSP_CALLID_UNDEF;
                        }
-               } else if (!strcasecmp(ast_var_name(current), "OSPDESTREMAILS")) {
+               } else if (!strcmp(ast_var_name(current), "OSPDESTREMAILS")) {
                        if (sscanf(ast_var_value(current), "%30d", &results.numdests) != 1) {
                                results.numdests = 0;
                        }
@@ -2615,7 +2700,7 @@ static int ospnext_exec(
        if ((res = osp_next(provider, cause, &results)) > 0) {
                status = AST_OSP_SUCCESS;
        } else {
-               results.tech[0] = '\0';
+               results.outtech[0] = '\0';
                results.dest[0] = '\0';
                results.calling[0] = '\0';
                results.called[0] = '\0';
@@ -2638,8 +2723,8 @@ static int ospnext_exec(
                }
        }
 
-       pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.tech);
-       ast_debug(1, "OSPNext: OSPOUTTECH '%s'\n", results.tech);
+       pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.outtech);
+       ast_debug(1, "OSPNext: OSPOUTTECH '%s'\n", results.outtech);
        pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
        ast_debug(1, "OSPNext: OSPDESTINATION '%s'\n", results.dest);
        pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
@@ -2678,28 +2763,28 @@ static int ospnext_exec(
        pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
        ast_debug(1, "OSPNext: %s\n", status);
 
-       if (!strcasecmp(results.tech, OSP_TECH_SIP)) {
-               snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
+       if (!strcasecmp(results.outtech, OSP_TECH_SIP)) {
+               snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.outtech, results.called, results.dest);
                pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
                if (!ast_strlen_zero(results.token)) {
                        snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
                        pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
                        ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
                }
-       } else if (!strcasecmp(results.tech, OSP_TECH_H323)) {
+       } else if (!strcasecmp(results.outtech, OSP_TECH_H323)) {
                if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
                        osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
                } else {
                        buffer[0] = '\0';
                }
                pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
-               snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
+               snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.outtech, results.called, results.dest);
                pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
-       } else if (!strcasecmp(results.tech, OSP_TECH_IAX)) {
-               snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.tech, results.dest, results.called);
+       } else if (!strcasecmp(results.outtech, OSP_TECH_IAX)) {
+               snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.outtech, results.dest, results.called);
                pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
-       } else if (!strcasecmp(results.tech, OSP_TECH_SKYPE)) {
-               snprintf(buffer, sizeof(buffer), "%s/%s", results.tech, results.called);
+       } else if (!strcasecmp(results.outtech, OSP_TECH_SKYPE)) {
+               snprintf(buffer, sizeof(buffer), "%s/%s", results.outtech, results.called);
                pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
        }
 
@@ -2729,7 +2814,7 @@ static int ospfinished_exec(
        int inhandle = OSP_INVALID_HANDLE;
        int outhandle = OSP_INVALID_HANDLE;
        int recorded = 0;
-       time_t start, connect, end;
+       time_t start = 0, connect = 0, end = 0;
        unsigned int release;
        char buffer[OSP_SIZE_INTSTR];
        char inqos[OSP_SIZE_QOSSTR] = { 0 };
@@ -2742,34 +2827,31 @@ static int ospfinished_exec(
                AST_APP_ARG(options);
        );
 
-       if (!(tmp = ast_strdupa(data))) {
-               ast_log(LOG_ERROR, "Out of memory\n");
-               return OSP_AST_ERROR;
-       }
+       tmp = ast_strdupa(data);
 
        AST_STANDARD_APP_ARGS(args, tmp);
 
-       headp = &chan->varshead;
+       headp = ast_channel_varshead(chan);
        AST_LIST_TRAVERSE(headp, current, entries) {
-               if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
+               if (!strcmp(ast_var_name(current), "OSPINHANDLE")) {
                        if (sscanf(ast_var_value(current), "%30d", &inhandle) != 1) {
                                inhandle = OSP_INVALID_HANDLE;
                        }
-               } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
+               } else if (!strcmp(ast_var_name(current), "OSPOUTHANDLE")) {
                        if (sscanf(ast_var_value(current), "%30d", &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")))
+                       (!strcmp(ast_var_name(current), "OSPAUTHSTATUS") ||
+                       !strcmp(ast_var_name(current), "OSPLOOKUPSTATUS") ||
+                       !strcmp(ast_var_name(current), "OSPNEXTSTATUS")))
                {
-                       if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) {
+                       if (strcmp(ast_var_value(current), AST_OSP_SUCCESS)) {
                                recorded = 1;
                        }
-               } else if (!strcasecmp(ast_var_name(current), "OSPINAUDIOQOS")) {
+               } else if (!strcmp(ast_var_name(current), "OSPINAUDIOQOS")) {
                        ast_copy_string(inqos, ast_var_value(current), sizeof(inqos));
-               } else if (!strcasecmp(ast_var_name(current), "OSPOUTAUDIOQOS")) {
+               } else if (!strcmp(ast_var_name(current), "OSPOUTAUDIOQOS")) {
                        ast_copy_string(outqos, ast_var_value(current), sizeof(outqos));
                }
        }
@@ -2784,19 +2866,18 @@ static int ospfinished_exec(
        }
        ast_debug(1, "OSPFinish: cause '%d'\n", cause);
 
-       if (chan->cdr) {
-               start = chan->cdr->start.tv_sec;
-               connect = chan->cdr->answer.tv_sec;
-               if (connect) {
-                       end = time(NULL);
-               } else {
-                       end = connect;
-               }
+       if (!ast_tvzero(ast_channel_creationtime(chan))) {
+               start = ast_channel_creationtime(chan).tv_sec;
+       }
+       if (!ast_tvzero(ast_channel_answertime(chan))) {
+               connect = ast_channel_answertime(chan).tv_sec;
+       }
+       if (connect) {
+               end = time(NULL);
        } else {
-               start = 0;
-               connect = 0;
-               end = 0;
+               end = connect;
        }
+
        ast_debug(1, "OSPFinish: start '%ld'\n", start);
        ast_debug(1, "OSPFinish: connect '%ld'\n", connect);
        ast_debug(1, "OSPFinish: end '%ld'\n", end);
@@ -2888,7 +2969,7 @@ static int osp_load(int reload)
 
                if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate")) && ast_true(cvar)) {
                        if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
-                               ast_log(LOG_WARNING, "OSP: Unable to enable hardware accelleration\n");
+                               ast_log(LOG_WARNING, "OSP: Unable to enable hardware acceleration, error='%d'\n", error);
                                OSPPInit(0);
                        } else {
                                osp_hardware = 1;
@@ -2902,7 +2983,7 @@ static int osp_load(int reload)
                        osp_security = 1;
                }
                ast_debug(1, "OSP: osp_security '%d'\n", osp_security);
-               
+
                if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat"))) {
                        if ((sscanf(cvar, "%30d", &ivar) == 1) &&
                                ((ivar == TOKEN_ALGO_SIGNED) || (ivar == TOKEN_ALGO_UNSIGNED) || (ivar == TOKEN_ALGO_BOTH)))
@@ -3004,6 +3085,7 @@ static char *handle_cli_osp_show(struct ast_cli_entry *e, int cmd, struct ast_cl
                        ast_cli(a->fd, "Source:            %s\n", strlen(provider->source) ? provider->source : "<unspecified>");
                        ast_cli(a->fd, "Auth Policy        %d\n", provider->authpolicy);
                        ast_cli(a->fd, "Default protocol   %s\n", provider->defprotocol);
+                       ast_cli(a->fd, "Work mode          %d\n", provider->workmode);
                        ast_cli(a->fd, "Service type       %d\n", provider->srvtype);
                        ast_cli(a->fd, "OSP Handle:        %d\n", provider->handle);
                        found++;
@@ -3076,6 +3158,7 @@ static int reload(void)
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
+       .support_level = AST_MODULE_SUPPORT_EXTENDED,
        .load = load_module,
        .unload = unload_module,
        .reload = reload,