2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief Open Settlement Protocol (OSP) Applications
23 * \author Mark Spencer <markster@digium.com>
25 * \extref The OSP Toolkit: http://www.transnexus.com
26 * \extref OpenSSL http://www.openssl.org
28 * \ingroup applications
32 <depend>osptk</depend>
33 <depend>openssl</depend>
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
41 #include <osp/osputils.h>
42 #include <osp/ospb64.h>
44 #include "asterisk/paths.h"
45 #include "asterisk/lock.h"
46 #include "asterisk/config.h"
47 #include "asterisk/utils.h"
48 #include "asterisk/causes.h"
49 #include "asterisk/channel.h"
50 #include "asterisk/app.h"
51 #include "asterisk/module.h"
52 #include "asterisk/pbx.h"
53 #include "asterisk/cli.h"
54 #include "asterisk/astosp.h"
57 <application name="OSPAuth" language="en_US">
62 <parameter name="provider" />
63 <parameter name="options" />
66 <para>Authenticate a call by OSP and sets the variables:</para>
68 <variable name="OSPINHANDLE">
69 <para>The inbound call transaction handle.</para>
71 <variable name="OSPINTIMELIMIT">
72 <para>The inbound call duration limit in seconds.</para>
75 <para>This application sets the following channel variable upon completion:</para>
77 <variable name="OSPAUTHSTATUS">
78 <para>The status of the OSP Auth attempt as a text string, one of</para>
79 <value name="SUCCESS" />
80 <value name="FAILED" />
81 <value name="ERROR" />
86 <application name="OSPLookup" language="en_US">
88 Lookup destination by OSP.
91 <parameter name="exten" required="true" />
92 <parameter name="provider" />
93 <parameter name="options">
96 <para>generate H323 call id for the outbound call</para>
99 <para>generate SIP call id for the outbound call.
100 Have not been implemented</para>
103 <para>generate IAX call id for the outbound call.
104 Have not been implemented</para>
110 <para>Looks up an extension via OSP and sets the variables, where <literal>n</literal> is the
111 number of the result beginning with <literal>1</literal>:</para>
113 <variable name="OSPOUTHANDLE">
114 <para>The OSP Handle for anything remaining.</para>
116 <variable name="OSPTECH">
117 <para>The technology to use for the call.</para>
119 <variable name="OSPDESTINATION">
120 <para>The destination to use for the call.</para>
122 <variable name="OSPOUTCALLING">
123 <para>The calling number to use for the call.</para>
125 <variable name="OSPOUTCALLED">
126 <para>The called number to use for the call.</para>
128 <variable name="OSPDIALSTR">
129 <para>The dial command string.</para>
131 <variable name="OSPOUTTOKEN">
132 <para>The actual OSP token as a string.</para>
134 <variable name="OSPOUTTIMELIMIT">
135 <para>The outbound call duraction limit in seconds.</para>
137 <variable name="OSPOUTCALLIDTYPES">
138 <para>The outbound call id types.</para>
140 <variable name="OSPOUTCALLID">
141 <para>The outbound call id.</para>
143 <variable name="OSPDESTREMAILS">
144 <para>The number of OSP results total remaining.</para>
148 <variable name="OSPLOOKUPSTATUS">
149 <para>This application sets the following channel variable upon completion:</para>
150 <value name="SUCCESS" />
151 <value name="FAILED" />
152 <value name="ERROR" />
157 <application name="OSPNext" language="en_US">
159 Lookup next destination by OSP.
162 <parameter name="cause" required="true" />
163 <parameter name="provider" />
164 <parameter name="options" />
167 <para>Looks up the next OSP Destination for <variable>OSPOUTHANDLE</variable>.</para>
168 <para>This application sets the following channel variable upon completion:</para>
170 <variable name="OSPNEXTSTATUS">
171 <para>The status of the OSP Next attempt as a text string, one of</para>
172 <value name="SUCCESS" />
173 <value name="FAILED" />
174 <value name="ERROR" />
179 <ref type="application">OSPLookup</ref>
182 <application name="OSPFinish" language="en_US">
187 <parameter name="status" />
188 <parameter name="options" />
191 <para>Records call state for <variable>OSPINHANDLE</variable>, according to status, which should
192 be one of <literal>BUSY</literal>, <literal>CONGESTION</literal>, <literal>ANSWER</literal>,
193 <literal>NOANSWER</literal>, or <literal>CHANUNAVAIL</literal> or coincidentally, just what the
194 Dial application stores in its <variable>DIALSTATUS</variable>.</para>
195 <para>This application sets the following channel variable upon completion:</para>
197 <variable name="OSPFINISHSTATUS">
198 <para>The status of the OSP Finish attempt as a text string, one of</para>
199 <value name="SUCCESS" />
200 <value name="FAILED" />
201 <value name="ERROR" />
208 /* OSP Buffer Sizes */
209 #define OSP_SIZE_INTSTR ((unsigned int)16) /* OSP signed/unsigned int string buffer size */
210 #define OSP_SIZE_NORSTR ((unsigned int)256) /* OSP normal string buffer size */
211 #define OSP_SIZE_KEYSTR ((unsigned int)1024) /* OSP certificate string buffer size */
212 #define OSP_SIZE_TOKSTR ((unsigned int)4096) /* OSP token string buffer size */
213 #define OSP_SIZE_TECHSTR ((unsigned int)32) /* OSP signed/unsigned int string buffer size */
214 #define OSP_SIZE_UUID ((unsigned int)16) /* UUID size */
215 #define OSP_SIZE_UUIDSTR ((unsigned int)36) /* UUID string size */
216 #define OSP_SIZE_QOSSTR ((unsigned int)1024) /* QoS string buffer size */
219 #define OSP_CALLID_UNDEF ((unsigned int)0) /* Undefined */
220 #define OSP_CALLID_SIP ((unsigned int)(1 << 0)) /* SIP */
221 #define OSP_CALLID_H323 ((unsigned int)(1 << 1)) /* H.323 */
222 #define OSP_CALLID_IAX ((unsigned int)(1 << 2)) /* IAX2 */
223 #define OSP_CALLID_MAXNUM ((unsigned int)3) /* Max number of call ID types */
225 /* OSP Supported Destination Protocols */
226 #define OSP_PROT_SIP ((const char*)"SIP") /* SIP protocol name */
227 #define OSP_PROT_H323 ((const char*)"H323") /* H.323 Q.931 protocol name*/
228 #define OSP_PROT_IAX ((const char*)"IAX") /* IAX2 protocol name */
229 #define OSP_PROT_SKYPE ((const char*)"SKYPE") /* Skype protocol name */
231 /* OSP supported Destination Tech */
232 #define OSP_TECH_SIP ((const char*)"SIP") /* SIP tech name */
233 #define OSP_TECH_H323 ((const char*)"H323") /* OH323 tech name */
234 #define OSP_TECH_IAX ((const char*)"IAX2") /* IAX2 tech name */
235 #define OSP_TECH_SKYPE ((const char*)"SKYPE") /* Skype tech name */
237 /* SIP OSP header field name */
238 #define OSP_SIP_HEADER ((const char*)"P-OSP-Auth-Token")
240 /* OSP Authentication Policy */
241 enum osp_authpolicy {
242 OSP_AUTH_NO = 0, /* Accept any call */
243 OSP_AUTH_YES, /* Accept call with valid OSP token or without OSP token */
244 OSP_AUTH_EXC /* Only accept call with valid OSP token */
247 /* OSP Service Type */
249 OSP_SRV_VOICE = 0, /* Normal voice service */
250 OSP_SRV_NPQUERY /* Ported number query service */
254 #define OSP_OK ((int)1) /* OSP function call successful */
255 #define OSP_FAILED ((int)0) /* OSP function call failed */
256 #define OSP_ERROR ((int)-1) /* OSP function call error */
257 #define OSP_AST_OK ((int)0) /* Asterisk function call successful */
258 #define OSP_AST_ERROR ((int)-1) /* Asterisk function call error */
259 #define OSP_INVALID_HANDLE ((int)-1) /* Invalid OSP handle, provider, transaction etc. */
260 #define OSP_CONFIG_FILE ((const char*)"osp.conf") /* OSP configuration file name */
261 #define OSP_GENERAL_CAT ((const char*)"general") /* OSP global configuration context name */
262 #define OSP_DEF_PROVIDER ((const char*)"default") /* OSP default provider context name */
263 #define OSP_MAX_CERTS ((unsigned int)10) /* OSP max number of cacerts */
264 #define OSP_MAX_SPOINTS ((unsigned int)10) /* OSP max number of service points */
265 #define OSP_DEF_MAXCONNECT ((unsigned int)20) /* OSP default max_connections */
266 #define OSP_MIN_MAXCONNECT ((unsigned int)1) /* OSP min max_connections */
267 #define OSP_MAX_MAXCONNECT ((unsigned int)1000) /* OSP max max_connections */
268 #define OSP_DEF_RETRYDELAY ((unsigned int)0) /* OSP default retry delay */
269 #define OSP_MIN_RETRYDELAY ((unsigned int)0) /* OSP min retry delay */
270 #define OSP_MAX_RETRYDELAY ((unsigned int)10) /* OSP max retry delay */
271 #define OSP_DEF_RETRYLIMIT ((unsigned int)2) /* OSP default retry times */
272 #define OSP_MIN_RETRYLIMIT ((unsigned int)0) /* OSP min retry times */
273 #define OSP_MAX_RETRYLIMIT ((unsigned int)100) /* OSP max retry times */
274 #define OSP_DEF_TIMEOUT ((unsigned int)500) /* OSP default timeout in ms */
275 #define OSP_MIN_TIMEOUT ((unsigned int)200) /* OSP min timeout in ms */
276 #define OSP_MAX_TIMEOUT ((unsigned int)10000) /* OSP max timeout in ms */
277 #define OSP_DEF_AUTHPOLICY OSP_AUTH_YES /* OSP default auth policy, yes */
278 #define OSP_AUDIT_URL ((const char*)"localhost") /* OSP default Audit URL */
279 #define OSP_LOCAL_VALIDATION ((int)1) /* Validate OSP token locally */
280 #define OSP_SSL_LIFETIME ((unsigned int)300) /* SSL life time, in seconds */
281 #define OSP_HTTP_PERSISTENCE ((int)1) /* In seconds */
282 #define OSP_CUSTOMER_ID ((const char*)"") /* OSP customer ID */
283 #define OSP_DEVICE_ID ((const char*)"") /* OSP device ID */
284 #define OSP_DEF_MAXDESTS ((unsigned int)5) /* OSP default max number of destinations */
285 #define OSP_DEF_TIMELIMIT ((unsigned int)0) /* OSP default duration limit, no limit */
286 #define OSP_DEF_PROTOCOL OSP_PROT_SIP /* OSP default destination protocol, SIP */
287 #define OSP_DEF_SRVTYPE OSP_SRV_VOICE /* OSP default service type, voice */
288 #define OSP_MAX_CUSTOMINFO ((unsigned int)8) /* OSP max number of custom info */
289 #define OSP_DEF_INTSTATS ((int)-1) /* OSP default int statistic */
290 #define OSP_DEF_FLOATSTATS ((float)-1) /* OSP default float statistic */
293 struct osp_provider {
294 OSPTPROVHANDLE handle; /* OSP provider handle */
295 char name[OSP_SIZE_NORSTR]; /* OSP provider context name */
296 char privatekey[OSP_SIZE_NORSTR]; /* OSP private key file name */
297 char localcert[OSP_SIZE_NORSTR]; /* OSP local cert file name */
298 unsigned int canum; /* Number of cacerts */
299 char cacerts[OSP_MAX_CERTS][OSP_SIZE_NORSTR]; /* Cacert file names */
300 unsigned int spnum; /* Number of service points */
301 char spoints[OSP_MAX_SPOINTS][OSP_SIZE_NORSTR]; /* Service point URLs */
302 unsigned int maxconnect; /* Max number of connections */
303 unsigned int retrydelay; /* Retry delay */
304 unsigned int retrylimit; /* Retry limit */
305 unsigned int timeout; /* Timeout in ms */
306 char source[OSP_SIZE_NORSTR]; /* IP of self */
307 enum osp_authpolicy authpolicy; /* OSP authentication policy */
308 const char* defprotocol; /* OSP default destination protocol */
309 enum osp_srvtype srvtype; /* OSP default service type */
310 struct osp_provider* next; /* Pointer to next OSP provider */
315 unsigned char buf[OSP_SIZE_NORSTR]; /* Call ID string */
316 unsigned int len; /* Call ID length */
319 /* Number Portability Data */
321 const char* rn; /* Rounding Number */
322 const char* cic; /* Carrier Identification Code */
323 int npdi; /* NP Database Dip Indicator */
324 const char* opname[OSPC_OPNAME_NUMBER]; /* Operator Names */
327 /* SIP Diversion Header Parameters */
328 struct osp_diversion {
329 const char* user; /* Diversion header user info */
330 const char* host; /* Diversion header host info */
333 /* OSP Application In/Output Results */
335 int inhandle; /* Inbound transaction handle */
336 int outhandle; /* Outbound transaction handle */
337 unsigned int intimelimit; /* Inbound duration limit */
338 unsigned int outtimelimit; /* Outbound duration limit */
339 char tech[OSP_SIZE_TECHSTR]; /* Outbound Asterisk TECH string */
340 char dest[OSP_SIZE_NORSTR]; /* Outbound destination IP address */
341 char calling[OSP_SIZE_NORSTR]; /* Outbound calling number, may be translated */
342 char called[OSP_SIZE_NORSTR]; /* Outbound called number, may be translated */
343 char token[OSP_SIZE_TOKSTR]; /* Outbound OSP token */
344 char networkid[OSP_SIZE_NORSTR]; /* Outbound network ID */
345 char nprn[OSP_SIZE_NORSTR]; /* Outbound NP routing number */
346 char npcic[OSP_SIZE_NORSTR]; /* Outbound NP carrier identification code */
347 int npdi; /* Outbound NP database dip indicator */
348 char opname[OSPC_OPNAME_NUMBER][OSP_SIZE_NORSTR]; /* Outbound Operator names */
349 unsigned int numdests; /* Number of remain outbound destinations */
350 struct osp_callid outcallid; /* Outbound call ID */
355 OSP_CALL_INBOUND, /* Inbound call leg */
356 OSP_CALL_OUTBOUND /* Outbound call leg */
359 /* OSP Media Stream Direction */
361 OSP_DIR_RX = 0, /* Receive */
362 OSP_DIR_TX, /* Send */
363 OSP_DIR_NUMBER /* Number of directions */
368 int value; /* Value */
369 float min; /* Minimum */
370 float max; /* Maximum */
371 float avg; /* Average */
372 float ndev; /* Normal deviation */
373 float sdev; /* Standard deviation */
376 /* OSP Module Global Variables */
377 AST_MUTEX_DEFINE_STATIC(osp_lock); /* Lock of OSP provider list */
378 static int osp_initialized = 0; /* Init flag */
379 static int osp_hardware = 0; /* Hardware accelleration flag */
380 static int osp_security = 0; /* Using security features flag */
381 static struct osp_provider* osp_providers = NULL; /* OSP provider list */
382 static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED; /* Token format supported */
384 /* OSP default certificates */
385 const char* B64PKey = "MIIBOgIBAAJBAK8t5l+PUbTC4lvwlNxV5lpl+2dwSZGW46dowTe6y133XyVEwNiiRma2YNk3xKs/TJ3Wl9Wpns2SYEAJsFfSTukCAwEAAQJAPz13vCm2GmZ8Zyp74usTxLCqSJZNyMRLHQWBM0g44Iuy4wE3vpi7Wq+xYuSOH2mu4OddnxswCP4QhaXVQavTAQIhAOBVCKXtppEw9UaOBL4vW0Ed/6EA/1D8hDW6St0h7EXJAiEAx+iRmZKhJD6VT84dtX5ZYNVk3j3dAcIOovpzUj9a0CECIEduTCapmZQ5xqAEsLXuVlxRtQgLTUD4ZxDElPn8x0MhAiBE2HlcND0+qDbvtwJQQOUzDgqg5xk3w8capboVdzAlQQIhAMC+lDL7+gDYkNAft5Mu+NObJmQs4Cr+DkDFsKqoxqrm";
386 const char* B64LCert = "MIIBeTCCASMCEHqkOHVRRWr+1COq3CR/xsowDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTA1MDYyMzAwMjkxOFoXDTA2MDYyNDAwMjkxOFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCvLeZfj1G0wuJb8JTcVeZaZftncEmRluOnaME3ustd918lRMDYokZmtmDZN8SrP0yd1pfVqZ7NkmBACbBX0k7pAgMBAAEwDQYJKoZIhvcNAQEEBQADQQDnV8QNFVVJx/+7IselU0wsepqMurivXZzuxOmTEmTVDzCJx1xhA8jd3vGAj7XDIYiPub1PV23eY5a2ARJuw5w9";
387 const char* B64CACert = "MIIBYDCCAQoCAQEwDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTAyMDIwNDE4MjU1MloXDTEyMDIwMzE4MjU1MlowOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPGeGwV41EIhX0jEDFLRXQhDEr50OUQPq+f55VwQd0TQNts06BP29+UiNdRW3c3IRHdZcJdC1Cg68ME9cgeq0h8CAwEAATANBgkqhkiG9w0BAQQFAANBAGkzBSj1EnnmUxbaiG1N4xjIuLAWydun7o3bFk2tV8dBIhnuh445obYyk1EnQ27kI7eACCILBZqi2MHDOIMnoN0=";
389 /* OSP Client Wrapper APIs */
392 * \brief Create OSP provider handle according to configuration
393 * \param cfg OSP configuration
394 * \param name OSP provider context name
395 * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
397 static int osp_create_provider(
398 struct ast_config* cfg,
401 int res = OSP_FAILED;
402 struct ast_variable* var;
403 struct osp_provider* provider;
404 OSPTPRIVATEKEY privatekey;
406 OSPT_CERT cacerts[OSP_MAX_CERTS];
407 const OSPT_CERT* pcacerts[OSP_MAX_CERTS];
408 const char* pspoints[OSP_MAX_SPOINTS];
409 unsigned char privatekeydata[OSP_SIZE_KEYSTR];
410 unsigned char localcertdata[OSP_SIZE_KEYSTR];
411 unsigned char cacertdata[OSP_SIZE_KEYSTR];
412 int i, num, error = OSPC_ERR_NO_ERROR;
414 if (!(provider = ast_calloc(1, sizeof(*provider)))) {
415 ast_log(LOG_ERROR, "Out of memory\n");
419 /* ast_calloc has set 0 in provider */
420 provider->handle = OSP_INVALID_HANDLE;
421 ast_copy_string(provider->name, name, sizeof(provider->name));
422 snprintf(provider->privatekey, sizeof(provider->privatekey), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, name);
423 snprintf(provider->localcert, sizeof(provider->localcert), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, name);
424 snprintf(provider->cacerts[0], sizeof(provider->cacerts[0]), "%s/%s-cacert_0.pem", ast_config_AST_KEY_DIR, name);
425 provider->maxconnect = OSP_DEF_MAXCONNECT;
426 provider->retrydelay = OSP_DEF_RETRYDELAY;
427 provider->retrylimit = OSP_DEF_RETRYLIMIT;
428 provider->timeout = OSP_DEF_TIMEOUT;
429 provider->authpolicy = OSP_DEF_AUTHPOLICY;
430 provider->defprotocol = OSP_DEF_PROTOCOL;
431 provider->srvtype = OSP_DEF_SRVTYPE;
433 for (var = ast_variable_browse(cfg, name); var != NULL; var = var->next) {
434 if (!strcasecmp(var->name, "privatekey")) {
436 if (var->value[0] == '/') {
437 ast_copy_string(provider->privatekey, var->value, sizeof(provider->privatekey));
439 snprintf(provider->privatekey, sizeof(provider->privatekey), "%s/%s", ast_config_AST_KEY_DIR, var->value);
441 ast_debug(1, "OSP: privatekey '%s'\n", provider->privatekey);
443 } else if (!strcasecmp(var->name, "localcert")) {
445 if (var->value[0] == '/') {
446 ast_copy_string(provider->localcert, var->value, sizeof(provider->localcert));
448 snprintf(provider->localcert, sizeof(provider->localcert), "%s/%s", ast_config_AST_KEY_DIR, var->value);
450 ast_debug(1, "OSP: localcert '%s'\n", provider->localcert);
452 } else if (!strcasecmp(var->name, "cacert")) {
454 if (provider->canum < OSP_MAX_CERTS) {
455 if (var->value[0] == '/') {
456 ast_copy_string(provider->cacerts[provider->canum], var->value, sizeof(provider->cacerts[provider->canum]));
458 snprintf(provider->cacerts[provider->canum], sizeof(provider->cacerts[provider->canum]), "%s/%s", ast_config_AST_KEY_DIR, var->value);
460 ast_debug(1, "OSP: cacerts[%d]: '%s'\n", provider->canum, provider->cacerts[provider->canum]);
463 ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", var->lineno);
466 } else if (!strcasecmp(var->name, "servicepoint")) {
467 if (provider->spnum < OSP_MAX_SPOINTS) {
468 ast_copy_string(provider->spoints[provider->spnum], var->value, sizeof(provider->spoints[provider->spnum]));
469 ast_debug(1, "OSP: servicepoint[%d]: '%s'\n", provider->spnum, provider->spoints[provider->spnum]);
472 ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", var->lineno);
474 } else if (!strcasecmp(var->name, "maxconnect")) {
475 if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_MAXCONNECT) && (num <= OSP_MAX_MAXCONNECT)) {
476 provider->maxconnect = num;
477 ast_debug(1, "OSP: maxconnect '%d'\n", num);
479 ast_log(LOG_WARNING, "OSP: maxconnect should be an integer from %d to %d, not '%s' at line %d\n",
480 OSP_MIN_MAXCONNECT, OSP_MAX_MAXCONNECT, var->value, var->lineno);
482 } else if (!strcasecmp(var->name, "retrydelay")) {
483 if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_RETRYDELAY) && (num <= OSP_MAX_RETRYDELAY)) {
484 provider->retrydelay = num;
485 ast_debug(1, "OSP: retrydelay '%d'\n", num);
487 ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n",
488 OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY, var->value, var->lineno);
490 } else if (!strcasecmp(var->name, "retrylimit")) {
491 if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_RETRYLIMIT) && (num <= OSP_MAX_RETRYLIMIT)) {
492 provider->retrylimit = num;
493 ast_debug(1, "OSP: retrylimit '%d'\n", num);
495 ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n",
496 OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT, var->value, var->lineno);
498 } else if (!strcasecmp(var->name, "timeout")) {
499 if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_TIMEOUT) && (num <= OSP_MAX_TIMEOUT)) {
500 provider->timeout = num;
501 ast_debug(1, "OSP: timeout '%d'\n", num);
503 ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n",
504 OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT, var->value, var->lineno);
506 } else if (!strcasecmp(var->name, "source")) {
507 ast_copy_string(provider->source, var->value, sizeof(provider->source));
508 ast_debug(1, "OSP: source '%s'\n", provider->source);
509 } else if (!strcasecmp(var->name, "authpolicy")) {
510 if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_AUTH_NO) || (num == OSP_AUTH_YES) || (num == OSP_AUTH_EXC))) {
511 provider->authpolicy = num;
512 ast_debug(1, "OSP: authpolicy '%d'\n", num);
514 ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n",
515 OSP_AUTH_NO, OSP_AUTH_YES, OSP_AUTH_EXC, var->value, var->lineno);
517 } else if (!strcasecmp(var->name, "defprotocol")) {
518 if (!strcasecmp(var->value, OSP_PROT_SIP)) {
519 provider->defprotocol = OSP_PROT_SIP;
520 ast_debug(1, "OSP: default protocol SIP\n");
521 } else if (!strcasecmp(var->value, OSP_PROT_H323)) {
522 provider->defprotocol = OSP_PROT_H323;
523 ast_debug(1, "OSP: default protocol H.323\n");
524 } else if (!strcasecmp(var->value, OSP_PROT_IAX)) {
525 provider->defprotocol = OSP_PROT_IAX;
526 ast_debug(1, "OSP: default protocol IAX\n");
527 } else if (!strcasecmp(var->value, OSP_PROT_SKYPE)) {
528 provider->defprotocol = OSP_PROT_SKYPE;
529 ast_debug(1, "OSP: default protocol Skype\n");
531 ast_log(LOG_WARNING, "OSP: default protocol should be %s, %s, %s or %s not '%s' at line %d\n",
532 OSP_PROT_SIP, OSP_PROT_H323, OSP_PROT_IAX, OSP_PROT_SKYPE, var->value, var->lineno);
534 } else if (!strcasecmp(var->name, "servicetype")) {
535 if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_SRV_VOICE) || (num == OSP_SRV_NPQUERY))) {
536 provider->srvtype = num;
537 ast_debug(1, "OSP: servicetype '%d'\n", num);
539 ast_log(LOG_WARNING, "OSP: servicetype should be %d or %d, not '%s' at line %d\n",
540 OSP_SRV_VOICE, OSP_SRV_NPQUERY, var->value, var->lineno);
545 if (provider->canum == 0) {
549 for (i = 0; i < provider->spnum; i++) {
550 pspoints[i] = provider->spoints[i];
554 privatekey.PrivateKeyData = NULL;
555 privatekey.PrivateKeyLength = 0;
557 localcert.CertData = NULL;
558 localcert.CertDataLength = 0;
560 for (i = 0; i < provider->canum; i++) {
561 cacerts[i].CertData = NULL;
562 cacerts[i].CertDataLength = 0;
565 if ((error = OSPPUtilLoadPEMPrivateKey((unsigned char*)provider->privatekey, &privatekey)) != OSPC_ERR_NO_ERROR) {
566 ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", provider->privatekey, error);
567 } else if ((error = OSPPUtilLoadPEMCert((unsigned char*)provider->localcert, &localcert)) != OSPC_ERR_NO_ERROR) {
568 ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", provider->localcert, error);
570 for (i = 0; i < provider->canum; i++) {
571 if ((error = OSPPUtilLoadPEMCert((unsigned char*)provider->cacerts[i], &cacerts[i])) != OSPC_ERR_NO_ERROR) {
572 ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", provider->cacerts[i], error);
575 pcacerts[i] = &cacerts[i];
580 privatekey.PrivateKeyData = privatekeydata;
581 privatekey.PrivateKeyLength = sizeof(privatekeydata);
583 localcert.CertData = localcertdata;
584 localcert.CertDataLength = sizeof(localcertdata);
586 cacerts[0].CertData = cacertdata;
587 cacerts[0].CertDataLength = sizeof(cacertdata);
588 pcacerts[0] = &cacerts[0];
590 if ((error = OSPPBase64Decode(B64PKey, strlen(B64PKey), privatekey.PrivateKeyData, &privatekey.PrivateKeyLength)) != OSPC_ERR_NO_ERROR) {
591 ast_log(LOG_WARNING, "OSP: Unable to decode private key, error '%d'\n", error);
592 } else if ((error = OSPPBase64Decode(B64LCert, strlen(B64LCert), localcert.CertData, &localcert.CertDataLength)) != OSPC_ERR_NO_ERROR) {
593 ast_log(LOG_WARNING, "OSP: Unable to decode local cert, error '%d'\n", error);
594 } else if ((error = OSPPBase64Decode(B64CACert, strlen(B64CACert), cacerts[0].CertData, &cacerts[0].CertDataLength)) != OSPC_ERR_NO_ERROR) {
595 ast_log(LOG_WARNING, "OSP: Unable to decode cacert, error '%d'\n", error);
599 if (error == OSPC_ERR_NO_ERROR) {
600 error = OSPPProviderNew(provider->spnum,
608 OSP_LOCAL_VALIDATION,
610 provider->maxconnect,
611 OSP_HTTP_PERSISTENCE,
612 provider->retrydelay,
613 provider->retrylimit,
618 if (error != OSPC_ERR_NO_ERROR) {
619 ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", name, error);
622 ast_debug(1, "OSP: provider '%s'\n", name);
623 ast_mutex_lock(&osp_lock);
624 provider->next = osp_providers;
625 osp_providers = provider;
626 ast_mutex_unlock(&osp_lock);
632 for (i = 0; i < provider->canum; i++) {
633 if (cacerts[i].CertData) {
634 ast_free(cacerts[i].CertData);
637 if (localcert.CertData) {
638 ast_free(localcert.CertData);
640 if (privatekey.PrivateKeyData) {
641 ast_free(privatekey.PrivateKeyData);
653 * \brief Get OSP provider by name
654 * \param name OSP provider context name
655 * \param provider OSP provider structure
656 * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
658 static int osp_get_provider(
660 struct osp_provider** provider)
662 int res = OSP_FAILED;
663 struct osp_provider* p;
667 ast_mutex_lock(&osp_lock);
668 for (p = osp_providers; p != NULL; p = p->next) {
669 if (!strcasecmp(p->name, name)) {
671 ast_debug(1, "OSP: find provider '%s'\n", name);
676 ast_mutex_unlock(&osp_lock);
682 * \brief Create OSP transaction handle
683 * \param name OSP provider context name
684 * \param trans OSP transaction handle, output
685 * \param source Source of provider, output
686 * \param sourcesize Size of source buffer, in
687 * \return OSK_OK Success, OSK_FAILED Failed, OSP_ERROR Error
689 static int osp_create_transaction(
693 unsigned int srcsize)
695 int res = OSP_FAILED;
696 struct osp_provider* provider;
699 if ((trans == NULL) || (source == NULL) || (srcsize <= 0)) {
700 ast_log(LOG_ERROR, "Invalid parameters\n");
704 *trans = OSP_INVALID_HANDLE;
707 ast_mutex_lock(&osp_lock);
708 for (provider = osp_providers; provider; provider = provider->next) {
709 if (!strcasecmp(provider->name, name)) {
710 error = OSPPTransactionNew(provider->handle, trans);
711 if (error == OSPC_ERR_NO_ERROR) {
712 ast_debug(1, "OSP: transaction '%d'\n", *trans);
713 ast_copy_string(source, provider->source, srcsize);
714 ast_debug(1, "OSP: source '%s'\n", source);
717 *trans = OSP_INVALID_HANDLE;
718 ast_debug(1, "OSP: Unable to create transaction handle, error '%d'\n", error);
725 ast_mutex_unlock(&osp_lock);
731 * \brief Convert "address:port" to "[x.x.x.x]:port" or "hostname:port" format
732 * \param src Source address string
733 * \param dest Destination address string
734 * \param destsize Size of dest buffer
736 static void osp_convert_inout(
739 unsigned int destsize)
742 char buffer[OSP_SIZE_NORSTR];
745 if ((dest != NULL) && (destsize > 0)) {
746 if (!ast_strlen_zero(src)) {
747 ast_copy_string(buffer, src, sizeof(buffer));
749 if((port = strchr(buffer, ':')) != NULL) {
754 if (inet_pton(AF_INET, buffer, &inp) == 1) {
756 snprintf(dest, destsize, "[%s]:%s", buffer, port);
758 snprintf(dest, destsize, "[%s]", buffer);
760 dest[destsize - 1] = '\0';
762 ast_copy_string(dest, src, destsize);
771 * \brief Convert "[x.x.x.x]:port" or "hostname:prot" to "address:port" format
772 * \param src Source address string
773 * \param dest Destination address string
774 * \param destsize Size of dest buffer
776 static void osp_convert_outin(
779 unsigned int destsize)
781 char buffer[OSP_SIZE_NORSTR];
785 if ((dest != NULL) && (destsize > 0)) {
786 if (!ast_strlen_zero(src)) {
787 ast_copy_string(buffer, src, sizeof(buffer));
789 if (buffer[0] == '[') {
790 if((port = strchr(buffer + 1, ':')) != NULL) {
795 if ((end = strchr(buffer + 1, ']')) != NULL) {
800 snprintf(dest, destsize, "%s:%s", buffer + 1, port);
801 dest[destsize - 1] = '\0';
803 ast_copy_string(dest, buffer + 1, destsize);
806 ast_copy_string(dest, src, destsize);
815 * \brief Validate OSP token of inbound call
816 * \param trans OSP transaction handle
817 * \param source Source of inbound call
818 * \param destination Destination of inbound call
819 * \param calling Calling number
820 * \param called Called number
821 * \param token OSP token, may be empty
822 * \param timelimit Call duration limit, output
823 * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
825 static int osp_validate_token(
828 const char* destination,
832 unsigned int* timelimit)
836 unsigned char tokenstr[OSP_SIZE_TOKSTR];
837 char src[OSP_SIZE_NORSTR];
838 char dest[OSP_SIZE_NORSTR];
839 unsigned int authorised;
840 unsigned int dummy = 0;
843 if (timelimit == NULL) {
844 ast_log(LOG_ERROR, "Invalid parameters\n");
848 tokenlen = ast_base64decode(tokenstr, token, strlen(token));
849 osp_convert_inout(source, src, sizeof(src));
850 osp_convert_inout(destination, dest, sizeof(dest));
851 error = OSPPTransactionValidateAuthorisation(trans,
856 calling ? calling : "",
869 if (error != OSPC_ERR_NO_ERROR) {
870 ast_log(LOG_WARNING, "OSP: Unable to validate inbound token, error '%d'\n", error);
873 } else if (authorised) {
874 ast_debug(1, "OSP: Authorised\n");
877 ast_debug(1, "OSP: Unauthorised\n");
885 * \brief Choose min duration limit
886 * \param in Inbound duration limit
887 * \param out Outbound duration limit
888 * \return min duration limit
890 static unsigned int osp_choose_timelimit(
894 if (in == OSP_DEF_TIMELIMIT) {
896 } else if (out == OSP_DEF_TIMELIMIT) {
899 return in < out ? in : out;
904 * \brief Choose min duration limit
905 * \param provider OSP provider
906 * \param calling Calling number
907 * \param called Called number
908 * \param destination Destination IP in '[x.x.x.x]' format
909 * \param tokenlen OSP token length
910 * \param token OSP token
911 * \param reason Failure reason, output
912 * \param results OSP lookup results, in/output
913 * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
915 static int osp_check_destination(
916 struct osp_provider* provider,
919 const char* destination,
920 unsigned int tokenlen,
922 OSPEFAILREASON* reason,
923 struct osp_results* results)
926 OSPE_DEST_OSPENABLED enabled;
927 OSPE_DEST_PROTOCOL protocol;
928 char dest[OSP_SIZE_NORSTR];
929 OSPE_OPERATOR_NAME type;
932 if ((provider == NULL) || (reason == NULL) || (results == NULL)) {
933 ast_log(LOG_ERROR, "Invalid parameters\n");
937 if ((error = OSPPTransactionIsDestOSPEnabled(results->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) {
938 ast_debug(1, "OSP: Unable to get destination OSP version, error '%d'\n", error);
939 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
943 if (enabled == OSPC_DOSP_FALSE) {
944 results->token[0] = '\0';
946 ast_base64encode(results->token, (const unsigned char*)token, tokenlen, sizeof(results->token) - 1);
949 if ((error = OSPPTransactionGetDestinationNetworkId(results->outhandle, sizeof(results->networkid), results->networkid)) != OSPC_ERR_NO_ERROR) {
950 ast_debug(1, "OSP: Unable to get destination network ID, error '%d'\n", error);
951 results->networkid[0] = '\0';
954 error = OSPPTransactionGetNumberPortabilityParameters(results->outhandle,
955 sizeof(results->nprn),
957 sizeof(results->npcic),
960 if (error != OSPC_ERR_NO_ERROR) {
961 ast_debug(1, "OSP: Unable to get number portability parameters, error '%d'\n", error);
962 results->nprn[0] = '\0';
963 results->npcic[0] = '\0';
967 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
968 error = OSPPTransactionGetOperatorName(results->outhandle, type, sizeof(results->opname[type]), results->opname[type]);
969 if (error != OSPC_ERR_NO_ERROR) {
970 ast_debug(1, "OSP: Unable to get operator name of type '%d', error '%d'\n", type, error);
971 results->opname[type][0] = '\0';
975 if ((error = OSPPTransactionGetDestProtocol(results->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
976 ast_debug(1, "OSP: Unable to get destination protocol, error '%d'\n", error);
977 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
978 results->token[0] = '\0';
979 results->networkid[0] = '\0';
980 results->nprn[0] = '\0';
981 results->npcic[0] = '\0';
983 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
984 results->opname[type][0] = '\0';
990 osp_convert_outin(destination, dest, sizeof(dest));
993 ast_debug(1, "OSP: protocol SIP\n");
994 ast_copy_string(results->tech, OSP_TECH_SIP, sizeof(results->tech));
995 ast_copy_string(results->dest, dest, sizeof(results->dest));
996 ast_copy_string(results->calling, calling, sizeof(results->calling));
997 ast_copy_string(results->called, called, sizeof(results->called));
999 case OSPC_DPROT_Q931:
1000 ast_debug(1, "OSP: protocol Q.931\n");
1001 ast_copy_string(results->tech, OSP_TECH_H323, sizeof(results->tech));
1002 ast_copy_string(results->dest, dest, sizeof(results->dest));
1003 ast_copy_string(results->calling, calling, sizeof(results->calling));
1004 ast_copy_string(results->called, called, sizeof(results->called));
1006 case OSPC_DPROT_IAX:
1007 ast_debug(1, "OSP: protocol IAX\n");
1008 ast_copy_string(results->tech, OSP_TECH_IAX, sizeof(results->tech));
1009 ast_copy_string(results->dest, dest, sizeof(results->dest));
1010 ast_copy_string(results->calling, calling, sizeof(results->calling));
1011 ast_copy_string(results->called, called, sizeof(results->called));
1013 case OSPC_DPROT_SKYPE:
1014 ast_debug(1, "OSP: protocol Skype\n");
1015 ast_copy_string(results->tech, OSP_TECH_SKYPE, sizeof(results->tech));
1016 ast_copy_string(results->dest, dest, sizeof(results->dest));
1017 ast_copy_string(results->calling, calling, sizeof(results->calling));
1018 ast_copy_string(results->called, called, sizeof(results->called));
1020 case OSPC_DPROT_UNDEFINED:
1021 case OSPC_DPROT_UNKNOWN:
1022 ast_debug(1, "OSP: unknown/undefined protocol '%d'\n", protocol);
1023 ast_debug(1, "OSP: use default protocol '%s'\n", provider->defprotocol);
1024 ast_copy_string(results->tech, provider->defprotocol, sizeof(results->tech));
1025 ast_copy_string(results->dest, dest, sizeof(results->dest));
1026 ast_copy_string(results->calling, calling, sizeof(results->calling));
1027 ast_copy_string(results->called, called, sizeof(results->called));
1029 case OSPC_DPROT_LRQ:
1030 case OSPC_DPROT_T37:
1031 case OSPC_DPROT_T38:
1032 case OSPC_DPROT_SMPP:
1033 case OSPC_DPROT_XMPP:
1035 ast_log(LOG_WARNING, "OSP: unsupported protocol '%d'\n", protocol);
1036 *reason = OSPC_FAIL_PROTOCOL_ERROR;
1037 results->token[0] = '\0';
1038 results->networkid[0] = '\0';
1039 results->nprn[0] = '\0';
1040 results->npcic[0] = '\0';
1042 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1043 results->opname[type][0] = '\0';
1053 * \brief Convert Asterisk status to TC code
1054 * \param cause Asterisk hangup cause
1055 * \return OSP TC code
1057 static OSPEFAILREASON asterisk2osp(
1060 return (OSPEFAILREASON)cause;
1064 * \brief OSP Authentication function
1065 * \param name OSP provider context name
1066 * \param trans OSP transaction handle, output
1067 * \param source Source of inbound call
1068 * \param calling Calling number
1069 * \param called Called number
1070 * \param token OSP token, may be empty
1071 * \param timelimit Call duration limit, output
1072 * \return OSP_OK Authenricated, OSP_FAILED Unauthenticated, OSP_ERROR Error
1074 static int osp_auth(
1078 const char* calling,
1081 unsigned int* timelimit)
1084 struct osp_provider* provider = NULL;
1085 char dest[OSP_SIZE_NORSTR];
1087 if ((trans == NULL) || (timelimit == NULL)) {
1088 ast_log(LOG_ERROR, "Invalid parameters\n");
1092 *trans = OSP_INVALID_HANDLE;
1093 *timelimit = OSP_DEF_TIMELIMIT;
1095 if ((res = osp_get_provider(name, &provider)) <= 0) {
1096 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1100 switch (provider->authpolicy) {
1105 if (ast_strlen_zero(token)) {
1107 } else if ((res = osp_create_transaction(name, trans, dest, sizeof(dest))) <= 0) {
1108 ast_debug(1, "OSP: Unable to generate transaction handle\n");
1109 *trans = OSP_INVALID_HANDLE;
1111 } else if((res = osp_validate_token(*trans, source, dest, calling, called, token, timelimit)) <= 0) {
1112 OSPPTransactionRecordFailure(*trans, OSPC_FAIL_CALL_REJECTED);
1117 if (ast_strlen_zero(token)) {
1119 } else if ((res = osp_create_transaction(name, trans, dest, sizeof(dest))) <= 0) {
1120 ast_debug(1, "OSP: Unable to generate transaction handle\n");
1121 *trans = OSP_INVALID_HANDLE;
1123 } else if((res = osp_validate_token(*trans, source, dest, calling, called, token, timelimit)) <= 0) {
1124 OSPPTransactionRecordFailure(*trans, OSPC_FAIL_CALL_REJECTED);
1133 * \brief Create a UUID
1134 * \param uuid UUID buffer
1135 * \param bufsize UUID buffer size
1136 * \return OSK_OK Created, OSP_ERROR Error
1138 static int osp_create_uuid(
1139 unsigned char* uuid,
1140 unsigned int* bufsize)
1143 long int tmp[OSP_SIZE_UUID / sizeof(long int)];
1145 if ((uuid != NULL) && (*bufsize >= OSP_SIZE_UUID)) {
1146 for (i = 0; i < OSP_SIZE_UUID / sizeof(long int); i++) {
1147 tmp[i] = ast_random();
1149 memcpy(uuid, tmp, OSP_SIZE_UUID);
1150 *bufsize = OSP_SIZE_UUID;
1153 ast_log(LOG_ERROR, "Invalid parameters\n");
1161 * \brief UUID to string
1163 * \param buffer String buffer
1164 * \param bufsize String buffer size
1165 * \return OSP_OK Successed, OSP_ERROR Error
1167 static int osp_uuid2str(
1168 unsigned char* uuid,
1170 unsigned int bufsize)
1174 if ((uuid != NULL) && (bufsize > OSP_SIZE_UUIDSTR)) {
1175 snprintf(buffer, bufsize, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1176 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
1177 uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
1180 ast_log(LOG_ERROR, "Invalid parameters\n");
1188 * \brief Create a call ID according to the type
1189 * \param type Call ID type
1190 * \param callid Call ID buffer
1191 * \return OSK_OK Created, OSP_FAILED Not create, OSP_ERROR Error
1193 static int osp_create_callid(
1195 struct osp_callid* callid)
1199 if (callid == NULL) {
1200 ast_log(LOG_ERROR, "Invalid parameters\n");
1204 callid->len = sizeof(callid->buf);
1206 case OSP_CALLID_H323:
1207 res = osp_create_uuid(callid->buf, &callid->len);
1209 case OSP_CALLID_SIP:
1210 case OSP_CALLID_IAX:
1217 if ((res != OSP_OK) && (callid->len != 0)) {
1218 callid->buf[0] = '\0';
1226 * \brief OSP Lookup function
1227 * \param name OSP provider context name
1228 * \param callidtypes Call ID types
1229 * \param srcdev Source device of outbound call
1230 * \param calling Calling number
1231 * \param called Called number
1232 * \param snetid Source network ID
1233 * \param np NP parameters
1234 * \param div SIP Diversion header parameters
1235 * \param cinfo Custom info
1236 * \param results Lookup results
1237 * \return OSP_OK Found , OSP_FAILED No route, OSP_ERROR Error
1239 static int osp_lookup(
1241 unsigned int callidtypes,
1243 const char* calling,
1246 struct osp_npdata* np,
1247 struct osp_diversion* div,
1248 const char* cinfo[],
1249 struct osp_results* results)
1252 struct osp_provider* provider = NULL;
1253 char source[OSP_SIZE_NORSTR];
1254 char callingnum[OSP_SIZE_NORSTR];
1255 char callednum[OSP_SIZE_NORSTR];
1256 char destination[OSP_SIZE_NORSTR];
1257 unsigned int tokenlen;
1258 char token[OSP_SIZE_TOKSTR];
1259 char src[OSP_SIZE_NORSTR];
1260 char dev[OSP_SIZE_NORSTR];
1261 char host[OSP_SIZE_NORSTR];
1262 unsigned int i, type;
1263 struct osp_callid callid;
1264 unsigned int callidnum;
1265 OSPT_CALL_ID* callids[OSP_CALLID_MAXNUM];
1266 char dest[OSP_SIZE_NORSTR];
1267 const char* preferred[2] = { NULL };
1268 unsigned int dummy = 0;
1269 OSPEFAILREASON reason;
1272 if (results == NULL) {
1273 ast_log(LOG_ERROR, "Invalid parameters\n");
1277 osp_convert_inout(results->dest, dest, sizeof(dest));
1279 results->outhandle = OSP_INVALID_HANDLE;
1280 results->tech[0] = '\0';
1281 results->calling[0] = '\0';
1282 results->called[0] = '\0';
1283 results->token[0] = '\0';
1284 results->networkid[0] = '\0';
1285 results->nprn[0] = '\0';
1286 results->npcic[0] = '\0';
1288 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1289 results->opname[type][0] = '\0';
1291 results->numdests = 0;
1292 results->outtimelimit = OSP_DEF_TIMELIMIT;
1294 if ((res = osp_get_provider(name, &provider)) <= 0) {
1295 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1299 if ((res = osp_create_transaction(name, &results->outhandle, source, sizeof(source))) <= 0) {
1300 ast_debug(1, "OSP: Unable to generate transaction handle\n");
1301 results->outhandle = OSP_INVALID_HANDLE;
1302 if (results->inhandle != OSP_INVALID_HANDLE) {
1303 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1308 if (!ast_strlen_zero(snetid)) {
1309 OSPPTransactionSetNetworkIds(results->outhandle, snetid, "");
1312 OSPPTransactionSetNumberPortability(results->outhandle, np->rn, np->cic, np->npdi);
1314 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1315 OSPPTransactionSetOperatorName(results->outhandle, type, np->opname[type]);
1318 osp_convert_inout(div->host, host, sizeof(host));
1319 OSPPTransactionSetDiversion(results->outhandle, div->user, host);
1321 if (cinfo != NULL) {
1322 for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
1323 if (!ast_strlen_zero(cinfo[i])) {
1324 OSPPTransactionSetCustomInfo(results->outhandle, i, cinfo[i]);
1331 for (i = 0; i < OSP_CALLID_MAXNUM; i++) {
1333 if (callidtypes & type) {
1334 error = osp_create_callid(type, &callid);
1336 callids[callidnum] = OSPPCallIdNew(callid.len, callid.buf);
1342 osp_convert_inout(source, src, sizeof(src));
1343 osp_convert_inout(srcdev, dev, sizeof(dev));
1344 if (provider->srvtype == OSP_SRV_NPQUERY) {
1345 OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_NPQUERY);
1346 if (!ast_strlen_zero(dest)) {
1347 preferred[0] = dest;
1349 results->numdests = 1;
1351 OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_VOICE);
1352 results->numdests = OSP_DEF_MAXDESTS;
1354 error = OSPPTransactionRequestAuthorisation(results->outhandle,
1357 calling ? calling : "",
1369 for (i = 0; i < callidnum; i++) {
1370 OSPPCallIdDelete(&callids[i]);
1373 if (error != OSPC_ERR_NO_ERROR) {
1374 ast_log(LOG_WARNING, "OSP: Unable to request authorization, error '%d'\n", error);
1375 results->numdests = 0;
1376 if (results->inhandle != OSP_INVALID_HANDLE) {
1377 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1382 if (!results->numdests) {
1383 ast_debug(1, "OSP: No more destination\n");
1384 if (results->inhandle != OSP_INVALID_HANDLE) {
1385 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1390 results->outcallid.len = sizeof(results->outcallid.buf);
1391 tokenlen = sizeof(token);
1392 error = OSPPTransactionGetFirstDestination(results->outhandle,
1396 &results->outtimelimit,
1397 &results->outcallid.len,
1398 results->outcallid.buf,
1403 sizeof(destination),
1409 if (error != OSPC_ERR_NO_ERROR) {
1410 ast_debug(1, "OSP: Unable to get first route, error '%d'\n", error);
1411 results->numdests = 0;
1412 results->outtimelimit = OSP_DEF_TIMELIMIT;
1413 if (results->inhandle != OSP_INVALID_HANDLE) {
1414 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1419 results->numdests--;
1420 results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
1421 ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
1422 ast_debug(1, "OSP: calling '%s'\n", callingnum);
1423 ast_debug(1, "OSP: called '%s'\n", callednum);
1424 ast_debug(1, "OSP: destination '%s'\n", destination);
1425 ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1427 if ((res = osp_check_destination(provider, callingnum, callednum, destination, tokenlen, token, &reason, results)) > 0) {
1431 if (!results->numdests) {
1432 ast_debug(1, "OSP: No more destination\n");
1433 results->outtimelimit = OSP_DEF_TIMELIMIT;
1434 OSPPTransactionRecordFailure(results->outhandle, reason);
1435 if (results->inhandle != OSP_INVALID_HANDLE) {
1436 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1441 while(results->numdests) {
1442 results->outcallid.len = sizeof(results->outcallid.buf);
1443 tokenlen = sizeof(token);
1444 error = OSPPTransactionGetNextDestination(results->outhandle,
1449 &results->outtimelimit,
1450 &results->outcallid.len,
1451 results->outcallid.buf,
1456 sizeof(destination),
1462 if (error == OSPC_ERR_NO_ERROR) {
1463 results->numdests--;
1464 results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
1465 ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
1466 ast_debug(1, "OSP: calling '%s'\n", callingnum);
1467 ast_debug(1, "OSP: called '%s'\n", callednum);
1468 ast_debug(1, "OSP: destination '%s'\n", destination);
1469 ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1471 if ((res = osp_check_destination(provider, callingnum, callednum, destination, tokenlen, token, &reason, results)) > 0) {
1473 } else if (!results->numdests) {
1474 ast_debug(1, "OSP: No more destination\n");
1475 OSPPTransactionRecordFailure(results->outhandle, reason);
1476 if (results->inhandle != OSP_INVALID_HANDLE) {
1477 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1483 ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
1484 results->numdests = 0;
1485 results->outtimelimit = OSP_DEF_TIMELIMIT;
1486 if (results->inhandle != OSP_INVALID_HANDLE) {
1487 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1498 * \brief OSP Lookup Next function
1499 * \param name OSP provider name
1500 * \param cause Asterisk hangup cuase
1501 * \param results Lookup results, in/output
1502 * \return OSP_OK Found , OSP_FAILED No route, OSP_ERROR Error
1504 static int osp_next(
1507 struct osp_results* results)
1510 struct osp_provider* provider = NULL;
1511 char calling[OSP_SIZE_NORSTR];
1512 char called[OSP_SIZE_NORSTR];
1513 char dest[OSP_SIZE_NORSTR];
1514 unsigned int tokenlen;
1515 char token[OSP_SIZE_TOKSTR];
1516 OSPEFAILREASON reason;
1517 OSPE_OPERATOR_NAME type;
1520 if (results == NULL) {
1521 ast_log(LOG_ERROR, "Invalid parameters\n");
1525 results->tech[0] = '\0';
1526 results->dest[0] = '\0';
1527 results->calling[0] = '\0';
1528 results->called[0] = '\0';
1529 results->token[0] = '\0';
1530 results->networkid[0] = '\0';
1531 results->nprn[0] = '\0';
1532 results->npcic[0] = '\0';
1534 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1535 results->opname[type][0] = '\0';
1537 results->outtimelimit = OSP_DEF_TIMELIMIT;
1539 if ((res = osp_get_provider(name, &provider)) <= 0) {
1540 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1544 if (results->outhandle == OSP_INVALID_HANDLE) {
1545 ast_debug(1, "OSP: Transaction handle undefined\n");
1546 results->numdests = 0;
1547 if (results->inhandle != OSP_INVALID_HANDLE) {
1548 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1553 reason = asterisk2osp(cause);
1555 if (!results->numdests) {
1556 ast_debug(1, "OSP: No more destination\n");
1557 OSPPTransactionRecordFailure(results->outhandle, reason);
1558 if (results->inhandle != OSP_INVALID_HANDLE) {
1559 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1564 while(results->numdests) {
1565 results->outcallid.len = sizeof(results->outcallid.buf);
1566 tokenlen = sizeof(token);
1567 error = OSPPTransactionGetNextDestination(
1573 &results->outtimelimit,
1574 &results->outcallid.len,
1575 results->outcallid.buf,
1586 if (error == OSPC_ERR_NO_ERROR) {
1587 results->numdests--;
1588 results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
1589 ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
1590 ast_debug(1, "OSP: calling '%s'\n", calling);
1591 ast_debug(1, "OSP: called '%s'\n", called);
1592 ast_debug(1, "OSP: destination '%s'\n", dest);
1593 ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1595 if ((res = osp_check_destination(provider, calling, called, dest, tokenlen, token, &reason, results)) > 0) {
1598 } else if (!results->numdests) {
1599 ast_debug(1, "OSP: No more destination\n");
1600 OSPPTransactionRecordFailure(results->outhandle, reason);
1601 if (results->inhandle != OSP_INVALID_HANDLE) {
1602 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1608 ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
1609 results->token[0] = '\0';
1610 results->numdests = 0;
1611 results->outtimelimit = OSP_DEF_TIMELIMIT;
1612 if (results->inhandle != OSP_INVALID_HANDLE) {
1613 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1624 * \brief Get integer from variable string
1625 * \param vstr Variable string
1626 * \return OSP_DEF_INTSTATS Error
1628 static int osp_get_varint(
1632 int value = OSP_DEF_INTSTATS;
1634 if (!ast_strlen_zero(vstr)) {
1635 if ((tmp = strchr(vstr, '=')) != NULL) {
1637 if (sscanf(tmp, "%30d", &value) != 1) {
1638 value = OSP_DEF_INTSTATS;
1647 * \brief Get float from variable string
1648 * \param vstr Variable string
1649 * \return OSP_DEF_FLOATSTATS Error
1651 static float osp_get_varfloat(
1655 float value = OSP_DEF_FLOATSTATS;
1657 if (!ast_strlen_zero(vstr)) {
1658 if ((tmp = strchr(vstr, '=')) != NULL) {
1660 if (sscanf(tmp, "%30f", &value) != 1) {
1661 value = OSP_DEF_FLOATSTATS;
1671 * \param trans OSP in/outbound transaction handle
1672 * \param leg Inbound/outbound
1673 * \param qos QoS string
1674 * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
1676 static int osp_report_qos(
1678 enum osp_callleg leg,
1681 int res = OSP_FAILED;
1682 enum osp_direction dir;
1683 char buffer[OSP_SIZE_NORSTR];
1686 int totalpackets[OSP_DIR_NUMBER];
1687 struct osp_metrics lost[OSP_DIR_NUMBER];
1688 struct osp_metrics jitter[OSP_DIR_NUMBER];
1689 struct osp_metrics rtt;
1692 if (!ast_strlen_zero(qos)) {
1693 for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
1694 totalpackets[dir] = OSP_DEF_INTSTATS;
1697 for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
1698 lost[dir].value = OSP_DEF_INTSTATS;
1699 lost[dir].min = OSP_DEF_FLOATSTATS;
1700 lost[dir].max = OSP_DEF_FLOATSTATS;
1701 lost[dir].avg = OSP_DEF_FLOATSTATS;
1702 lost[dir].sdev = OSP_DEF_FLOATSTATS;
1705 for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
1706 jitter[dir].value = OSP_DEF_INTSTATS;
1707 jitter[dir].min = OSP_DEF_FLOATSTATS;
1708 jitter[dir].max = OSP_DEF_FLOATSTATS;
1709 jitter[dir].avg = OSP_DEF_FLOATSTATS;
1710 jitter[dir].sdev = OSP_DEF_FLOATSTATS;
1713 rtt.value = OSP_DEF_INTSTATS;
1714 rtt.min = OSP_DEF_FLOATSTATS;
1715 rtt.max = OSP_DEF_FLOATSTATS;
1716 rtt.avg = OSP_DEF_FLOATSTATS;
1717 rtt.sdev = OSP_DEF_FLOATSTATS;
1719 ast_copy_string(buffer, qos, sizeof(buffer));
1720 for (item = strtok_r(buffer, ";", &tmp); item; item = strtok_r(NULL, ";", &tmp)) {
1721 if (!strncasecmp(item, "rxcount", strlen("rxcount"))) {
1722 totalpackets[OSP_DIR_RX] = osp_get_varint(item);
1723 } else if (!strncasecmp(item, "txcount", strlen("txcount"))) {
1724 totalpackets[OSP_DIR_TX] = osp_get_varint(item);
1725 } else if (!strncasecmp(item, "lp", strlen("lp"))) {
1726 lost[OSP_DIR_RX].value = osp_get_varint(item);
1727 } else if (!strncasecmp(item, "minrxlost", strlen("minrxlost"))) {
1728 lost[OSP_DIR_RX].min = osp_get_varfloat(item);
1729 } else if (!strncasecmp(item, "maxrxlost", strlen("maxrxlost"))) {
1730 lost[OSP_DIR_RX].max = osp_get_varfloat(item);
1731 } else if (!strncasecmp(item, "avgrxlost", strlen("avgrxlost"))) {
1732 lost[OSP_DIR_RX].avg = osp_get_varfloat(item);
1733 } else if (!strncasecmp(item, "stdevrxlost", strlen("stdevrxlost"))) {
1734 lost[OSP_DIR_RX].sdev = osp_get_varfloat(item);
1735 } else if (!strncasecmp(item, "rlp", strlen("rlp"))) {
1736 lost[OSP_DIR_TX].value = osp_get_varint(item);
1737 } else if (!strncasecmp(item, "reported_minlost", strlen("reported_minlost"))) {
1738 lost[OSP_DIR_TX].min = osp_get_varfloat(item);
1739 } else if (!strncasecmp(item, "reported_maxlost", strlen("reported_maxlost"))) {
1740 lost[OSP_DIR_TX].max = osp_get_varfloat(item);
1741 } else if (!strncasecmp(item, "reported_avglost", strlen("reported_avglost"))) {
1742 lost[OSP_DIR_TX].avg = osp_get_varfloat(item);
1743 } else if (!strncasecmp(item, "reported_stdevlost", strlen("reported_stdevlost"))) {
1744 lost[OSP_DIR_TX].sdev = osp_get_varfloat(item);
1745 } else if (!strncasecmp(item, "rxjitter", strlen("rxjitter"))) {
1746 jitter[OSP_DIR_RX].value = osp_get_varint(item);
1747 } else if (!strncasecmp(item, "minrxjitter", strlen("minrxjitter"))) {
1748 jitter[OSP_DIR_RX].min = osp_get_varfloat(item);
1749 } else if (!strncasecmp(item, "maxrxjitter", strlen("maxrxjitter"))) {
1750 jitter[OSP_DIR_RX].max = osp_get_varfloat(item);
1751 } else if (!strncasecmp(item, "avgrxjitter", strlen("avgjitter"))) {
1752 jitter[OSP_DIR_RX].avg = osp_get_varfloat(item);
1753 } else if (!strncasecmp(item, "stdevrxjitter", strlen("stdevjitter"))) {
1754 jitter[OSP_DIR_RX].sdev = osp_get_varfloat(item);
1755 } else if (!strncasecmp(item, "txjitter", strlen("txjitter"))) {
1756 jitter[OSP_DIR_TX].value = osp_get_varint(item);
1757 } else if (!strncasecmp(item, "reported_minjitter", strlen("reported_minjitter"))) {
1758 jitter[OSP_DIR_TX].min = osp_get_varfloat(item);
1759 } else if (!strncasecmp(item, "reported_maxjitter", strlen("reported_maxjitter"))) {
1760 jitter[OSP_DIR_TX].max = osp_get_varfloat(item);
1761 } else if (!strncasecmp(item, "reported_avgjitter", strlen("reported_avgjitter"))) {
1762 jitter[OSP_DIR_TX].avg = osp_get_varfloat(item);
1763 } else if (!strncasecmp(item, "reported_stdevjitter", strlen("reported_stdevjitter"))) {
1764 jitter[OSP_DIR_TX].sdev = osp_get_varfloat(item);
1765 } else if (!strncasecmp(item, "rtt", strlen("rtt"))) {
1766 rtt.value = osp_get_varint(item);
1767 } else if (!strncasecmp(item, "minrtt", strlen("minrtt"))) {
1768 rtt.min = osp_get_varfloat(item);
1769 } else if (!strncasecmp(item, "maxrtt", strlen("maxrtt"))) {
1770 rtt.max = osp_get_varfloat(item);
1771 } else if (!strncasecmp(item, "avgrtt", strlen("avgrtt"))) {
1772 rtt.avg = osp_get_varfloat(item);
1773 } else if (!strncasecmp(item, "stdevrtt", strlen("stdevrtt"))) {
1774 rtt.sdev = osp_get_varfloat(item);
1778 ast_debug(1, "OSP: call leg '%d'\n", leg);
1779 ast_debug(1, "OSP: rxcount '%d'\n", totalpackets[OSP_DIR_RX]);
1780 ast_debug(1, "OSP: txcount '%d'\n", totalpackets[OSP_DIR_TX]);
1781 ast_debug(1, "OSP: lp '%d'\n",lost[OSP_DIR_RX].value);
1782 ast_debug(1, "OSP: minrxlost '%f'\n", lost[OSP_DIR_RX].min);
1783 ast_debug(1, "OSP: maxrxlost '%f'\n", lost[OSP_DIR_RX].max);
1784 ast_debug(1, "OSP: avgrxlost '%f'\n", lost[OSP_DIR_RX].avg);
1785 ast_debug(1, "OSP: stdevrxlost '%f'\n", lost[OSP_DIR_RX].sdev);
1786 ast_debug(1, "OSP: rlp '%d'\n", lost[OSP_DIR_TX].value);
1787 ast_debug(1, "OSP: reported_minlost '%f'\n", lost[OSP_DIR_TX].min);
1788 ast_debug(1, "OSP: reported_maxlost '%f'\n", lost[OSP_DIR_TX].max);
1789 ast_debug(1, "OSP: reported_avglost '%f'\n", lost[OSP_DIR_TX].avg);
1790 ast_debug(1, "OSP: reported_stdevlost '%f'\n", lost[OSP_DIR_TX].sdev);
1791 ast_debug(1, "OSP: rxjitter '%d'\n", jitter[OSP_DIR_RX].value);
1792 ast_debug(1, "OSP: minrxjitter '%f'\n", jitter[OSP_DIR_RX].min);
1793 ast_debug(1, "OSP: maxrxjitter '%f'\n", jitter[OSP_DIR_RX].max);
1794 ast_debug(1, "OSP: avgrxjitter '%f'\n", jitter[OSP_DIR_RX].avg);
1795 ast_debug(1, "OSP: stdevrxjitter '%f'\n", jitter[OSP_DIR_RX].sdev);
1796 ast_debug(1, "OSP: txjitter '%d'\n", jitter[OSP_DIR_TX].value);
1797 ast_debug(1, "OSP: reported_minjitter '%f'\n", jitter[OSP_DIR_TX].min);
1798 ast_debug(1, "OSP: reported_maxjitter '%f'\n", jitter[OSP_DIR_TX].max);
1799 ast_debug(1, "OSP: reported_avgjitter '%f'\n", jitter[OSP_DIR_TX].avg);
1800 ast_debug(1, "OSP: reported_stdevjitter '%f'\n", jitter[OSP_DIR_TX].sdev);
1801 ast_debug(1, "OSP: rtt '%d'\n", rtt.value);
1802 ast_debug(1, "OSP: minrtt '%f'\n", rtt.min);
1803 ast_debug(1, "OSP: maxrtt '%f'\n", rtt.max);
1804 ast_debug(1, "OSP: avgrtt '%f'\n", rtt.avg);
1805 ast_debug(1, "OSP: stdevrtt '%f'\n", rtt.sdev);
1807 if (leg == OSP_CALL_INBOUND) {
1808 OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_DOWNSTREAM, totalpackets[OSP_DIR_RX]);
1809 OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM, totalpackets[OSP_DIR_TX]);
1810 if (lost[OSP_DIR_RX].value >= 0) {
1811 value = lost[OSP_DIR_RX].value;
1813 value = (int)lost[OSP_DIR_RX].avg;
1815 OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_DOWNSTREAM, value, OSP_DEF_INTSTATS);
1816 if (lost[OSP_DIR_TX].value >= 0) {
1817 value = lost[OSP_DIR_TX].value;
1819 value = (int)lost[OSP_DIR_TX].avg;
1821 OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM, value, OSP_DEF_INTSTATS);
1822 if (jitter[OSP_DIR_RX].value >= 0) {
1823 value = jitter[OSP_DIR_RX].value;
1825 value = (int)jitter[OSP_DIR_RX].avg;
1827 OSPPTransactionSetJitter(trans,
1829 OSPC_SFLOW_DOWNSTREAM,
1831 (int)jitter[OSP_DIR_RX].min,
1832 (int)jitter[OSP_DIR_RX].max,
1833 value, jitter[OSP_DIR_RX].sdev);
1834 if (jitter[OSP_DIR_TX].value >= 0) {
1835 value = jitter[OSP_DIR_TX].value;
1837 value = (int)jitter[OSP_DIR_TX].avg;
1839 OSPPTransactionSetJitter(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM,
1840 OSP_DEF_INTSTATS, (int)jitter[OSP_DIR_TX].min, (int)jitter[OSP_DIR_TX].max, value, jitter[OSP_DIR_TX].sdev);
1842 OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_UPSTREAM, totalpackets[OSP_DIR_RX]);
1843 OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_DOWNSTREAM, totalpackets[OSP_DIR_TX]);
1844 OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_UPSTREAM, lost[OSP_DIR_RX].value, OSP_DEF_INTSTATS);
1845 OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_DOWNSTREAM, lost[OSP_DIR_TX].value, OSP_DEF_INTSTATS);
1846 if (jitter[OSP_DIR_RX].value >= 0) {
1847 value = jitter[OSP_DIR_RX].value;
1849 value = (int)jitter[OSP_DIR_RX].avg;
1851 OSPPTransactionSetJitter(trans,
1853 OSPC_SFLOW_UPSTREAM,
1855 (int)jitter[OSP_DIR_RX].min,
1856 (int)jitter[OSP_DIR_RX].max,
1858 jitter[OSP_DIR_RX].sdev);
1859 if (jitter[OSP_DIR_TX].value >= 0) {
1860 value = jitter[OSP_DIR_TX].value;
1862 value = (int)jitter[OSP_DIR_TX].avg;
1864 OSPPTransactionSetJitter(trans,
1866 OSPC_SFLOW_DOWNSTREAM,
1868 (int)jitter[OSP_DIR_TX].min,
1869 (int)jitter[OSP_DIR_TX].max,
1871 jitter[OSP_DIR_TX].sdev);
1873 if (rtt.value >= 0) {
1876 value = (int)rtt.avg;
1878 OSPPTransactionSetRoundTripDelay(trans, OSP_DEF_INTSTATS, (int)rtt.min, (int)rtt.max, value, rtt.sdev);
1887 * \brief OSP Finish function
1888 * \param trans OSP in/outbound transaction handle
1889 * \param recorded If failure reason has been recorded
1890 * \param cause Asterisk hangup cause
1891 * \param start Call start time
1892 * \param connect Call connect time
1893 * \param end Call end time
1894 * \param release Who release first, 0 source, 1 destination
1895 * \param inqos Inbound QoS string
1896 * \param outqos Outbound QoS string
1897 * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
1899 static int osp_finish(
1906 unsigned int release,
1911 OSPEFAILREASON reason;
1913 unsigned isPddInfoPresent = 0;
1915 unsigned int dummy = 0;
1918 if (trans == OSP_INVALID_HANDLE) {
1923 reason = asterisk2osp(cause);
1924 OSPPTransactionRecordFailure(trans, reason);
1927 osp_report_qos(trans, OSP_CALL_INBOUND, inqos);
1928 osp_report_qos(trans, OSP_CALL_OUTBOUND, outqos);
1930 error = OSPPTransactionReportUsage(trans,
1931 difftime(end, connect),
1946 if (error == OSPC_ERR_NO_ERROR) {
1947 ast_debug(1, "OSP: Usage reported\n");
1950 ast_debug(1, "OSP: Unable to report usage, error '%d'\n", error);
1953 OSPPTransactionDelete(trans);
1958 /* OSP Application APIs */
1961 * \brief OSP Application OSPAuth
1962 * \param chan Channel
1963 * \param data Parameter
1964 * \return OSP_AST_OK Success, OSP_AST_ERROR Error
1966 static int ospauth_exec(
1967 struct ast_channel *chan,
1971 const char* provider = OSP_DEF_PROVIDER;
1972 struct varshead* headp;
1973 struct ast_var_t* current;
1974 const char* source = "";
1975 const char* token = "";
1977 unsigned int timelimit;
1978 char buffer[OSP_SIZE_INTSTR];
1982 AST_DECLARE_APP_ARGS(args,
1983 AST_APP_ARG(provider);
1984 AST_APP_ARG(options);
1987 if (!(tmp = ast_strdupa(data))) {
1988 ast_log(LOG_ERROR, "Out of memory\n");
1989 return OSP_AST_ERROR;
1992 AST_STANDARD_APP_ARGS(args, tmp);
1994 if (!ast_strlen_zero(args.provider)) {
1995 provider = args.provider;
1997 ast_debug(1, "OSPAuth: provider '%s'\n", provider);
1999 headp = &chan->varshead;
2000 AST_LIST_TRAVERSE(headp, current, entries) {
2001 if (!strcasecmp(ast_var_name(current), "OSPINPEERIP")) {
2002 source = ast_var_value(current);
2003 } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
2004 token = ast_var_value(current);
2008 ast_debug(1, "OSPAuth: source '%s'\n", source);
2009 ast_debug(1, "OSPAuth: token size '%zd'\n", strlen(token));
2011 if ((res = osp_auth(provider, &handle, source, chan->cid.cid_num, chan->exten, token, &timelimit)) > 0) {
2012 status = AST_OSP_SUCCESS;
2014 timelimit = OSP_DEF_TIMELIMIT;
2016 status = AST_OSP_FAILED;
2018 status = AST_OSP_ERROR;
2022 snprintf(buffer, sizeof(buffer), "%d", handle);
2023 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
2024 ast_debug(1, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
2025 snprintf(buffer, sizeof(buffer), "%d", timelimit);
2026 pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
2027 ast_debug(1, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
2028 pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
2029 ast_debug(1, "OSPAuth: %s\n", status);
2032 res = OSP_AST_ERROR;
2041 * \brief OSP Application OSPLookup
2042 * \param chan Channel
2043 * \param data Parameter
2044 * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2046 static int osplookup_exec(
2047 struct ast_channel* chan,
2051 const char* provider = OSP_DEF_PROVIDER;
2052 unsigned int callidtypes = OSP_CALLID_UNDEF;
2053 struct varshead* headp;
2054 struct ast_var_t* current;
2055 const char* srcdev = "";
2056 const char* snetid = "";
2057 struct osp_npdata np;
2058 OSPE_OPERATOR_NAME type;
2059 struct osp_diversion div;
2061 const char* cinfo[OSP_MAX_CUSTOMINFO] = { NULL };
2062 char buffer[OSP_SIZE_TOKSTR];
2063 struct osp_results results;
2067 AST_DECLARE_APP_ARGS(args,
2069 AST_APP_ARG(provider);
2070 AST_APP_ARG(options);
2073 if (ast_strlen_zero(data)) {
2074 ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[|provider[|options]])\n");
2075 return OSP_AST_ERROR;
2078 if (!(tmp = ast_strdupa(data))) {
2079 ast_log(LOG_ERROR, "Out of memory\n");
2080 return OSP_AST_ERROR;
2083 AST_STANDARD_APP_ARGS(args, tmp);
2085 ast_debug(1, "OSPLookup: exten '%s'\n", args.exten);
2087 if (!ast_strlen_zero(args.provider)) {
2088 provider = args.provider;
2090 ast_debug(1, "OSPlookup: provider '%s'\n", provider);
2093 if (strchr(args.options, 'h')) {
2094 callidtypes |= OSP_CALLID_H323;
2096 if (strchr(args.options, 's')) {
2097 callidtypes |= OSP_CALLID_SIP;
2099 if (strchr(args.options, 'i')) {
2100 callidtypes |= OSP_CALLID_IAX;
2103 ast_debug(1, "OSPLookup: call id types '%d'\n", callidtypes);
2105 results.inhandle = OSP_INVALID_HANDLE;
2106 results.intimelimit = OSP_DEF_TIMELIMIT;
2107 results.dest[0] = '\0';
2112 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2113 np.opname[type] = "";
2119 headp = &chan->varshead;
2120 AST_LIST_TRAVERSE(headp, current, entries) {
2121 if (!strcasecmp(ast_var_name(current), "OSPINPEERIP")) {
2122 srcdev = ast_var_value(current);
2123 } else if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
2124 if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
2125 results.inhandle = OSP_INVALID_HANDLE;
2127 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
2128 if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
2129 results.intimelimit = OSP_DEF_TIMELIMIT;
2131 } else if (!strcasecmp(ast_var_name(current), "OSPINNETWORKID")) {
2132 snetid = ast_var_value(current);
2133 } else if (!strcasecmp(ast_var_name(current), "OSPINNPRN")) {
2134 np.rn = ast_var_value(current);
2135 } else if (!strcasecmp(ast_var_name(current), "OSPINNPCIC")) {
2136 np.cic = ast_var_value(current);
2137 } else if (!strcasecmp(ast_var_name(current), "OSPINNPDI")) {
2138 if (ast_true(ast_var_value(current))) {
2141 } else if (!strcasecmp(ast_var_name(current), "OSPINSPID")) {
2142 np.opname[OSPC_OPNAME_SPID] = ast_var_value(current);
2143 } else if (!strcasecmp(ast_var_name(current), "OSPINOCN")) {
2144 np.opname[OSPC_OPNAME_OCN] = ast_var_value(current);
2145 } else if (!strcasecmp(ast_var_name(current), "OSPINSPN")) {
2146 np.opname[OSPC_OPNAME_SPN] = ast_var_value(current);
2147 } else if (!strcasecmp(ast_var_name(current), "OSPINALTSPN")) {
2148 np.opname[OSPC_OPNAME_ALTSPN] = ast_var_value(current);
2149 } else if (!strcasecmp(ast_var_name(current), "OSPINMCC")) {
2150 np.opname[OSPC_OPNAME_MCC] = ast_var_value(current);
2151 } else if (!strcasecmp(ast_var_name(current), "OSPINMNC")) {
2152 np.opname[OSPC_OPNAME_MNC] = ast_var_value(current);
2153 } else if (!strcasecmp(ast_var_name(current), "OSPINTOHOST")) {
2154 ast_copy_string(results.dest, ast_var_value(current), sizeof(results.dest));
2155 } else if (!strcasecmp(ast_var_name(current), "OSPINDIVUSER")) {
2156 div.user = ast_var_value(current);
2157 } else if (!strcasecmp(ast_var_name(current), "OSPINDIVHOST")) {
2158 div.host = ast_var_value(current);
2159 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO1")) {
2160 cinfo[0] = ast_var_value(current);
2161 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO2")) {
2162 cinfo[1] = ast_var_value(current);
2163 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO3")) {
2164 cinfo[2] = ast_var_value(current);
2165 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO4")) {
2166 cinfo[3] = ast_var_value(current);
2167 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO5")) {
2168 cinfo[4] = ast_var_value(current);
2169 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO6")) {
2170 cinfo[5] = ast_var_value(current);
2171 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO7")) {
2172 cinfo[6] = ast_var_value(current);
2173 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO8")) {
2174 cinfo[7] = ast_var_value(current);
2177 ast_debug(1, "OSPLookup: source device '%s'\n", srcdev);
2178 ast_debug(1, "OSPLookup: OSPINHANDLE '%d'\n", results.inhandle);
2179 ast_debug(1, "OSPLookup: OSPINTIMELIMIT '%d'\n", results.intimelimit);
2180 ast_debug(1, "OSPLookup: OSPINNETWORKID '%s'\n", snetid);
2181 ast_debug(1, "OSPLookup: OSPINNPRN '%s'\n", np.rn);
2182 ast_debug(1, "OSPLookup: OSPINNPCIC '%s'\n", np.cic);
2183 ast_debug(1, "OSPLookup: OSPINNPDI '%d'\n", np.npdi);
2184 ast_debug(1, "OSPLookup: OSPINSPID '%s'\n", np.opname[OSPC_OPNAME_SPID]);
2185 ast_debug(1, "OSPLookup: OSPINOCN '%s'\n", np.opname[OSPC_OPNAME_OCN]);
2186 ast_debug(1, "OSPLookup: OSPINSPN '%s'\n", np.opname[OSPC_OPNAME_SPN]);
2187 ast_debug(1, "OSPLookup: OSPINALTSPN '%s'\n", np.opname[OSPC_OPNAME_ALTSPN]);
2188 ast_debug(1, "OSPLookup: OSPINMCC '%s'\n", np.opname[OSPC_OPNAME_MCC]);
2189 ast_debug(1, "OSPLookup: OSPINMNC '%s'\n", np.opname[OSPC_OPNAME_MNC]);
2190 ast_debug(1, "OSPLookup: OSPINTOHOST '%s'\n", results.dest);
2191 ast_debug(1, "OSPLookup: OSPINDIVUSER '%s'\n", div.user);
2192 ast_debug(1, "OSPLookup: OSPINDIVHOST'%s'\n", div.host);
2193 for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
2194 if (!ast_strlen_zero(cinfo[i])) {
2195 ast_debug(1, "OSPLookup: OSPINCUSTOMINFO%d '%s'\n", i, cinfo[i]);
2199 if ((cres = ast_autoservice_start(chan)) < 0) {
2200 return OSP_AST_ERROR;
2203 if ((res = osp_lookup(provider, callidtypes, srcdev, chan->cid.cid_num, args.exten, snetid, &np, &div, cinfo, &results)) > 0) {
2204 status = AST_OSP_SUCCESS;
2206 results.tech[0] = '\0';
2207 results.dest[0] = '\0';
2208 results.calling[0] = '\0';
2209 results.called[0] = '\0';
2210 results.token[0] = '\0';
2211 results.networkid[0] = '\0';
2212 results.nprn[0] = '\0';
2213 results.npcic[0] = '\0';
2215 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2216 results.opname[type][0] = '\0';
2218 results.numdests = 0;
2219 results.outtimelimit = OSP_DEF_TIMELIMIT;
2220 results.outcallid.buf[0] = '\0';
2221 results.outcallid.len = 0;
2223 status = AST_OSP_FAILED;
2225 status = AST_OSP_ERROR;
2229 snprintf(buffer, sizeof(buffer), "%d", results.outhandle);
2230 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
2231 ast_debug(1, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
2232 pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.tech);
2233 ast_debug(1, "OSPLookup: OSPOUTTECH '%s'\n", results.tech);
2234 pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
2235 ast_debug(1, "OSPLookup: OSPDESTINATION '%s'\n", results.dest);
2236 pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
2237 ast_debug(1, "OSPLookup: OSPOUTCALLING '%s'\n", results.calling);
2238 pbx_builtin_setvar_helper(chan, "OSPOUTCALLED", results.called);
2239 ast_debug(1, "OSPLookup: OSPOUTCALLED '%s'\n", results.called);
2240 pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", results.networkid);
2241 ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", results.networkid);
2242 pbx_builtin_setvar_helper(chan, "OSPOUTNPRN", results.nprn);
2243 ast_debug(1, "OSPLookup: OSPOUTNPRN '%s'\n", results.nprn);
2244 pbx_builtin_setvar_helper(chan, "OSPOUTNPCIC", results.npcic);
2245 ast_debug(1, "OSPLookup: OSPOUTNPCIC '%s'\n", results.npcic);
2246 snprintf(buffer, sizeof(buffer), "%d", results.npdi);
2247 pbx_builtin_setvar_helper(chan, "OSPOUTNPDI", buffer);
2248 ast_debug(1, "OSPLookup: OSPOUTNPDI'%s'\n", buffer);
2249 pbx_builtin_setvar_helper(chan, "OSPOUTSPID", results.opname[OSPC_OPNAME_SPID]);
2250 ast_debug(1, "OSPLookup: OSPOUTSPID '%s'\n", results.opname[OSPC_OPNAME_SPID]);
2251 pbx_builtin_setvar_helper(chan, "OSPOUTOCN", results.opname[OSPC_OPNAME_OCN]);
2252 ast_debug(1, "OSPLookup: OSPOUTOCN '%s'\n", results.opname[OSPC_OPNAME_OCN]);
2253 pbx_builtin_setvar_helper(chan, "OSPOUTSPN", results.opname[OSPC_OPNAME_SPN]);
2254 ast_debug(1, "OSPLookup: OSPOUTSPN '%s'\n", results.opname[OSPC_OPNAME_SPN]);
2255 pbx_builtin_setvar_helper(chan, "OSPOUTALTSPN", results.opname[OSPC_OPNAME_ALTSPN]);
2256 ast_debug(1, "OSPLookup: OSPOUTALTSPN '%s'\n", results.opname[OSPC_OPNAME_ALTSPN]);
2257 pbx_builtin_setvar_helper(chan, "OSPOUTMCC", results.opname[OSPC_OPNAME_MCC]);
2258 ast_debug(1, "OSPLookup: OSPOUTMCC '%s'\n", results.opname[OSPC_OPNAME_MCC]);
2259 pbx_builtin_setvar_helper(chan, "OSPOUTMNC", results.opname[OSPC_OPNAME_MNC]);
2260 ast_debug(1, "OSPLookup: OSPOUTMNC '%s'\n", results.opname[OSPC_OPNAME_MNC]);
2261 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", results.token);
2262 ast_debug(1, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(results.token));
2263 snprintf(buffer, sizeof(buffer), "%d", results.numdests);
2264 pbx_builtin_setvar_helper(chan, "OSPDESTREMAILS", buffer);
2265 ast_debug(1, "OSPLookup: OSPDESTREMAILS '%s'\n", buffer);
2266 snprintf(buffer, sizeof(buffer), "%d", results.outtimelimit);
2267 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
2268 ast_debug(1, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
2269 snprintf(buffer, sizeof(buffer), "%d", callidtypes);
2270 pbx_builtin_setvar_helper(chan, "OSPOUTCALLIDTYPES", buffer);
2271 ast_debug(1, "OSPLookup: OSPOUTCALLIDTYPES '%s'\n", buffer);
2272 pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
2273 ast_debug(1, "OSPLookup: %s\n", status);
2275 if (!strcasecmp(results.tech, OSP_TECH_SIP)) {
2276 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
2277 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2278 if (!ast_strlen_zero(results.token)) {
2279 snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
2280 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
2281 ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
2283 } else if (!strcasecmp(results.tech, OSP_TECH_H323)) {
2284 if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
2285 osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
2289 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
2290 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
2291 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2292 } else if (!strcasecmp(results.tech, OSP_TECH_IAX)) {
2293 snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.tech, results.dest, results.called);
2294 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2295 } else if (!strcasecmp(results.tech, OSP_TECH_SKYPE)) {
2296 snprintf(buffer, sizeof(buffer), "%s/%s", results.tech, results.called);
2297 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2300 if ((cres = ast_autoservice_stop(chan)) < 0) {
2301 return OSP_AST_ERROR;
2305 res = OSP_AST_ERROR;
2314 * \brief OSP Application OSPNext
2315 * \param chan Channel
2316 * \param data Parameter
2317 * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2319 static int ospnext_exec(
2320 struct ast_channel* chan,
2324 const char* provider = OSP_DEF_PROVIDER;
2326 struct varshead* headp;
2327 struct ast_var_t* current;
2328 struct osp_results results;
2329 OSPE_OPERATOR_NAME type;
2330 char buffer[OSP_SIZE_TOKSTR];
2331 unsigned int callidtypes = OSP_CALLID_UNDEF;
2335 AST_DECLARE_APP_ARGS(args,
2337 AST_APP_ARG(provider);
2338 AST_APP_ARG(options);
2341 if (ast_strlen_zero(data)) {
2342 ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[|provider[|options]])\n");
2343 return OSP_AST_ERROR;
2346 if (!(tmp = ast_strdupa(data))) {
2347 ast_log(LOG_ERROR, "Out of memory\n");
2348 return OSP_AST_ERROR;
2351 AST_STANDARD_APP_ARGS(args, tmp);
2353 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
2356 ast_debug(1, "OSPNext: cause '%d'\n", cause);
2358 if (!ast_strlen_zero(args.provider)) {
2359 provider = args.provider;
2361 ast_debug(1, "OSPlookup: provider '%s'\n", provider);
2363 results.inhandle = OSP_INVALID_HANDLE;
2364 results.outhandle = OSP_INVALID_HANDLE;
2365 results.intimelimit = OSP_DEF_TIMELIMIT;
2366 results.numdests = 0;
2368 headp = &chan->varshead;
2369 AST_LIST_TRAVERSE(headp, current, entries) {
2370 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
2371 if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
2372 results.inhandle = OSP_INVALID_HANDLE;
2374 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
2375 if (sscanf(ast_var_value(current), "%30d", &results.outhandle) != 1) {
2376 results.outhandle = OSP_INVALID_HANDLE;
2378 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
2379 if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
2380 results.intimelimit = OSP_DEF_TIMELIMIT;
2382 } else if (!strcasecmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) {
2383 if (sscanf(ast_var_value(current), "%30d", &callidtypes) != 1) {
2384 callidtypes = OSP_CALLID_UNDEF;
2386 } else if (!strcasecmp(ast_var_name(current), "OSPDESTREMAILS")) {
2387 if (sscanf(ast_var_value(current), "%30d", &results.numdests) != 1) {
2388 results.numdests = 0;
2392 ast_debug(1, "OSPNext: OSPINHANDLE '%d'\n", results.inhandle);
2393 ast_debug(1, "OSPNext: OSPOUTHANDLE '%d'\n", results.outhandle);
2394 ast_debug(1, "OSPNext: OSPINTIMELIMIT '%d'\n", results.intimelimit);
2395 ast_debug(1, "OSPNext: OSPOUTCALLIDTYPES '%d'\n", callidtypes);
2396 ast_debug(1, "OSPNext: OSPDESTREMAILS '%d'\n", results.numdests);
2398 if ((res = osp_next(provider, cause, &results)) > 0) {
2399 status = AST_OSP_SUCCESS;
2401 results.tech[0] = '\0';
2402 results.dest[0] = '\0';
2403 results.calling[0] = '\0';
2404 results.called[0] = '\0';
2405 results.token[0] = '\0';
2406 results.networkid[0] = '\0';
2407 results.nprn[0] = '\0';
2408 results.npcic[0] = '\0';
2410 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2411 results.opname[type][0] = '\0';
2413 results.numdests = 0;
2414 results.outtimelimit = OSP_DEF_TIMELIMIT;
2415 results.outcallid.buf[0] = '\0';
2416 results.outcallid.len = 0;
2418 status = AST_OSP_FAILED;
2420 status = AST_OSP_ERROR;
2424 pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.tech);
2425 ast_debug(1, "OSPNext: OSPOUTTECH '%s'\n", results.tech);
2426 pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
2427 ast_debug(1, "OSPNext: OSPDESTINATION '%s'\n", results.dest);
2428 pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
2429 ast_debug(1, "OSPNext: OSPOUTCALLING '%s'\n", results.calling);
2430 pbx_builtin_setvar_helper(chan, "OSPOUTCALLED", results.called);
2431 ast_debug(1, "OSPNext: OSPOUTCALLED'%s'\n", results.called);
2432 pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", results.networkid);
2433 ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", results.networkid);
2434 pbx_builtin_setvar_helper(chan, "OSPOUTNPRN", results.nprn);
2435 ast_debug(1, "OSPLookup: OSPOUTNPRN '%s'\n", results.nprn);
2436 pbx_builtin_setvar_helper(chan, "OSPOUTNPCIC", results.npcic);
2437 ast_debug(1, "OSPLookup: OSPOUTNPCIC '%s'\n", results.npcic);
2438 snprintf(buffer, sizeof(buffer), "%d", results.npdi);
2439 pbx_builtin_setvar_helper(chan, "OSPOUTNPDI", buffer);
2440 ast_debug(1, "OSPLookup: OSPOUTNPDI'%s'\n", buffer);
2441 pbx_builtin_setvar_helper(chan, "OSPOUTSPID", results.opname[OSPC_OPNAME_SPID]);
2442 ast_debug(1, "OSPLookup: OSPOUTSPID '%s'\n", results.opname[OSPC_OPNAME_SPID]);
2443 pbx_builtin_setvar_helper(chan, "OSPOUTOCN", results.opname[OSPC_OPNAME_OCN]);
2444 ast_debug(1, "OSPLookup: OSPOUTOCN '%s'\n", results.opname[OSPC_OPNAME_OCN]);
2445 pbx_builtin_setvar_helper(chan, "OSPOUTSPN", results.opname[OSPC_OPNAME_SPN]);
2446 ast_debug(1, "OSPLookup: OSPOUTSPN '%s'\n", results.opname[OSPC_OPNAME_SPN]);
2447 pbx_builtin_setvar_helper(chan, "OSPOUTALTSPN", results.opname[OSPC_OPNAME_ALTSPN]);
2448 ast_debug(1, "OSPLookup: OSPOUTALTSPN '%s'\n", results.opname[OSPC_OPNAME_ALTSPN]);
2449 pbx_builtin_setvar_helper(chan, "OSPOUTMCC", results.opname[OSPC_OPNAME_MCC]);
2450 ast_debug(1, "OSPLookup: OSPOUTMCC '%s'\n", results.opname[OSPC_OPNAME_MCC]);
2451 pbx_builtin_setvar_helper(chan, "OSPOUTMNC", results.opname[OSPC_OPNAME_MNC]);
2452 ast_debug(1, "OSPLookup: OSPOUTMNC '%s'\n", results.opname[OSPC_OPNAME_MNC]);
2453 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", results.token);
2454 ast_debug(1, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(results.token));
2455 snprintf(buffer, sizeof(buffer), "%d", results.numdests);
2456 pbx_builtin_setvar_helper(chan, "OSPDESTREMAILS", buffer);
2457 ast_debug(1, "OSPNext: OSPDESTREMAILS '%s'\n", buffer);
2458 snprintf(buffer, sizeof(buffer), "%d", results.outtimelimit);
2459 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
2460 ast_debug(1, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
2461 pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
2462 ast_debug(1, "OSPNext: %s\n", status);
2464 if (!strcasecmp(results.tech, OSP_TECH_SIP)) {
2465 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
2466 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2467 if (!ast_strlen_zero(results.token)) {
2468 snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
2469 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
2470 ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
2472 } else if (!strcasecmp(results.tech, OSP_TECH_H323)) {
2473 if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
2474 osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
2478 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
2479 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
2480 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2481 } else if (!strcasecmp(results.tech, OSP_TECH_IAX)) {
2482 snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.tech, results.dest, results.called);
2483 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2484 } else if (!strcasecmp(results.tech, OSP_TECH_SKYPE)) {
2485 snprintf(buffer, sizeof(buffer), "%s/%s", results.tech, results.called);
2486 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2490 res = OSP_AST_ERROR;
2499 * \brief OSP Application OSPFinish
2500 * \param chan Channel
2501 * \param data Parameter
2502 * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2504 static int ospfinished_exec(
2505 struct ast_channel* chan,
2510 struct varshead* headp;
2511 struct ast_var_t* current;
2512 int inhandle = OSP_INVALID_HANDLE;
2513 int outhandle = OSP_INVALID_HANDLE;
2515 time_t start, connect, end;
2516 unsigned int release;
2517 char buffer[OSP_SIZE_INTSTR];
2518 char inqos[OSP_SIZE_QOSSTR] = { 0 };
2519 char outqos[OSP_SIZE_QOSSTR] = { 0 };
2523 AST_DECLARE_APP_ARGS(args,
2525 AST_APP_ARG(options);
2528 if (!(tmp = ast_strdupa(data))) {
2529 ast_log(LOG_ERROR, "Out of memory\n");
2530 return OSP_AST_ERROR;
2533 AST_STANDARD_APP_ARGS(args, tmp);
2535 headp = &chan->varshead;
2536 AST_LIST_TRAVERSE(headp, current, entries) {
2537 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
2538 if (sscanf(ast_var_value(current), "%30d", &inhandle) != 1) {
2539 inhandle = OSP_INVALID_HANDLE;
2541 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
2542 if (sscanf(ast_var_value(current), "%30d", &outhandle) != 1) {
2543 outhandle = OSP_INVALID_HANDLE;
2545 } else if (!recorded &&
2546 (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") ||
2547 !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") ||
2548 !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS")))
2550 if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) {
2553 } else if (!strcasecmp(ast_var_name(current), "OSPINAUDIOQOS")) {
2554 ast_copy_string(inqos, ast_var_value(current), sizeof(inqos));
2555 } else if (!strcasecmp(ast_var_name(current), "OSPOUTAUDIOQOS")) {
2556 ast_copy_string(outqos, ast_var_value(current), sizeof(outqos));
2559 ast_debug(1, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
2560 ast_debug(1, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
2561 ast_debug(1, "OSPFinish: recorded '%d'\n", recorded);
2562 ast_debug(1, "OSPFinish: OSPINAUDIOQOS '%s'\n", inqos);
2563 ast_debug(1, "OSPFinish: OSPOUTAUDIOQOS '%s'\n", outqos);
2565 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
2568 ast_debug(1, "OSPFinish: cause '%d'\n", cause);
2571 start = chan->cdr->start.tv_sec;
2572 connect = chan->cdr->answer.tv_sec;
2583 ast_debug(1, "OSPFinish: start '%ld'\n", start);
2584 ast_debug(1, "OSPFinish: connect '%ld'\n", connect);
2585 ast_debug(1, "OSPFinish: end '%ld'\n", end);
2587 release = ast_check_hangup(chan) ? 0 : 1;
2589 if (osp_finish(outhandle, recorded, cause, start, connect, end, release, inqos, outqos) <= 0) {
2590 ast_debug(1, "OSPFinish: Unable to report usage for outbound call\n");
2593 case AST_CAUSE_NORMAL_CLEARING:
2596 cause = AST_CAUSE_NO_ROUTE_DESTINATION;
2599 if (osp_finish(inhandle, recorded, cause, start, connect, end, release, inqos, outqos) <= 0) {
2600 ast_debug(1, "OSPFinish: Unable to report usage for inbound call\n");
2602 snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
2603 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
2604 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
2607 status = AST_OSP_SUCCESS;
2609 status = AST_OSP_FAILED;
2611 status = AST_OSP_ERROR;
2613 pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
2616 res = OSP_AST_ERROR;
2624 /* OSP Module APIs */
2626 static int osp_unload(void)
2628 struct osp_provider* provider;
2629 struct osp_provider* next;
2631 if (osp_initialized) {
2632 ast_mutex_lock(&osp_lock);
2633 for (provider = osp_providers; provider; provider = next) {
2634 next = provider->next;
2635 OSPPProviderDelete(provider->handle, 0);
2638 osp_providers = NULL;
2639 ast_mutex_unlock(&osp_lock);
2643 osp_tokenformat = TOKEN_ALGO_SIGNED;
2646 osp_initialized = 0;
2652 static int osp_load(int reload)
2656 struct ast_config* cfg;
2657 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2658 int error = OSPC_ERR_NO_ERROR;
2660 if ((cfg = ast_config_load(OSP_CONFIG_FILE, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
2662 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2663 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", OSP_CONFIG_FILE);
2672 if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate")) && ast_true(cvar)) {
2673 if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
2674 ast_log(LOG_WARNING, "OSP: Unable to enable hardware accelleration\n");
2682 ast_debug(1, "OSP: osp_hardware '%d'\n", osp_hardware);
2684 if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "securityfeatures")) && ast_true(cvar)) {
2687 ast_debug(1, "OSP: osp_security '%d'\n", osp_security);
2690 if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat"))) {
2691 if ((sscanf(cvar, "%30d", &ivar) == 1) &&
2692 ((ivar == TOKEN_ALGO_SIGNED) || (ivar == TOKEN_ALGO_UNSIGNED) || (ivar == TOKEN_ALGO_BOTH)))
2694 osp_tokenformat = ivar;
2696 ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n",
2697 TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, cvar);
2700 ast_debug(1, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
2702 for (cvar = ast_category_browse(cfg, NULL); cvar != NULL; cvar = ast_category_browse(cfg, cvar)) {
2703 if (strcasecmp(cvar, OSP_GENERAL_CAT)) {
2704 osp_create_provider(cfg, cvar);
2708 osp_initialized = 1;
2710 ast_config_destroy(cfg);
2712 ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
2715 ast_debug(1, "OSP: osp_initialized '%d'\n", osp_initialized);
2720 static char *handle_cli_osp_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2724 struct osp_provider* provider;
2725 const char* name = NULL;
2726 const char* tokenalgo;
2730 e->command = "osp show";
2733 " Displays information on Open Settlement Protocol support\n";
2739 if ((a->argc < 2) || (a->argc > 3)) {
2740 return CLI_SHOWUSAGE;
2748 switch (osp_tokenformat) {
2749 case TOKEN_ALGO_BOTH:
2752 case TOKEN_ALGO_UNSIGNED:
2753 tokenalgo = "Unsigned";
2755 case TOKEN_ALGO_SIGNED:
2757 tokenalgo = "Signed";
2760 ast_cli(a->fd, "OSP: %s/%s/%s/%s\n",
2761 osp_initialized ? "Initialized" : "Uninitialized",
2762 osp_hardware ? "Accelerated" : "Normal",
2763 osp_security ? "Enabled" : "Disabled",
2767 ast_mutex_lock(&osp_lock);
2768 for (provider = osp_providers; provider; provider = provider->next) {
2769 if (!name || !strcasecmp(provider->name, name)) {
2771 ast_cli(a->fd, "\n");
2773 ast_cli(a->fd, " == OSP Provider '%s' == \n", provider->name);
2775 ast_cli(a->fd, "Local Private Key: %s\n", provider->privatekey);
2776 ast_cli(a->fd, "Local Certificate: %s\n", provider->localcert);
2777 for (i = 0; i < provider->canum; i++) {
2778 ast_cli(a->fd, "CA Certificate %d: %s\n", i + 1, provider->cacerts[i]);
2781 for (i = 0; i < provider->spnum; i++) {
2782 ast_cli(a->fd, "Service Point %d: %s\n", i + 1, provider->spoints[i]);
2784 ast_cli(a->fd, "Max Connections: %d\n", provider->maxconnect);
2785 ast_cli(a->fd, "Retry Delay: %d seconds\n", provider->retrydelay);
2786 ast_cli(a->fd, "Retry Limit: %d\n", provider->retrylimit);
2787 ast_cli(a->fd, "Timeout: %d milliseconds\n", provider->timeout);
2788 ast_cli(a->fd, "Source: %s\n", strlen(provider->source) ? provider->source : "<unspecified>");
2789 ast_cli(a->fd, "Auth Policy %d\n", provider->authpolicy);
2790 ast_cli(a->fd, "Default protocol %s\n", provider->defprotocol);
2791 ast_cli(a->fd, "Service type %d\n", provider->srvtype);
2792 ast_cli(a->fd, "OSP Handle: %d\n", provider->handle);
2796 ast_mutex_unlock(&osp_lock);
2800 ast_cli(a->fd, "Unable to find OSP provider '%s'\n", name);
2802 ast_cli(a->fd, "No OSP providers configured\n");
2809 /* OSPAuth() dialplan application */
2810 static const char app1[] = "OSPAuth";
2812 /* OSPLookup() dialplan application */
2813 static const char app2[] = "OSPLookup";
2815 /* OSPNext() dialplan application */
2816 static const char app3[] = "OSPNext";
2818 /* OSPFinish() dialplan application */
2819 static const char app4[] = "OSPFinish";
2821 static struct ast_cli_entry cli_osp[] = {
2822 AST_CLI_DEFINE(handle_cli_osp_show, "Displays OSF information")
2825 static int load_module(void)
2830 return AST_MODULE_LOAD_DECLINE;
2832 ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
2833 res = ast_register_application_xml(app1, ospauth_exec);
2834 res |= ast_register_application_xml(app2, osplookup_exec);
2835 res |= ast_register_application_xml(app3, ospnext_exec);
2836 res |= ast_register_application_xml(app4, ospfinished_exec);
2841 static int unload_module(void)
2845 res = ast_unregister_application(app4);
2846 res |= ast_unregister_application(app3);
2847 res |= ast_unregister_application(app2);
2848 res |= ast_unregister_application(app1);
2849 ast_cli_unregister_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
2855 static int reload(void)
2862 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
2863 .load = load_module,
2864 .unload = unload_module,