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>
34 <support_level>extended</support_level>
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
42 #include <osp/osputils.h>
43 #include <osp/ospb64.h>
45 #include "asterisk/paths.h"
46 #include "asterisk/lock.h"
47 #include "asterisk/config.h"
48 #include "asterisk/utils.h"
49 #include "asterisk/causes.h"
50 #include "asterisk/channel.h"
51 #include "asterisk/app.h"
52 #include "asterisk/module.h"
53 #include "asterisk/pbx.h"
54 #include "asterisk/cli.h"
55 #include "asterisk/astosp.h"
58 <application name="OSPAuth" language="en_US">
63 <parameter name="provider">
64 <para>The name of the provider that authenticates the call.</para>
66 <parameter name="options">
67 <para>Reserverd.</para>
71 <para>Authenticate a call by OSP.</para>
72 <para>Input variables:</para>
74 <variable name="OSPINPEERIP">
75 <para>The last hop IP address.</para>
77 <variable name="OSPINTOKEN">
78 <para>The inbound OSP token.</para>
81 <para>Output variables:</para>
83 <variable name="OSPINHANDLE">
84 <para>The inbound call OSP transaction handle.</para>
86 <variable name="OSPINTIMELIMIT">
87 <para>The inbound call duration limit in seconds.</para>
90 <para>This application sets the following channel variable upon completion:</para>
92 <variable name="OSPAUTHSTATUS">
93 <para>The status of OSPAuth attempt as a text string, one of</para>
94 <value name="SUCCESS" />
95 <value name="FAILED" />
96 <value name="ERROR" />
101 <ref type="application">OSPLookup</ref>
102 <ref type="application">OSPNext</ref>
103 <ref type="application">OSPFinish</ref>
106 <application name="OSPLookup" language="en_US">
108 Lookup destination by OSP.
111 <parameter name="exten" required="true">
112 <para>The exten of the call.</para>
114 <parameter name="provider">
115 <para>The name of the provider that is used to route the call.</para>
117 <parameter name="options">
120 <para>generate H323 call id for the outbound call</para>
123 <para>generate SIP call id for the outbound call. Have not been implemented</para>
126 <para>generate IAX call id for the outbound call. Have not been implemented</para>
132 <para>Looks up destination via OSP.</para>
133 <para>Input variables:</para>
135 <variable name="OSPINACTUALSRC">
136 <para>The actual source device IP address in indirect mode.</para>
138 <variable name="OSPINPEERIP">
139 <para>The last hop IP address.</para>
141 <variable name="OSPINHANDLE">
142 <para>The inbound call OSP transaction handle.</para>
144 <variable name="OSPINTIMELIMIT">
145 <para>The inbound call duration limit in seconds.</para>
147 <variable name="OSPINNETWORKID">
148 <para>The inbound source network ID.</para>
150 <variable name="OSPINNPRN">
151 <para>The inbound routing number.</para>
153 <variable name="OSPINNPCIC">
154 <para>The inbound carrier identification code.</para>
156 <variable name="OSPINNPDI">
157 <para>The inbound number portability database dip indicator.</para>
159 <variable name="OSPINSPID">
160 <para>The inbound service provider identity.</para>
162 <variable name="OSPINOCN">
163 <para>The inbound operator company number.</para>
165 <variable name="OSPINSPN">
166 <para>The inbound service provider name.</para>
168 <variable name="OSPINALTSPN">
169 <para>The inbound alternate service provider name.</para>
171 <variable name="OSPINMCC">
172 <para>The inbound mobile country code.</para>
174 <variable name="OSPINMNC">
175 <para>The inbound mobile network code.</para>
177 <variable name="OSPINTOHOST">
178 <para>The inbound To header host part.</para>
180 <variable name="OSPINDIVUSER">
181 <para>The inbound Diversion header user part.</para>
183 <variable name="OSPINDIVHOST">
184 <para>The inbound Diversion header host part.</para>
186 <variable name="OSPINCUSTOMINFOn">
187 <para>The inbound custom information, where <literal>n</literal> is the index beginning with <literal>1</literal>
188 upto <literal>8</literal>.</para>
191 <para>Output variables:</para>
193 <variable name="OSPOUTHANDLE">
194 <para>The outbound call OSP transaction handle.</para>
196 <variable name="OSPOUTTECH">
197 <para>The outbound channel technology for the call.</para>
199 <variable name="OSPDESTINATION">
200 <para>The outbound destination IP address.</para>
202 <variable name="OSPOUTCALLING">
203 <para>The outbound calling number.</para>
205 <variable name="OSPOUTCALLED">
206 <para>The outbound called number.</para>
208 <variable name="OSPOUTNETWORKID">
209 <para>The outbound destination network ID.</para>
211 <variable name="OSPOUTNPRN">
212 <para>The outbound routing number.</para>
214 <variable name="OSPOUTNPCIC">
215 <para>The outbound carrier identification code.</para>
217 <variable name="OSPOUTNPDI">
218 <para>The outbound number portability database dip indicator.</para>
220 <variable name="OSPOUTSPID">
221 <para>The outbound service provider identity.</para>
223 <variable name="OSPOUTOCN">
224 <para>The outbound operator company number.</para>
226 <variable name="OSPOUTSPN">
227 <para>The outbound service provider name.</para>
229 <variable name="OSPOUTALTSPN">
230 <para>The outbound alternate service provider name.</para>
232 <variable name="OSPOUTMCC">
233 <para>The outbound mobile country code.</para>
235 <variable name="OSPOUTMNC">
236 <para>The outbound mobile network code.</para>
238 <variable name="OSPOUTTOKEN">
239 <para>The outbound OSP token.</para>
241 <variable name="OSPDESTREMAILS">
242 <para>The number of remained destinations.</para>
244 <variable name="OSPOUTTIMELIMIT">
245 <para>The outbound call duration limit in seconds.</para>
247 <variable name="OSPOUTCALLIDTYPES">
248 <para>The outbound Call-ID types.</para>
250 <variable name="OSPOUTCALLID">
251 <para>The outbound Call-ID. Only for H.323.</para>
253 <variable name="OSPDIALSTR">
254 <para>The outbound Dial command string.</para>
257 <para>This application sets the following channel variable upon completion:</para>
259 <variable name="OSPLOOKUPSTATUS">
260 <para>The status of OSPLookup attempt as a text string, one of</para>
261 <value name="SUCCESS" />
262 <value name="FAILED" />
263 <value name="ERROR" />
268 <ref type="application">OSPAuth</ref>
269 <ref type="application">OSPNext</ref>
270 <ref type="application">OSPFinish</ref>
273 <application name="OSPNext" language="en_US">
275 Lookup next destination by OSP.
278 <para>Looks up the next destination via OSP.</para>
279 <para>Input variables:</para>
281 <variable name="OSPINHANDLE">
282 <para>The inbound call OSP transaction handle.</para>
284 <variable name="OSPOUTHANDLE">
285 <para>The outbound call OSP transaction handle.</para>
287 <variable name="OSPINTIMELIMIT">
288 <para>The inbound call duration limit in seconds.</para>
290 <variable name="OSPOUTCALLIDTYPES">
291 <para>The outbound Call-ID types.</para>
293 <variable name="OSPDESTREMAILS">
294 <para>The number of remained destinations.</para>
297 <para>Output variables:</para>
299 <variable name="OSPOUTTECH">
300 <para>The outbound channel technology.</para>
302 <variable name="OSPDESTINATION">
303 <para>The destination IP address.</para>
305 <variable name="OSPOUTCALLING">
306 <para>The outbound calling number.</para>
308 <variable name="OSPOUTCALLED">
309 <para>The outbound called number.</para>
311 <variable name="OSPOUTNETWORKID">
312 <para>The outbound destination network ID.</para>
314 <variable name="OSPOUTNPRN">
315 <para>The outbound routing number.</para>
317 <variable name="OSPOUTNPCIC">
318 <para>The outbound carrier identification code.</para>
320 <variable name="OSPOUTNPDI">
321 <para>The outbound number portability database dip indicator.</para>
323 <variable name="OSPOUTSPID">
324 <para>The outbound service provider identity.</para>
326 <variable name="OSPOUTOCN">
327 <para>The outbound operator company number.</para>
329 <variable name="OSPOUTSPN">
330 <para>The outbound service provider name.</para>
332 <variable name="OSPOUTALTSPN">
333 <para>The outbound alternate service provider name.</para>
335 <variable name="OSPOUTMCC">
336 <para>The outbound mobile country code.</para>
338 <variable name="OSPOUTMNC">
339 <para>The outbound mobile network code.</para>
341 <variable name="OSPOUTTOKEN">
342 <para>The outbound OSP token.</para>
344 <variable name="OSPDESTREMAILS">
345 <para>The number of remained destinations.</para>
347 <variable name="OSPOUTTIMELIMIT">
348 <para>The outbound call duration limit in seconds.</para>
350 <variable name="OSPOUTCALLID">
351 <para>The outbound Call-ID. Only for H.323.</para>
353 <variable name="OSPDIALSTR">
354 <para>The outbound Dial command string.</para>
357 <para>This application sets the following channel variable upon completion:</para>
359 <variable name="OSPNEXTSTATUS">
360 <para>The status of the OSPNext attempt as a text string, one of</para>
361 <value name="SUCCESS" />
362 <value name="FAILED" />
363 <value name="ERROR" />
368 <ref type="application">OSPAuth</ref>
369 <ref type="application">OSPLookup</ref>
370 <ref type="application">OSPFinish</ref>
373 <application name="OSPFinish" language="en_US">
378 <parameter name="cause">
379 <para>Hangup cause.</para>
381 <parameter name="options">
382 <para>Reserved.</para>
386 <para>Report call state.</para>
387 <para>Input variables:</para>
389 <variable name="OSPINHANDLE">
390 <para>The inbound call OSP transaction handle.</para>
392 <variable name="OSPOUTHANDLE">
393 <para>The outbound call OSP transaction handle.</para>
395 <variable name="OSPAUTHSTATUS">
396 <para>The OSPAuth status.</para>
398 <variable name="OSPLOOKUPSTATUS">
399 <para>The OSPLookup status.</para>
401 <variable name="OSPNEXTSTATUS">
402 <para>The OSPNext status.</para>
404 <variable name="OSPINAUDIOQOS">
405 <para>The inbound call leg audio QoS string.</para>
407 <variable name="OSPOUTAUDIOQOS">
408 <para>The outbound call leg audio QoS string.</para>
411 <para>This application sets the following channel variable upon completion:</para>
413 <variable name="OSPFINISHSTATUS">
414 <para>The status of the OSPFinish attempt as a text string, one of</para>
415 <value name="SUCCESS" />
416 <value name="FAILED" />
417 <value name="ERROR" />
422 <ref type="application">OSPAuth</ref>
423 <ref type="application">OSPLookup</ref>
424 <ref type="application">OSPNext</ref>
429 /* OSP Buffer Sizes */
430 #define OSP_SIZE_INTSTR ((unsigned int)16) /* OSP signed/unsigned int string buffer size */
431 #define OSP_SIZE_NORSTR ((unsigned int)256) /* OSP normal string buffer size */
432 #define OSP_SIZE_KEYSTR ((unsigned int)1024) /* OSP certificate string buffer size */
433 #define OSP_SIZE_TOKSTR ((unsigned int)4096) /* OSP token string buffer size */
434 #define OSP_SIZE_TECHSTR ((unsigned int)32) /* OSP signed/unsigned int string buffer size */
435 #define OSP_SIZE_UUID ((unsigned int)16) /* UUID size */
436 #define OSP_SIZE_UUIDSTR ((unsigned int)36) /* UUID string size */
437 #define OSP_SIZE_QOSSTR ((unsigned int)1024) /* QoS string buffer size */
440 #define OSP_CALLID_UNDEF ((unsigned int)0) /* Undefined */
441 #define OSP_CALLID_SIP ((unsigned int)(1 << 0)) /* SIP */
442 #define OSP_CALLID_H323 ((unsigned int)(1 << 1)) /* H.323 */
443 #define OSP_CALLID_IAX ((unsigned int)(1 << 2)) /* IAX2 */
444 #define OSP_CALLID_MAXNUM ((unsigned int)3) /* Max number of call ID types */
446 /* OSP Supported Destination Protocols */
447 #define OSP_PROT_SIP ((const char*)"SIP") /* SIP protocol name */
448 #define OSP_PROT_H323 ((const char*)"H323") /* H.323 Q.931 protocol name*/
449 #define OSP_PROT_IAX ((const char*)"IAX") /* IAX2 protocol name */
450 #define OSP_PROT_SKYPE ((const char*)"SKYPE") /* Skype protocol name */
452 /* OSP supported Destination Tech */
453 #define OSP_TECH_SIP ((const char*)"SIP") /* SIP tech name */
454 #define OSP_TECH_H323 ((const char*)"H323") /* OH323 tech name */
455 #define OSP_TECH_IAX ((const char*)"IAX2") /* IAX2 tech name */
456 #define OSP_TECH_SKYPE ((const char*)"SKYPE") /* Skype tech name */
458 /* SIP OSP header field name */
459 #define OSP_SIP_HEADER ((const char*)"P-OSP-Auth-Token")
461 /* OSP Authentication Policy */
462 enum osp_authpolicy {
463 OSP_AUTH_NO = 0, /* Accept any call */
464 OSP_AUTH_YES, /* Accept call with valid OSP token or without OSP token */
465 OSP_AUTH_EXC /* Only accept call with valid OSP token */
470 OSP_MODE_DIRECT= 0, /* Direct */
471 OSP_MODE_INDIRECT /* Indirect */
474 /* OSP Service Type */
476 OSP_SRV_VOICE = 0, /* Normal voice service */
477 OSP_SRV_NPQUERY /* Ported number query service */
481 #define OSP_OK ((int)1) /* OSP function call successful */
482 #define OSP_FAILED ((int)0) /* OSP function call failed */
483 #define OSP_ERROR ((int)-1) /* OSP function call error */
484 #define OSP_AST_OK ((int)0) /* Asterisk function call successful */
485 #define OSP_AST_ERROR ((int)-1) /* Asterisk function call error */
486 #define OSP_INVALID_HANDLE ((int)-1) /* Invalid OSP handle, provider, transaction etc. */
487 #define OSP_CONFIG_FILE ((const char*)"osp.conf") /* OSP configuration file name */
488 #define OSP_GENERAL_CAT ((const char*)"general") /* OSP global configuration context name */
489 #define OSP_DEF_PROVIDER ((const char*)"default") /* OSP default provider context name */
490 #define OSP_MAX_CERTS ((unsigned int)10) /* OSP max number of cacerts */
491 #define OSP_MAX_SPOINTS ((unsigned int)10) /* OSP max number of service points */
492 #define OSP_DEF_MAXCONNECT ((unsigned int)20) /* OSP default max_connections */
493 #define OSP_MIN_MAXCONNECT ((unsigned int)1) /* OSP min max_connections */
494 #define OSP_MAX_MAXCONNECT ((unsigned int)1000) /* OSP max max_connections */
495 #define OSP_DEF_RETRYDELAY ((unsigned int)0) /* OSP default retry delay */
496 #define OSP_MIN_RETRYDELAY ((unsigned int)0) /* OSP min retry delay */
497 #define OSP_MAX_RETRYDELAY ((unsigned int)10) /* OSP max retry delay */
498 #define OSP_DEF_RETRYLIMIT ((unsigned int)2) /* OSP default retry times */
499 #define OSP_MIN_RETRYLIMIT ((unsigned int)0) /* OSP min retry times */
500 #define OSP_MAX_RETRYLIMIT ((unsigned int)100) /* OSP max retry times */
501 #define OSP_DEF_TIMEOUT ((unsigned int)500) /* OSP default timeout in ms */
502 #define OSP_MIN_TIMEOUT ((unsigned int)200) /* OSP min timeout in ms */
503 #define OSP_MAX_TIMEOUT ((unsigned int)10000) /* OSP max timeout in ms */
504 #define OSP_DEF_AUTHPOLICY OSP_AUTH_YES /* OSP default auth policy, yes */
505 #define OSP_AUDIT_URL ((const char*)"localhost") /* OSP default Audit URL */
506 #define OSP_LOCAL_VALIDATION ((int)1) /* Validate OSP token locally */
507 #define OSP_SSL_LIFETIME ((unsigned int)300) /* SSL life time, in seconds */
508 #define OSP_HTTP_PERSISTENCE ((int)1) /* In seconds */
509 #define OSP_CUSTOMER_ID ((const char*)"") /* OSP customer ID */
510 #define OSP_DEVICE_ID ((const char*)"") /* OSP device ID */
511 #define OSP_DEF_MAXDESTS ((unsigned int)5) /* OSP default max number of destinations */
512 #define OSP_DEF_TIMELIMIT ((unsigned int)0) /* OSP default duration limit, no limit */
513 #define OSP_DEF_PROTOCOL OSP_PROT_SIP /* OSP default destination protocol, SIP */
514 #define OSP_DEF_WORKMODE OSP_MODE_DIRECT /* OSP default work mode, direct */
515 #define OSP_DEF_SRVTYPE OSP_SRV_VOICE /* OSP default service type, voice */
516 #define OSP_MAX_CUSTOMINFO ((unsigned int)8) /* OSP max number of custom info */
517 #define OSP_DEF_INTSTATS ((int)-1) /* OSP default int statistic */
518 #define OSP_DEF_FLOATSTATS ((float)-1) /* OSP default float statistic */
521 struct osp_provider {
522 OSPTPROVHANDLE handle; /* OSP provider handle */
523 char name[OSP_SIZE_NORSTR]; /* OSP provider context name */
524 char privatekey[OSP_SIZE_NORSTR]; /* OSP private key file name */
525 char localcert[OSP_SIZE_NORSTR]; /* OSP local cert file name */
526 unsigned int canum; /* Number of cacerts */
527 char cacerts[OSP_MAX_CERTS][OSP_SIZE_NORSTR]; /* Cacert file names */
528 unsigned int spnum; /* Number of service points */
529 char spoints[OSP_MAX_SPOINTS][OSP_SIZE_NORSTR]; /* Service point URLs */
530 unsigned int maxconnect; /* Max number of connections */
531 unsigned int retrydelay; /* Retry delay */
532 unsigned int retrylimit; /* Retry limit */
533 unsigned int timeout; /* Timeout in ms */
534 char source[OSP_SIZE_NORSTR]; /* IP of self */
535 enum osp_authpolicy authpolicy; /* OSP authentication policy */
536 const char* defprotocol; /* OSP default destination protocol */
537 enum osp_workmode workmode; /* OSP work mode */
538 enum osp_srvtype srvtype; /* OSP service type */
539 struct osp_provider* next; /* Pointer to next OSP provider */
544 unsigned char buf[OSP_SIZE_NORSTR]; /* Call ID string */
545 unsigned int len; /* Call ID length */
548 /* Number Portability Data */
550 const char* rn; /* Rounding Number */
551 const char* cic; /* Carrier Identification Code */
552 int npdi; /* NP Database Dip Indicator */
553 const char* opname[OSPC_OPNAME_NUMBER]; /* Operator Names */
556 /* SIP Diversion Header Parameters */
557 struct osp_diversion {
558 const char* user; /* Diversion header user info */
559 const char* host; /* Diversion header host info */
562 /* OSP Application In/Output Results */
564 int inhandle; /* Inbound transaction handle */
565 int outhandle; /* Outbound transaction handle */
566 unsigned int intimelimit; /* Inbound duration limit */
567 unsigned int outtimelimit; /* Outbound duration limit */
568 char tech[OSP_SIZE_TECHSTR]; /* Outbound Asterisk TECH string */
569 char dest[OSP_SIZE_NORSTR]; /* Outbound destination IP address */
570 char calling[OSP_SIZE_NORSTR]; /* Outbound calling number, may be translated */
571 char called[OSP_SIZE_NORSTR]; /* Outbound called number, may be translated */
572 char token[OSP_SIZE_TOKSTR]; /* Outbound OSP token */
573 char networkid[OSP_SIZE_NORSTR]; /* Outbound network ID */
574 char nprn[OSP_SIZE_NORSTR]; /* Outbound NP routing number */
575 char npcic[OSP_SIZE_NORSTR]; /* Outbound NP carrier identification code */
576 int npdi; /* Outbound NP database dip indicator */
577 char opname[OSPC_OPNAME_NUMBER][OSP_SIZE_NORSTR]; /* Outbound Operator names */
578 unsigned int numdests; /* Number of remain outbound destinations */
579 struct osp_callid outcallid; /* Outbound call ID */
584 OSP_CALL_INBOUND, /* Inbound call leg */
585 OSP_CALL_OUTBOUND /* Outbound call leg */
588 /* OSP Media Stream Direction */
590 OSP_DIR_RX = 0, /* Receive */
591 OSP_DIR_TX, /* Send */
592 OSP_DIR_NUMBER /* Number of directions */
597 int value; /* Value */
598 float min; /* Minimum */
599 float max; /* Maximum */
600 float avg; /* Average */
601 float ndev; /* Normal deviation */
602 float sdev; /* Standard deviation */
605 /* OSP Module Global Variables */
606 AST_MUTEX_DEFINE_STATIC(osp_lock); /* Lock of OSP provider list */
607 static int osp_initialized = 0; /* Init flag */
608 static int osp_hardware = 0; /* Hardware accelleration flag */
609 static int osp_security = 0; /* Using security features flag */
610 static struct osp_provider* osp_providers = NULL; /* OSP provider list */
611 static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED; /* Token format supported */
613 /* OSP default certificates */
614 const char* B64PKey = "MIIBOgIBAAJBAK8t5l+PUbTC4lvwlNxV5lpl+2dwSZGW46dowTe6y133XyVEwNiiRma2YNk3xKs/TJ3Wl9Wpns2SYEAJsFfSTukCAwEAAQJAPz13vCm2GmZ8Zyp74usTxLCqSJZNyMRLHQWBM0g44Iuy4wE3vpi7Wq+xYuSOH2mu4OddnxswCP4QhaXVQavTAQIhAOBVCKXtppEw9UaOBL4vW0Ed/6EA/1D8hDW6St0h7EXJAiEAx+iRmZKhJD6VT84dtX5ZYNVk3j3dAcIOovpzUj9a0CECIEduTCapmZQ5xqAEsLXuVlxRtQgLTUD4ZxDElPn8x0MhAiBE2HlcND0+qDbvtwJQQOUzDgqg5xk3w8capboVdzAlQQIhAMC+lDL7+gDYkNAft5Mu+NObJmQs4Cr+DkDFsKqoxqrm";
615 const char* B64LCert = "MIIBeTCCASMCEHqkOHVRRWr+1COq3CR/xsowDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTA1MDYyMzAwMjkxOFoXDTA2MDYyNDAwMjkxOFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCvLeZfj1G0wuJb8JTcVeZaZftncEmRluOnaME3ustd918lRMDYokZmtmDZN8SrP0yd1pfVqZ7NkmBACbBX0k7pAgMBAAEwDQYJKoZIhvcNAQEEBQADQQDnV8QNFVVJx/+7IselU0wsepqMurivXZzuxOmTEmTVDzCJx1xhA8jd3vGAj7XDIYiPub1PV23eY5a2ARJuw5w9";
616 const char* B64CACert = "MIIBYDCCAQoCAQEwDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTAyMDIwNDE4MjU1MloXDTEyMDIwMzE4MjU1MlowOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPGeGwV41EIhX0jEDFLRXQhDEr50OUQPq+f55VwQd0TQNts06BP29+UiNdRW3c3IRHdZcJdC1Cg68ME9cgeq0h8CAwEAATANBgkqhkiG9w0BAQQFAANBAGkzBSj1EnnmUxbaiG1N4xjIuLAWydun7o3bFk2tV8dBIhnuh445obYyk1EnQ27kI7eACCILBZqi2MHDOIMnoN0=";
618 /* OSP Client Wrapper APIs */
621 * \brief Create OSP provider handle according to configuration
622 * \param cfg OSP configuration
623 * \param name OSP provider context name
624 * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
626 static int osp_create_provider(
627 struct ast_config* cfg,
630 int res = OSP_FAILED;
631 struct ast_variable* var;
632 struct osp_provider* provider;
633 OSPTPRIVATEKEY privatekey;
635 OSPT_CERT cacerts[OSP_MAX_CERTS];
636 const OSPT_CERT* pcacerts[OSP_MAX_CERTS];
637 const char* pspoints[OSP_MAX_SPOINTS];
638 unsigned char privatekeydata[OSP_SIZE_KEYSTR];
639 unsigned char localcertdata[OSP_SIZE_KEYSTR];
640 unsigned char cacertdata[OSP_SIZE_KEYSTR];
641 int i, num, error = OSPC_ERR_NO_ERROR;
643 if (!(provider = ast_calloc(1, sizeof(*provider)))) {
644 ast_log(LOG_ERROR, "Out of memory\n");
648 /* ast_calloc has set 0 in provider */
649 provider->handle = OSP_INVALID_HANDLE;
650 ast_copy_string(provider->name, name, sizeof(provider->name));
651 snprintf(provider->privatekey, sizeof(provider->privatekey), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, name);
652 snprintf(provider->localcert, sizeof(provider->localcert), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, name);
653 snprintf(provider->cacerts[0], sizeof(provider->cacerts[0]), "%s/%s-cacert_0.pem", ast_config_AST_KEY_DIR, name);
654 provider->maxconnect = OSP_DEF_MAXCONNECT;
655 provider->retrydelay = OSP_DEF_RETRYDELAY;
656 provider->retrylimit = OSP_DEF_RETRYLIMIT;
657 provider->timeout = OSP_DEF_TIMEOUT;
658 provider->authpolicy = OSP_DEF_AUTHPOLICY;
659 provider->defprotocol = OSP_DEF_PROTOCOL;
660 provider->workmode = OSP_DEF_WORKMODE;
661 provider->srvtype = OSP_DEF_SRVTYPE;
663 for (var = ast_variable_browse(cfg, name); var != NULL; var = var->next) {
664 if (!strcasecmp(var->name, "privatekey")) {
666 if (var->value[0] == '/') {
667 ast_copy_string(provider->privatekey, var->value, sizeof(provider->privatekey));
669 snprintf(provider->privatekey, sizeof(provider->privatekey), "%s/%s", ast_config_AST_KEY_DIR, var->value);
671 ast_debug(1, "OSP: privatekey '%s'\n", provider->privatekey);
673 } else if (!strcasecmp(var->name, "localcert")) {
675 if (var->value[0] == '/') {
676 ast_copy_string(provider->localcert, var->value, sizeof(provider->localcert));
678 snprintf(provider->localcert, sizeof(provider->localcert), "%s/%s", ast_config_AST_KEY_DIR, var->value);
680 ast_debug(1, "OSP: localcert '%s'\n", provider->localcert);
682 } else if (!strcasecmp(var->name, "cacert")) {
684 if (provider->canum < OSP_MAX_CERTS) {
685 if (var->value[0] == '/') {
686 ast_copy_string(provider->cacerts[provider->canum], var->value, sizeof(provider->cacerts[provider->canum]));
688 snprintf(provider->cacerts[provider->canum], sizeof(provider->cacerts[provider->canum]), "%s/%s", ast_config_AST_KEY_DIR, var->value);
690 ast_debug(1, "OSP: cacerts[%d]: '%s'\n", provider->canum, provider->cacerts[provider->canum]);
693 ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", var->lineno);
696 } else if (!strcasecmp(var->name, "servicepoint")) {
697 if (provider->spnum < OSP_MAX_SPOINTS) {
698 ast_copy_string(provider->spoints[provider->spnum], var->value, sizeof(provider->spoints[provider->spnum]));
699 ast_debug(1, "OSP: servicepoint[%d]: '%s'\n", provider->spnum, provider->spoints[provider->spnum]);
702 ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", var->lineno);
704 } else if (!strcasecmp(var->name, "maxconnect")) {
705 if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_MAXCONNECT) && (num <= OSP_MAX_MAXCONNECT)) {
706 provider->maxconnect = num;
707 ast_debug(1, "OSP: maxconnect '%d'\n", num);
709 ast_log(LOG_WARNING, "OSP: maxconnect should be an integer from %d to %d, not '%s' at line %d\n",
710 OSP_MIN_MAXCONNECT, OSP_MAX_MAXCONNECT, var->value, var->lineno);
712 } else if (!strcasecmp(var->name, "retrydelay")) {
713 if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_RETRYDELAY) && (num <= OSP_MAX_RETRYDELAY)) {
714 provider->retrydelay = num;
715 ast_debug(1, "OSP: retrydelay '%d'\n", num);
717 ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n",
718 OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY, var->value, var->lineno);
720 } else if (!strcasecmp(var->name, "retrylimit")) {
721 if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_RETRYLIMIT) && (num <= OSP_MAX_RETRYLIMIT)) {
722 provider->retrylimit = num;
723 ast_debug(1, "OSP: retrylimit '%d'\n", num);
725 ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n",
726 OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT, var->value, var->lineno);
728 } else if (!strcasecmp(var->name, "timeout")) {
729 if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_TIMEOUT) && (num <= OSP_MAX_TIMEOUT)) {
730 provider->timeout = num;
731 ast_debug(1, "OSP: timeout '%d'\n", num);
733 ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n",
734 OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT, var->value, var->lineno);
736 } else if (!strcasecmp(var->name, "source")) {
737 ast_copy_string(provider->source, var->value, sizeof(provider->source));
738 ast_debug(1, "OSP: source '%s'\n", provider->source);
739 } else if (!strcasecmp(var->name, "authpolicy")) {
740 if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_AUTH_NO) || (num == OSP_AUTH_YES) || (num == OSP_AUTH_EXC))) {
741 provider->authpolicy = num;
742 ast_debug(1, "OSP: authpolicy '%d'\n", num);
744 ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n",
745 OSP_AUTH_NO, OSP_AUTH_YES, OSP_AUTH_EXC, var->value, var->lineno);
747 } else if (!strcasecmp(var->name, "defprotocol")) {
748 if (!strcasecmp(var->value, OSP_PROT_SIP)) {
749 provider->defprotocol = OSP_PROT_SIP;
750 ast_debug(1, "OSP: default protocol SIP\n");
751 } else if (!strcasecmp(var->value, OSP_PROT_H323)) {
752 provider->defprotocol = OSP_PROT_H323;
753 ast_debug(1, "OSP: default protocol H.323\n");
754 } else if (!strcasecmp(var->value, OSP_PROT_IAX)) {
755 provider->defprotocol = OSP_PROT_IAX;
756 ast_debug(1, "OSP: default protocol IAX\n");
757 } else if (!strcasecmp(var->value, OSP_PROT_SKYPE)) {
758 provider->defprotocol = OSP_PROT_SKYPE;
759 ast_debug(1, "OSP: default protocol Skype\n");
761 ast_log(LOG_WARNING, "OSP: default protocol should be %s, %s, %s or %s not '%s' at line %d\n",
762 OSP_PROT_SIP, OSP_PROT_H323, OSP_PROT_IAX, OSP_PROT_SKYPE, var->value, var->lineno);
764 } else if (!strcasecmp(var->name, "workmode")) {
765 if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_MODE_DIRECT) || (num == OSP_MODE_INDIRECT))) {
766 provider->workmode = num;
767 ast_debug(1, "OSP: workmode '%d'\n", num);
769 ast_log(LOG_WARNING, "OSP: workmode should be %d or %d, not '%s' at line %d\n",
770 OSP_MODE_DIRECT, OSP_MODE_INDIRECT, var->value, var->lineno);
772 } else if (!strcasecmp(var->name, "servicetype")) {
773 if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_SRV_VOICE) || (num == OSP_SRV_NPQUERY))) {
774 provider->srvtype = num;
775 ast_debug(1, "OSP: servicetype '%d'\n", num);
777 ast_log(LOG_WARNING, "OSP: servicetype should be %d or %d, not '%s' at line %d\n",
778 OSP_SRV_VOICE, OSP_SRV_NPQUERY, var->value, var->lineno);
783 if (provider->canum == 0) {
787 for (i = 0; i < provider->spnum; i++) {
788 pspoints[i] = provider->spoints[i];
792 privatekey.PrivateKeyData = NULL;
793 privatekey.PrivateKeyLength = 0;
795 localcert.CertData = NULL;
796 localcert.CertDataLength = 0;
798 for (i = 0; i < provider->canum; i++) {
799 cacerts[i].CertData = NULL;
800 cacerts[i].CertDataLength = 0;
803 if ((error = OSPPUtilLoadPEMPrivateKey((unsigned char*)provider->privatekey, &privatekey)) != OSPC_ERR_NO_ERROR) {
804 ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", provider->privatekey, error);
805 } else if ((error = OSPPUtilLoadPEMCert((unsigned char*)provider->localcert, &localcert)) != OSPC_ERR_NO_ERROR) {
806 ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", provider->localcert, error);
808 for (i = 0; i < provider->canum; i++) {
809 if ((error = OSPPUtilLoadPEMCert((unsigned char*)provider->cacerts[i], &cacerts[i])) != OSPC_ERR_NO_ERROR) {
810 ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", provider->cacerts[i], error);
813 pcacerts[i] = &cacerts[i];
818 privatekey.PrivateKeyData = privatekeydata;
819 privatekey.PrivateKeyLength = sizeof(privatekeydata);
821 localcert.CertData = localcertdata;
822 localcert.CertDataLength = sizeof(localcertdata);
824 cacerts[0].CertData = cacertdata;
825 cacerts[0].CertDataLength = sizeof(cacertdata);
826 pcacerts[0] = &cacerts[0];
828 if ((error = OSPPBase64Decode(B64PKey, strlen(B64PKey), privatekey.PrivateKeyData, &privatekey.PrivateKeyLength)) != OSPC_ERR_NO_ERROR) {
829 ast_log(LOG_WARNING, "OSP: Unable to decode private key, error '%d'\n", error);
830 } else if ((error = OSPPBase64Decode(B64LCert, strlen(B64LCert), localcert.CertData, &localcert.CertDataLength)) != OSPC_ERR_NO_ERROR) {
831 ast_log(LOG_WARNING, "OSP: Unable to decode local cert, error '%d'\n", error);
832 } else if ((error = OSPPBase64Decode(B64CACert, strlen(B64CACert), cacerts[0].CertData, &cacerts[0].CertDataLength)) != OSPC_ERR_NO_ERROR) {
833 ast_log(LOG_WARNING, "OSP: Unable to decode cacert, error '%d'\n", error);
837 if (error == OSPC_ERR_NO_ERROR) {
838 error = OSPPProviderNew(provider->spnum,
846 OSP_LOCAL_VALIDATION,
848 provider->maxconnect,
849 OSP_HTTP_PERSISTENCE,
850 provider->retrydelay,
851 provider->retrylimit,
856 if (error != OSPC_ERR_NO_ERROR) {
857 ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", name, error);
860 ast_debug(1, "OSP: provider '%s'\n", name);
861 ast_mutex_lock(&osp_lock);
862 provider->next = osp_providers;
863 osp_providers = provider;
864 ast_mutex_unlock(&osp_lock);
870 for (i = 0; i < provider->canum; i++) {
871 if (cacerts[i].CertData) {
872 ast_free(cacerts[i].CertData);
875 if (localcert.CertData) {
876 ast_free(localcert.CertData);
878 if (privatekey.PrivateKeyData) {
879 ast_free(privatekey.PrivateKeyData);
891 * \brief Get OSP provider by name
892 * \param name OSP provider context name
893 * \param provider OSP provider structure
894 * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
896 static int osp_get_provider(
898 struct osp_provider** provider)
900 int res = OSP_FAILED;
901 struct osp_provider* p;
905 ast_mutex_lock(&osp_lock);
906 for (p = osp_providers; p != NULL; p = p->next) {
907 if (!strcasecmp(p->name, name)) {
909 ast_debug(1, "OSP: find provider '%s'\n", name);
914 ast_mutex_unlock(&osp_lock);
920 * \brief Create OSP transaction handle
921 * \param name OSP provider context name
922 * \param trans OSP transaction handle, output
923 * \param source Source of provider, output
924 * \param srcsize Size of source buffer, in
925 * \return OSK_OK Success, OSK_FAILED Failed, OSP_ERROR Error
927 static int osp_create_transaction(
931 unsigned int srcsize)
933 int res = OSP_FAILED;
934 struct osp_provider* provider;
937 if ((trans == NULL) || (source == NULL) || (srcsize <= 0)) {
938 ast_log(LOG_ERROR, "Invalid parameters\n");
942 *trans = OSP_INVALID_HANDLE;
945 ast_mutex_lock(&osp_lock);
946 for (provider = osp_providers; provider; provider = provider->next) {
947 if (!strcasecmp(provider->name, name)) {
948 error = OSPPTransactionNew(provider->handle, trans);
949 if (error == OSPC_ERR_NO_ERROR) {
950 ast_debug(1, "OSP: transaction '%d'\n", *trans);
951 ast_copy_string(source, provider->source, srcsize);
952 ast_debug(1, "OSP: source '%s'\n", source);
955 *trans = OSP_INVALID_HANDLE;
956 ast_debug(1, "OSP: Unable to create transaction handle, error '%d'\n", error);
963 ast_mutex_unlock(&osp_lock);
969 * \brief Convert "address:port" to "[x.x.x.x]:port" or "hostname:port" format
970 * \param src Source address string
971 * \param dest Destination address string
972 * \param destsize Size of dest buffer
974 static void osp_convert_inout(
977 unsigned int destsize)
980 char buffer[OSP_SIZE_NORSTR];
983 if ((dest != NULL) && (destsize > 0)) {
984 if (!ast_strlen_zero(src)) {
985 ast_copy_string(buffer, src, sizeof(buffer));
987 if((port = strchr(buffer, ':')) != NULL) {
992 if (inet_pton(AF_INET, buffer, &inp) == 1) {
994 snprintf(dest, destsize, "[%s]:%s", buffer, port);
996 snprintf(dest, destsize, "[%s]", buffer);
998 dest[destsize - 1] = '\0';
1000 ast_copy_string(dest, src, destsize);
1009 * \brief Convert "[x.x.x.x]:port" or "hostname:prot" to "address:port" format
1010 * \param src Source address string
1011 * \param dest Destination address string
1012 * \param destsize Size of dest buffer
1014 static void osp_convert_outin(
1017 unsigned int destsize)
1019 char buffer[OSP_SIZE_NORSTR];
1023 if ((dest != NULL) && (destsize > 0)) {
1024 if (!ast_strlen_zero(src)) {
1025 ast_copy_string(buffer, src, sizeof(buffer));
1027 if (buffer[0] == '[') {
1028 if((port = strchr(buffer + 1, ':')) != NULL) {
1033 if ((end = strchr(buffer + 1, ']')) != NULL) {
1038 snprintf(dest, destsize, "%s:%s", buffer + 1, port);
1039 dest[destsize - 1] = '\0';
1041 ast_copy_string(dest, buffer + 1, destsize);
1044 ast_copy_string(dest, src, destsize);
1053 * \brief Validate OSP token of inbound call
1054 * \param trans OSP transaction handle
1055 * \param source Source of inbound call
1056 * \param destination Destination of inbound call
1057 * \param calling Calling number
1058 * \param called Called number
1059 * \param token OSP token, may be empty
1060 * \param timelimit Call duration limit, output
1061 * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
1063 static int osp_validate_token(
1066 const char* destination,
1067 const char* calling,
1070 unsigned int* timelimit)
1074 unsigned char tokenstr[OSP_SIZE_TOKSTR];
1075 char src[OSP_SIZE_NORSTR];
1076 char dest[OSP_SIZE_NORSTR];
1077 unsigned int authorised;
1078 unsigned int dummy = 0;
1081 if (timelimit == NULL) {
1082 ast_log(LOG_ERROR, "Invalid parameters\n");
1086 tokenlen = ast_base64decode(tokenstr, token, strlen(token));
1087 osp_convert_inout(source, src, sizeof(src));
1088 osp_convert_inout(destination, dest, sizeof(dest));
1089 error = OSPPTransactionValidateAuthorisation(trans,
1094 calling ? calling : "",
1107 if (error != OSPC_ERR_NO_ERROR) {
1108 ast_log(LOG_WARNING, "OSP: Unable to validate inbound token, error '%d'\n", error);
1111 } else if (authorised) {
1112 ast_debug(1, "OSP: Authorised\n");
1115 ast_debug(1, "OSP: Unauthorised\n");
1123 * \brief Choose min duration limit
1124 * \param in Inbound duration limit
1125 * \param out Outbound duration limit
1126 * \return min duration limit
1128 static unsigned int osp_choose_timelimit(
1132 if (in == OSP_DEF_TIMELIMIT) {
1134 } else if (out == OSP_DEF_TIMELIMIT) {
1137 return in < out ? in : out;
1142 * \brief Choose min duration limit
1143 * \param provider OSP provider
1144 * \param calling Calling number
1145 * \param called Called number
1146 * \param destination Destination IP in '[x.x.x.x]' format
1147 * \param tokenlen OSP token length
1148 * \param token OSP token
1149 * \param reason Failure reason, output
1150 * \param results OSP lookup results, in/output
1151 * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
1153 static int osp_check_destination(
1154 struct osp_provider* provider,
1155 const char* calling,
1157 const char* destination,
1158 unsigned int tokenlen,
1160 OSPEFAILREASON* reason,
1161 struct osp_results* results)
1164 OSPE_DEST_OSPENABLED enabled;
1165 OSPE_DEST_PROTOCOL protocol;
1166 char dest[OSP_SIZE_NORSTR];
1167 OSPE_OPERATOR_NAME type;
1170 if ((provider == NULL) || (reason == NULL) || (results == NULL)) {
1171 ast_log(LOG_ERROR, "Invalid parameters\n");
1175 if ((error = OSPPTransactionIsDestOSPEnabled(results->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) {
1176 ast_debug(1, "OSP: Unable to get destination OSP version, error '%d'\n", error);
1177 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
1181 if (enabled == OSPC_DOSP_FALSE) {
1182 results->token[0] = '\0';
1184 ast_base64encode(results->token, (const unsigned char*)token, tokenlen, sizeof(results->token) - 1);
1187 if ((error = OSPPTransactionGetDestinationNetworkId(results->outhandle, sizeof(results->networkid), results->networkid)) != OSPC_ERR_NO_ERROR) {
1188 ast_debug(1, "OSP: Unable to get destination network ID, error '%d'\n", error);
1189 results->networkid[0] = '\0';
1192 error = OSPPTransactionGetNumberPortabilityParameters(results->outhandle,
1193 sizeof(results->nprn),
1195 sizeof(results->npcic),
1198 if (error != OSPC_ERR_NO_ERROR) {
1199 ast_debug(1, "OSP: Unable to get number portability parameters, error '%d'\n", error);
1200 results->nprn[0] = '\0';
1201 results->npcic[0] = '\0';
1205 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1206 error = OSPPTransactionGetOperatorName(results->outhandle, type, sizeof(results->opname[type]), results->opname[type]);
1207 if (error != OSPC_ERR_NO_ERROR) {
1208 ast_debug(1, "OSP: Unable to get operator name of type '%d', error '%d'\n", type, error);
1209 results->opname[type][0] = '\0';
1213 if ((error = OSPPTransactionGetDestProtocol(results->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
1214 ast_debug(1, "OSP: Unable to get destination protocol, error '%d'\n", error);
1215 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
1216 results->token[0] = '\0';
1217 results->networkid[0] = '\0';
1218 results->nprn[0] = '\0';
1219 results->npcic[0] = '\0';
1221 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1222 results->opname[type][0] = '\0';
1228 osp_convert_outin(destination, dest, sizeof(dest));
1230 case OSPC_DPROT_SIP:
1231 ast_debug(1, "OSP: protocol SIP\n");
1232 ast_copy_string(results->tech, OSP_TECH_SIP, sizeof(results->tech));
1233 ast_copy_string(results->dest, dest, sizeof(results->dest));
1234 ast_copy_string(results->calling, calling, sizeof(results->calling));
1235 ast_copy_string(results->called, called, sizeof(results->called));
1237 case OSPC_DPROT_Q931:
1238 ast_debug(1, "OSP: protocol Q.931\n");
1239 ast_copy_string(results->tech, OSP_TECH_H323, sizeof(results->tech));
1240 ast_copy_string(results->dest, dest, sizeof(results->dest));
1241 ast_copy_string(results->calling, calling, sizeof(results->calling));
1242 ast_copy_string(results->called, called, sizeof(results->called));
1244 case OSPC_DPROT_IAX:
1245 ast_debug(1, "OSP: protocol IAX\n");
1246 ast_copy_string(results->tech, OSP_TECH_IAX, sizeof(results->tech));
1247 ast_copy_string(results->dest, dest, sizeof(results->dest));
1248 ast_copy_string(results->calling, calling, sizeof(results->calling));
1249 ast_copy_string(results->called, called, sizeof(results->called));
1251 case OSPC_DPROT_SKYPE:
1252 ast_debug(1, "OSP: protocol Skype\n");
1253 ast_copy_string(results->tech, OSP_TECH_SKYPE, sizeof(results->tech));
1254 ast_copy_string(results->dest, dest, sizeof(results->dest));
1255 ast_copy_string(results->calling, calling, sizeof(results->calling));
1256 ast_copy_string(results->called, called, sizeof(results->called));
1258 case OSPC_DPROT_UNDEFINED:
1259 case OSPC_DPROT_UNKNOWN:
1260 ast_debug(1, "OSP: unknown/undefined protocol '%d'\n", protocol);
1261 ast_debug(1, "OSP: use default protocol '%s'\n", provider->defprotocol);
1262 ast_copy_string(results->tech, provider->defprotocol, sizeof(results->tech));
1263 ast_copy_string(results->dest, dest, sizeof(results->dest));
1264 ast_copy_string(results->calling, calling, sizeof(results->calling));
1265 ast_copy_string(results->called, called, sizeof(results->called));
1267 case OSPC_DPROT_LRQ:
1268 case OSPC_DPROT_T37:
1269 case OSPC_DPROT_T38:
1270 case OSPC_DPROT_SMPP:
1271 case OSPC_DPROT_XMPP:
1273 ast_log(LOG_WARNING, "OSP: unsupported protocol '%d'\n", protocol);
1274 *reason = OSPC_FAIL_PROTOCOL_ERROR;
1275 results->token[0] = '\0';
1276 results->networkid[0] = '\0';
1277 results->nprn[0] = '\0';
1278 results->npcic[0] = '\0';
1280 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1281 results->opname[type][0] = '\0';
1291 * \brief Convert Asterisk status to TC code
1292 * \param cause Asterisk hangup cause
1293 * \return OSP TC code
1295 static OSPEFAILREASON asterisk2osp(
1298 return (OSPEFAILREASON)cause;
1302 * \brief OSP Authentication function
1303 * \param name OSP provider context name
1304 * \param trans OSP transaction handle, output
1305 * \param source Source of inbound call
1306 * \param calling Calling number
1307 * \param called Called number
1308 * \param token OSP token, may be empty
1309 * \param timelimit Call duration limit, output
1310 * \return OSP_OK Authenricated, OSP_FAILED Unauthenticated, OSP_ERROR Error
1312 static int osp_auth(
1316 const char* calling,
1319 unsigned int* timelimit)
1322 struct osp_provider* provider = NULL;
1323 char dest[OSP_SIZE_NORSTR];
1325 if ((trans == NULL) || (timelimit == NULL)) {
1326 ast_log(LOG_ERROR, "Invalid parameters\n");
1330 *trans = OSP_INVALID_HANDLE;
1331 *timelimit = OSP_DEF_TIMELIMIT;
1333 if ((res = osp_get_provider(name, &provider)) <= 0) {
1334 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1338 switch (provider->authpolicy) {
1343 if (ast_strlen_zero(token)) {
1345 } else if ((res = osp_create_transaction(name, trans, dest, sizeof(dest))) <= 0) {
1346 ast_debug(1, "OSP: Unable to generate transaction handle\n");
1347 *trans = OSP_INVALID_HANDLE;
1349 } else if((res = osp_validate_token(*trans, source, dest, calling, called, token, timelimit)) <= 0) {
1350 OSPPTransactionRecordFailure(*trans, OSPC_FAIL_CALL_REJECTED);
1355 if (ast_strlen_zero(token)) {
1357 } else if ((res = osp_create_transaction(name, trans, dest, sizeof(dest))) <= 0) {
1358 ast_debug(1, "OSP: Unable to generate transaction handle\n");
1359 *trans = OSP_INVALID_HANDLE;
1361 } else if((res = osp_validate_token(*trans, source, dest, calling, called, token, timelimit)) <= 0) {
1362 OSPPTransactionRecordFailure(*trans, OSPC_FAIL_CALL_REJECTED);
1371 * \brief Create a UUID
1372 * \param uuid UUID buffer
1373 * \param bufsize UUID buffer size
1374 * \return OSK_OK Created, OSP_ERROR Error
1376 static int osp_create_uuid(
1377 unsigned char* uuid,
1378 unsigned int* bufsize)
1381 long int tmp[OSP_SIZE_UUID / sizeof(long int)];
1383 if ((uuid != NULL) && (*bufsize >= OSP_SIZE_UUID)) {
1384 for (i = 0; i < OSP_SIZE_UUID / sizeof(long int); i++) {
1385 tmp[i] = ast_random();
1387 memcpy(uuid, tmp, OSP_SIZE_UUID);
1388 *bufsize = OSP_SIZE_UUID;
1391 ast_log(LOG_ERROR, "Invalid parameters\n");
1399 * \brief UUID to string
1401 * \param buffer String buffer
1402 * \param bufsize String buffer size
1403 * \return OSP_OK Successed, OSP_ERROR Error
1405 static int osp_uuid2str(
1406 unsigned char* uuid,
1408 unsigned int bufsize)
1412 if ((uuid != NULL) && (bufsize > OSP_SIZE_UUIDSTR)) {
1413 snprintf(buffer, bufsize, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1414 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
1415 uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
1418 ast_log(LOG_ERROR, "Invalid parameters\n");
1426 * \brief Create a call ID according to the type
1427 * \param type Call ID type
1428 * \param callid Call ID buffer
1429 * \return OSK_OK Created, OSP_FAILED Not create, OSP_ERROR Error
1431 static int osp_create_callid(
1433 struct osp_callid* callid)
1437 if (callid == NULL) {
1438 ast_log(LOG_ERROR, "Invalid parameters\n");
1442 callid->len = sizeof(callid->buf);
1444 case OSP_CALLID_H323:
1445 res = osp_create_uuid(callid->buf, &callid->len);
1447 case OSP_CALLID_SIP:
1448 case OSP_CALLID_IAX:
1455 if ((res != OSP_OK) && (callid->len != 0)) {
1456 callid->buf[0] = '\0';
1464 * \brief OSP Lookup function
1465 * \param name OSP provider context name
1466 * \param callidtypes Call ID types
1467 * \param actualsrc Actual source device in indirect mode
1468 * \param srcdev Source device of outbound call
1469 * \param calling Calling number
1470 * \param called Called number
1471 * \param snetid Source network ID
1472 * \param np NP parameters
1473 * \param div SIP Diversion header parameters
1474 * \param cinfo Custom info
1475 * \param results Lookup results
1476 * \return OSP_OK Found , OSP_FAILED No route, OSP_ERROR Error
1478 static int osp_lookup(
1480 unsigned int callidtypes,
1481 const char* actualsrc,
1483 const char* calling,
1486 struct osp_npdata* np,
1487 struct osp_diversion* div,
1488 const char* cinfo[],
1489 struct osp_results* results)
1492 struct osp_provider* provider = NULL;
1493 char source[OSP_SIZE_NORSTR];
1494 char callingnum[OSP_SIZE_NORSTR];
1495 char callednum[OSP_SIZE_NORSTR];
1496 char destination[OSP_SIZE_NORSTR];
1498 unsigned int tokenlen;
1499 char token[OSP_SIZE_TOKSTR];
1500 char src[OSP_SIZE_NORSTR];
1501 char dev[OSP_SIZE_NORSTR];
1502 char host[OSP_SIZE_NORSTR];
1503 unsigned int i, type;
1504 struct osp_callid callid;
1505 unsigned int callidnum;
1506 OSPT_CALL_ID* callids[OSP_CALLID_MAXNUM];
1507 char dest[OSP_SIZE_NORSTR];
1508 const char* preferred[2] = { NULL };
1509 unsigned int dummy = 0;
1510 OSPEFAILREASON reason;
1513 if (results == NULL) {
1514 ast_log(LOG_ERROR, "Invalid parameters\n");
1518 osp_convert_inout(results->dest, dest, sizeof(dest));
1520 results->outhandle = OSP_INVALID_HANDLE;
1521 results->tech[0] = '\0';
1522 results->calling[0] = '\0';
1523 results->called[0] = '\0';
1524 results->token[0] = '\0';
1525 results->networkid[0] = '\0';
1526 results->nprn[0] = '\0';
1527 results->npcic[0] = '\0';
1529 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1530 results->opname[type][0] = '\0';
1532 results->numdests = 0;
1533 results->outtimelimit = OSP_DEF_TIMELIMIT;
1535 if ((res = osp_get_provider(name, &provider)) <= 0) {
1536 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1540 if ((res = osp_create_transaction(name, &results->outhandle, source, sizeof(source))) <= 0) {
1541 ast_debug(1, "OSP: Unable to generate transaction handle\n");
1542 results->outhandle = OSP_INVALID_HANDLE;
1543 if (results->inhandle != OSP_INVALID_HANDLE) {
1544 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1549 if (!ast_strlen_zero(snetid)) {
1550 OSPPTransactionSetNetworkIds(results->outhandle, snetid, "");
1553 OSPPTransactionSetNumberPortability(results->outhandle, np->rn, np->cic, np->npdi);
1555 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1556 OSPPTransactionSetOperatorName(results->outhandle, type, np->opname[type]);
1559 osp_convert_inout(div->host, host, sizeof(host));
1560 OSPPTransactionSetDiversion(results->outhandle, div->user, host);
1562 if (cinfo != NULL) {
1563 for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
1564 if (!ast_strlen_zero(cinfo[i])) {
1565 OSPPTransactionSetCustomInfo(results->outhandle, i, cinfo[i]);
1570 ast_copy_string(callednum, called, sizeof(callednum));
1571 if((tmp = strchr(callednum, ';')) != NULL) {
1577 for (i = 0; i < OSP_CALLID_MAXNUM; i++) {
1579 if (callidtypes & type) {
1580 error = osp_create_callid(type, &callid);
1582 callids[callidnum] = OSPPCallIdNew(callid.len, callid.buf);
1588 if (provider->workmode == OSP_MODE_INDIRECT) {
1589 osp_convert_inout(srcdev, src, sizeof(src));
1590 if (ast_strlen_zero(actualsrc)) {
1591 osp_convert_inout(srcdev, dev, sizeof(dev));
1593 osp_convert_inout(actualsrc, dev, sizeof(dev));
1596 osp_convert_inout(source, src, sizeof(src));
1597 osp_convert_inout(srcdev, dev, sizeof(dev));
1600 if (provider->srvtype == OSP_SRV_NPQUERY) {
1601 OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_NPQUERY);
1602 if (!ast_strlen_zero(dest)) {
1603 preferred[0] = dest;
1605 results->numdests = 1;
1607 OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_VOICE);
1608 results->numdests = OSP_DEF_MAXDESTS;
1610 error = OSPPTransactionRequestAuthorisation(results->outhandle,
1613 calling ? calling : "",
1625 for (i = 0; i < callidnum; i++) {
1626 OSPPCallIdDelete(&callids[i]);
1629 if (error != OSPC_ERR_NO_ERROR) {
1630 ast_log(LOG_WARNING, "OSP: Unable to request authorization, error '%d'\n", error);
1631 results->numdests = 0;
1632 if (results->inhandle != OSP_INVALID_HANDLE) {
1633 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1638 if (!results->numdests) {
1639 ast_debug(1, "OSP: No more destination\n");
1640 if (results->inhandle != OSP_INVALID_HANDLE) {
1641 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1646 results->outcallid.len = sizeof(results->outcallid.buf);
1647 tokenlen = sizeof(token);
1648 error = OSPPTransactionGetFirstDestination(results->outhandle,
1652 &results->outtimelimit,
1653 &results->outcallid.len,
1654 results->outcallid.buf,
1659 sizeof(destination),
1665 if (error != OSPC_ERR_NO_ERROR) {
1666 ast_debug(1, "OSP: Unable to get first route, error '%d'\n", error);
1667 results->numdests = 0;
1668 results->outtimelimit = OSP_DEF_TIMELIMIT;
1669 if (results->inhandle != OSP_INVALID_HANDLE) {
1670 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1675 results->numdests--;
1676 results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
1677 ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
1678 ast_debug(1, "OSP: calling '%s'\n", callingnum);
1679 ast_debug(1, "OSP: called '%s'\n", callednum);
1680 ast_debug(1, "OSP: destination '%s'\n", destination);
1681 ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1683 if ((res = osp_check_destination(provider, callingnum, callednum, destination, tokenlen, token, &reason, results)) > 0) {
1687 if (!results->numdests) {
1688 ast_debug(1, "OSP: No more destination\n");
1689 results->outtimelimit = OSP_DEF_TIMELIMIT;
1690 OSPPTransactionRecordFailure(results->outhandle, reason);
1691 if (results->inhandle != OSP_INVALID_HANDLE) {
1692 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1697 while(results->numdests) {
1698 results->outcallid.len = sizeof(results->outcallid.buf);
1699 tokenlen = sizeof(token);
1700 error = OSPPTransactionGetNextDestination(results->outhandle,
1705 &results->outtimelimit,
1706 &results->outcallid.len,
1707 results->outcallid.buf,
1712 sizeof(destination),
1718 if (error == OSPC_ERR_NO_ERROR) {
1719 results->numdests--;
1720 results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
1721 ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
1722 ast_debug(1, "OSP: calling '%s'\n", callingnum);
1723 ast_debug(1, "OSP: called '%s'\n", callednum);
1724 ast_debug(1, "OSP: destination '%s'\n", destination);
1725 ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1727 if ((res = osp_check_destination(provider, callingnum, callednum, destination, tokenlen, token, &reason, results)) > 0) {
1729 } else if (!results->numdests) {
1730 ast_debug(1, "OSP: No more destination\n");
1731 OSPPTransactionRecordFailure(results->outhandle, reason);
1732 if (results->inhandle != OSP_INVALID_HANDLE) {
1733 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1739 ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
1740 results->numdests = 0;
1741 results->outtimelimit = OSP_DEF_TIMELIMIT;
1742 if (results->inhandle != OSP_INVALID_HANDLE) {
1743 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1754 * \brief OSP Lookup Next function
1755 * \param name OSP provider name
1756 * \param cause Asterisk hangup cuase
1757 * \param results Lookup results, in/output
1758 * \return OSP_OK Found , OSP_FAILED No route, OSP_ERROR Error
1760 static int osp_next(
1763 struct osp_results* results)
1766 struct osp_provider* provider = NULL;
1767 char calling[OSP_SIZE_NORSTR];
1768 char called[OSP_SIZE_NORSTR];
1769 char dest[OSP_SIZE_NORSTR];
1770 unsigned int tokenlen;
1771 char token[OSP_SIZE_TOKSTR];
1772 OSPEFAILREASON reason;
1773 OSPE_OPERATOR_NAME type;
1776 if (results == NULL) {
1777 ast_log(LOG_ERROR, "Invalid parameters\n");
1781 results->tech[0] = '\0';
1782 results->dest[0] = '\0';
1783 results->calling[0] = '\0';
1784 results->called[0] = '\0';
1785 results->token[0] = '\0';
1786 results->networkid[0] = '\0';
1787 results->nprn[0] = '\0';
1788 results->npcic[0] = '\0';
1790 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1791 results->opname[type][0] = '\0';
1793 results->outtimelimit = OSP_DEF_TIMELIMIT;
1795 if ((res = osp_get_provider(name, &provider)) <= 0) {
1796 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1800 if (results->outhandle == OSP_INVALID_HANDLE) {
1801 ast_debug(1, "OSP: Transaction handle undefined\n");
1802 results->numdests = 0;
1803 if (results->inhandle != OSP_INVALID_HANDLE) {
1804 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1809 reason = asterisk2osp(cause);
1811 if (!results->numdests) {
1812 ast_debug(1, "OSP: No more destination\n");
1813 OSPPTransactionRecordFailure(results->outhandle, reason);
1814 if (results->inhandle != OSP_INVALID_HANDLE) {
1815 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1820 while(results->numdests) {
1821 results->outcallid.len = sizeof(results->outcallid.buf);
1822 tokenlen = sizeof(token);
1823 error = OSPPTransactionGetNextDestination(
1829 &results->outtimelimit,
1830 &results->outcallid.len,
1831 results->outcallid.buf,
1842 if (error == OSPC_ERR_NO_ERROR) {
1843 results->numdests--;
1844 results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
1845 ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
1846 ast_debug(1, "OSP: calling '%s'\n", calling);
1847 ast_debug(1, "OSP: called '%s'\n", called);
1848 ast_debug(1, "OSP: destination '%s'\n", dest);
1849 ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1851 if ((res = osp_check_destination(provider, calling, called, dest, tokenlen, token, &reason, results)) > 0) {
1854 } else if (!results->numdests) {
1855 ast_debug(1, "OSP: No more destination\n");
1856 OSPPTransactionRecordFailure(results->outhandle, reason);
1857 if (results->inhandle != OSP_INVALID_HANDLE) {
1858 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1864 ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
1865 results->token[0] = '\0';
1866 results->numdests = 0;
1867 results->outtimelimit = OSP_DEF_TIMELIMIT;
1868 if (results->inhandle != OSP_INVALID_HANDLE) {
1869 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1880 * \brief Get integer from variable string
1881 * \param vstr Variable string
1882 * \return OSP_DEF_INTSTATS Error
1884 static int osp_get_varint(
1888 int value = OSP_DEF_INTSTATS;
1890 if (!ast_strlen_zero(vstr)) {
1891 if ((tmp = strchr(vstr, '=')) != NULL) {
1893 if (sscanf(tmp, "%30d", &value) != 1) {
1894 value = OSP_DEF_INTSTATS;
1903 * \brief Get float from variable string
1904 * \param vstr Variable string
1905 * \return OSP_DEF_FLOATSTATS Error
1907 static float osp_get_varfloat(
1911 float value = OSP_DEF_FLOATSTATS;
1913 if (!ast_strlen_zero(vstr)) {
1914 if ((tmp = strchr(vstr, '=')) != NULL) {
1916 if (sscanf(tmp, "%30f", &value) != 1) {
1917 value = OSP_DEF_FLOATSTATS;
1927 * \param trans OSP in/outbound transaction handle
1928 * \param leg Inbound/outbound
1929 * \param qos QoS string
1930 * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
1932 static int osp_report_qos(
1934 enum osp_callleg leg,
1937 int res = OSP_FAILED;
1938 enum osp_direction dir;
1939 char buffer[OSP_SIZE_NORSTR];
1942 int totalpackets[OSP_DIR_NUMBER];
1943 struct osp_metrics lost[OSP_DIR_NUMBER];
1944 struct osp_metrics jitter[OSP_DIR_NUMBER];
1945 struct osp_metrics rtt;
1948 if (!ast_strlen_zero(qos)) {
1949 for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
1950 totalpackets[dir] = OSP_DEF_INTSTATS;
1953 for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
1954 lost[dir].value = OSP_DEF_INTSTATS;
1955 lost[dir].min = OSP_DEF_FLOATSTATS;
1956 lost[dir].max = OSP_DEF_FLOATSTATS;
1957 lost[dir].avg = OSP_DEF_FLOATSTATS;
1958 lost[dir].sdev = OSP_DEF_FLOATSTATS;
1961 for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
1962 jitter[dir].value = OSP_DEF_INTSTATS;
1963 jitter[dir].min = OSP_DEF_FLOATSTATS;
1964 jitter[dir].max = OSP_DEF_FLOATSTATS;
1965 jitter[dir].avg = OSP_DEF_FLOATSTATS;
1966 jitter[dir].sdev = OSP_DEF_FLOATSTATS;
1969 rtt.value = OSP_DEF_INTSTATS;
1970 rtt.min = OSP_DEF_FLOATSTATS;
1971 rtt.max = OSP_DEF_FLOATSTATS;
1972 rtt.avg = OSP_DEF_FLOATSTATS;
1973 rtt.sdev = OSP_DEF_FLOATSTATS;
1975 ast_copy_string(buffer, qos, sizeof(buffer));
1976 for (item = strtok_r(buffer, ";", &tmp); item; item = strtok_r(NULL, ";", &tmp)) {
1977 if (!strncasecmp(item, "rxcount", strlen("rxcount"))) {
1978 totalpackets[OSP_DIR_RX] = osp_get_varint(item);
1979 } else if (!strncasecmp(item, "txcount", strlen("txcount"))) {
1980 totalpackets[OSP_DIR_TX] = osp_get_varint(item);
1981 } else if (!strncasecmp(item, "lp", strlen("lp"))) {
1982 lost[OSP_DIR_RX].value = osp_get_varint(item);
1983 } else if (!strncasecmp(item, "minrxlost", strlen("minrxlost"))) {
1984 lost[OSP_DIR_RX].min = osp_get_varfloat(item);
1985 } else if (!strncasecmp(item, "maxrxlost", strlen("maxrxlost"))) {
1986 lost[OSP_DIR_RX].max = osp_get_varfloat(item);
1987 } else if (!strncasecmp(item, "avgrxlost", strlen("avgrxlost"))) {
1988 lost[OSP_DIR_RX].avg = osp_get_varfloat(item);
1989 } else if (!strncasecmp(item, "stdevrxlost", strlen("stdevrxlost"))) {
1990 lost[OSP_DIR_RX].sdev = osp_get_varfloat(item);
1991 } else if (!strncasecmp(item, "rlp", strlen("rlp"))) {
1992 lost[OSP_DIR_TX].value = osp_get_varint(item);
1993 } else if (!strncasecmp(item, "reported_minlost", strlen("reported_minlost"))) {
1994 lost[OSP_DIR_TX].min = osp_get_varfloat(item);
1995 } else if (!strncasecmp(item, "reported_maxlost", strlen("reported_maxlost"))) {
1996 lost[OSP_DIR_TX].max = osp_get_varfloat(item);
1997 } else if (!strncasecmp(item, "reported_avglost", strlen("reported_avglost"))) {
1998 lost[OSP_DIR_TX].avg = osp_get_varfloat(item);
1999 } else if (!strncasecmp(item, "reported_stdevlost", strlen("reported_stdevlost"))) {
2000 lost[OSP_DIR_TX].sdev = osp_get_varfloat(item);
2001 } else if (!strncasecmp(item, "rxjitter", strlen("rxjitter"))) {
2002 jitter[OSP_DIR_RX].value = osp_get_varint(item);
2003 } else if (!strncasecmp(item, "minrxjitter", strlen("minrxjitter"))) {
2004 jitter[OSP_DIR_RX].min = osp_get_varfloat(item);
2005 } else if (!strncasecmp(item, "maxrxjitter", strlen("maxrxjitter"))) {
2006 jitter[OSP_DIR_RX].max = osp_get_varfloat(item);
2007 } else if (!strncasecmp(item, "avgrxjitter", strlen("avgjitter"))) {
2008 jitter[OSP_DIR_RX].avg = osp_get_varfloat(item);
2009 } else if (!strncasecmp(item, "stdevrxjitter", strlen("stdevjitter"))) {
2010 jitter[OSP_DIR_RX].sdev = osp_get_varfloat(item);
2011 } else if (!strncasecmp(item, "txjitter", strlen("txjitter"))) {
2012 jitter[OSP_DIR_TX].value = osp_get_varint(item);
2013 } else if (!strncasecmp(item, "reported_minjitter", strlen("reported_minjitter"))) {
2014 jitter[OSP_DIR_TX].min = osp_get_varfloat(item);
2015 } else if (!strncasecmp(item, "reported_maxjitter", strlen("reported_maxjitter"))) {
2016 jitter[OSP_DIR_TX].max = osp_get_varfloat(item);
2017 } else if (!strncasecmp(item, "reported_avgjitter", strlen("reported_avgjitter"))) {
2018 jitter[OSP_DIR_TX].avg = osp_get_varfloat(item);
2019 } else if (!strncasecmp(item, "reported_stdevjitter", strlen("reported_stdevjitter"))) {
2020 jitter[OSP_DIR_TX].sdev = osp_get_varfloat(item);
2021 } else if (!strncasecmp(item, "rtt", strlen("rtt"))) {
2022 rtt.value = osp_get_varint(item);
2023 } else if (!strncasecmp(item, "minrtt", strlen("minrtt"))) {
2024 rtt.min = osp_get_varfloat(item);
2025 } else if (!strncasecmp(item, "maxrtt", strlen("maxrtt"))) {
2026 rtt.max = osp_get_varfloat(item);
2027 } else if (!strncasecmp(item, "avgrtt", strlen("avgrtt"))) {
2028 rtt.avg = osp_get_varfloat(item);
2029 } else if (!strncasecmp(item, "stdevrtt", strlen("stdevrtt"))) {
2030 rtt.sdev = osp_get_varfloat(item);
2034 ast_debug(1, "OSP: call leg '%d'\n", leg);
2035 ast_debug(1, "OSP: rxcount '%d'\n", totalpackets[OSP_DIR_RX]);
2036 ast_debug(1, "OSP: txcount '%d'\n", totalpackets[OSP_DIR_TX]);
2037 ast_debug(1, "OSP: lp '%d'\n",lost[OSP_DIR_RX].value);
2038 ast_debug(1, "OSP: minrxlost '%f'\n", lost[OSP_DIR_RX].min);
2039 ast_debug(1, "OSP: maxrxlost '%f'\n", lost[OSP_DIR_RX].max);
2040 ast_debug(1, "OSP: avgrxlost '%f'\n", lost[OSP_DIR_RX].avg);
2041 ast_debug(1, "OSP: stdevrxlost '%f'\n", lost[OSP_DIR_RX].sdev);
2042 ast_debug(1, "OSP: rlp '%d'\n", lost[OSP_DIR_TX].value);
2043 ast_debug(1, "OSP: reported_minlost '%f'\n", lost[OSP_DIR_TX].min);
2044 ast_debug(1, "OSP: reported_maxlost '%f'\n", lost[OSP_DIR_TX].max);
2045 ast_debug(1, "OSP: reported_avglost '%f'\n", lost[OSP_DIR_TX].avg);
2046 ast_debug(1, "OSP: reported_stdevlost '%f'\n", lost[OSP_DIR_TX].sdev);
2047 ast_debug(1, "OSP: rxjitter '%d'\n", jitter[OSP_DIR_RX].value);
2048 ast_debug(1, "OSP: minrxjitter '%f'\n", jitter[OSP_DIR_RX].min);
2049 ast_debug(1, "OSP: maxrxjitter '%f'\n", jitter[OSP_DIR_RX].max);
2050 ast_debug(1, "OSP: avgrxjitter '%f'\n", jitter[OSP_DIR_RX].avg);
2051 ast_debug(1, "OSP: stdevrxjitter '%f'\n", jitter[OSP_DIR_RX].sdev);
2052 ast_debug(1, "OSP: txjitter '%d'\n", jitter[OSP_DIR_TX].value);
2053 ast_debug(1, "OSP: reported_minjitter '%f'\n", jitter[OSP_DIR_TX].min);
2054 ast_debug(1, "OSP: reported_maxjitter '%f'\n", jitter[OSP_DIR_TX].max);
2055 ast_debug(1, "OSP: reported_avgjitter '%f'\n", jitter[OSP_DIR_TX].avg);
2056 ast_debug(1, "OSP: reported_stdevjitter '%f'\n", jitter[OSP_DIR_TX].sdev);
2057 ast_debug(1, "OSP: rtt '%d'\n", rtt.value);
2058 ast_debug(1, "OSP: minrtt '%f'\n", rtt.min);
2059 ast_debug(1, "OSP: maxrtt '%f'\n", rtt.max);
2060 ast_debug(1, "OSP: avgrtt '%f'\n", rtt.avg);
2061 ast_debug(1, "OSP: stdevrtt '%f'\n", rtt.sdev);
2063 if (leg == OSP_CALL_INBOUND) {
2064 OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_DOWNSTREAM, totalpackets[OSP_DIR_RX]);
2065 OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM, totalpackets[OSP_DIR_TX]);
2066 if (lost[OSP_DIR_RX].value >= 0) {
2067 value = lost[OSP_DIR_RX].value;
2069 value = (int)lost[OSP_DIR_RX].avg;
2071 OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_DOWNSTREAM, value, OSP_DEF_INTSTATS);
2072 if (lost[OSP_DIR_TX].value >= 0) {
2073 value = lost[OSP_DIR_TX].value;
2075 value = (int)lost[OSP_DIR_TX].avg;
2077 OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM, value, OSP_DEF_INTSTATS);
2078 if (jitter[OSP_DIR_RX].value >= 0) {
2079 value = jitter[OSP_DIR_RX].value;
2081 value = (int)jitter[OSP_DIR_RX].avg;
2083 OSPPTransactionSetJitter(trans,
2085 OSPC_SFLOW_DOWNSTREAM,
2087 (int)jitter[OSP_DIR_RX].min,
2088 (int)jitter[OSP_DIR_RX].max,
2089 value, jitter[OSP_DIR_RX].sdev);
2090 if (jitter[OSP_DIR_TX].value >= 0) {
2091 value = jitter[OSP_DIR_TX].value;
2093 value = (int)jitter[OSP_DIR_TX].avg;
2095 OSPPTransactionSetJitter(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM,
2096 OSP_DEF_INTSTATS, (int)jitter[OSP_DIR_TX].min, (int)jitter[OSP_DIR_TX].max, value, jitter[OSP_DIR_TX].sdev);
2098 OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_UPSTREAM, totalpackets[OSP_DIR_RX]);
2099 OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_DOWNSTREAM, totalpackets[OSP_DIR_TX]);
2100 OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_UPSTREAM, lost[OSP_DIR_RX].value, OSP_DEF_INTSTATS);
2101 OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_DOWNSTREAM, lost[OSP_DIR_TX].value, OSP_DEF_INTSTATS);
2102 if (jitter[OSP_DIR_RX].value >= 0) {
2103 value = jitter[OSP_DIR_RX].value;
2105 value = (int)jitter[OSP_DIR_RX].avg;
2107 OSPPTransactionSetJitter(trans,
2109 OSPC_SFLOW_UPSTREAM,
2111 (int)jitter[OSP_DIR_RX].min,
2112 (int)jitter[OSP_DIR_RX].max,
2114 jitter[OSP_DIR_RX].sdev);
2115 if (jitter[OSP_DIR_TX].value >= 0) {
2116 value = jitter[OSP_DIR_TX].value;
2118 value = (int)jitter[OSP_DIR_TX].avg;
2120 OSPPTransactionSetJitter(trans,
2122 OSPC_SFLOW_DOWNSTREAM,
2124 (int)jitter[OSP_DIR_TX].min,
2125 (int)jitter[OSP_DIR_TX].max,
2127 jitter[OSP_DIR_TX].sdev);
2129 if (rtt.value >= 0) {
2132 value = (int)rtt.avg;
2134 OSPPTransactionSetRoundTripDelay(trans, OSP_DEF_INTSTATS, (int)rtt.min, (int)rtt.max, value, rtt.sdev);
2143 * \brief OSP Finish function
2144 * \param trans OSP in/outbound transaction handle
2145 * \param recorded If failure reason has been recorded
2146 * \param cause Asterisk hangup cause
2147 * \param start Call start time
2148 * \param connect Call connect time
2149 * \param end Call end time
2150 * \param release Who release first, 0 source, 1 destination
2151 * \param inqos Inbound QoS string
2152 * \param outqos Outbound QoS string
2153 * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
2155 static int osp_finish(
2162 unsigned int release,
2167 OSPEFAILREASON reason;
2169 unsigned isPddInfoPresent = 0;
2171 unsigned int dummy = 0;
2174 if (trans == OSP_INVALID_HANDLE) {
2179 reason = asterisk2osp(cause);
2180 OSPPTransactionRecordFailure(trans, reason);
2183 osp_report_qos(trans, OSP_CALL_INBOUND, inqos);
2184 osp_report_qos(trans, OSP_CALL_OUTBOUND, outqos);
2186 error = OSPPTransactionReportUsage(trans,
2187 difftime(end, connect),
2202 if (error == OSPC_ERR_NO_ERROR) {
2203 ast_debug(1, "OSP: Usage reported\n");
2206 ast_debug(1, "OSP: Unable to report usage, error '%d'\n", error);
2209 OSPPTransactionDelete(trans);
2214 /* OSP Application APIs */
2217 * \brief OSP Application OSPAuth
2218 * \param chan Channel
2219 * \param data Parameter
2220 * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2222 static int ospauth_exec(
2223 struct ast_channel *chan,
2227 const char* provider = OSP_DEF_PROVIDER;
2228 struct varshead* headp;
2229 struct ast_var_t* current;
2230 const char* source = "";
2231 const char* token = "";
2233 unsigned int timelimit;
2234 char buffer[OSP_SIZE_INTSTR];
2238 AST_DECLARE_APP_ARGS(args,
2239 AST_APP_ARG(provider);
2240 AST_APP_ARG(options);
2243 if (!(tmp = ast_strdupa(data))) {
2244 ast_log(LOG_ERROR, "Out of memory\n");
2245 return OSP_AST_ERROR;
2248 AST_STANDARD_APP_ARGS(args, tmp);
2250 if (!ast_strlen_zero(args.provider)) {
2251 provider = args.provider;
2253 ast_debug(1, "OSPAuth: provider '%s'\n", provider);
2255 headp = &chan->varshead;
2256 AST_LIST_TRAVERSE(headp, current, entries) {
2257 if (!strcasecmp(ast_var_name(current), "OSPINPEERIP")) {
2258 source = ast_var_value(current);
2259 } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
2260 token = ast_var_value(current);
2264 ast_debug(1, "OSPAuth: source '%s'\n", source);
2265 ast_debug(1, "OSPAuth: token size '%zd'\n", strlen(token));
2267 res = osp_auth(provider, &handle, source,
2268 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
2269 chan->exten, token, &timelimit);
2271 status = AST_OSP_SUCCESS;
2273 timelimit = OSP_DEF_TIMELIMIT;
2275 status = AST_OSP_FAILED;
2277 status = AST_OSP_ERROR;
2281 snprintf(buffer, sizeof(buffer), "%d", handle);
2282 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
2283 ast_debug(1, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
2284 snprintf(buffer, sizeof(buffer), "%d", timelimit);
2285 pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
2286 ast_debug(1, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
2287 pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
2288 ast_debug(1, "OSPAuth: %s\n", status);
2291 res = OSP_AST_ERROR;
2300 * \brief OSP Application OSPLookup
2301 * \param chan Channel
2302 * \param data Parameter
2303 * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2305 static int osplookup_exec(
2306 struct ast_channel* chan,
2310 const char* provider = OSP_DEF_PROVIDER;
2311 unsigned int callidtypes = OSP_CALLID_UNDEF;
2312 struct varshead* headp;
2313 struct ast_var_t* current;
2314 const char* actualsrc = "";
2315 const char* srcdev = "";
2316 const char* snetid = "";
2317 struct osp_npdata np;
2318 OSPE_OPERATOR_NAME type;
2319 struct osp_diversion div;
2321 const char* cinfo[OSP_MAX_CUSTOMINFO] = { NULL };
2322 char buffer[OSP_SIZE_TOKSTR];
2323 struct osp_results results;
2327 AST_DECLARE_APP_ARGS(args,
2329 AST_APP_ARG(provider);
2330 AST_APP_ARG(options);
2333 if (ast_strlen_zero(data)) {
2334 ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[,provider[,options]])\n");
2335 return OSP_AST_ERROR;
2338 if (!(tmp = ast_strdupa(data))) {
2339 ast_log(LOG_ERROR, "Out of memory\n");
2340 return OSP_AST_ERROR;
2343 AST_STANDARD_APP_ARGS(args, tmp);
2345 ast_debug(1, "OSPLookup: exten '%s'\n", args.exten);
2347 if (!ast_strlen_zero(args.provider)) {
2348 provider = args.provider;
2350 ast_debug(1, "OSPlookup: provider '%s'\n", provider);
2353 if (strchr(args.options, 'h')) {
2354 callidtypes |= OSP_CALLID_H323;
2356 if (strchr(args.options, 's')) {
2357 callidtypes |= OSP_CALLID_SIP;
2359 if (strchr(args.options, 'i')) {
2360 callidtypes |= OSP_CALLID_IAX;
2363 ast_debug(1, "OSPLookup: call id types '%d'\n", callidtypes);
2365 results.inhandle = OSP_INVALID_HANDLE;
2366 results.intimelimit = OSP_DEF_TIMELIMIT;
2367 results.dest[0] = '\0';
2372 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2373 np.opname[type] = "";
2379 headp = &chan->varshead;
2380 AST_LIST_TRAVERSE(headp, current, entries) {
2381 if (!strcasecmp(ast_var_name(current), "OSPINACTUALSRC")) {
2382 actualsrc = ast_var_value(current);
2383 } else if (!strcasecmp(ast_var_name(current), "OSPINPEERIP")) {
2384 srcdev = ast_var_value(current);
2385 } else if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
2386 if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
2387 results.inhandle = OSP_INVALID_HANDLE;
2389 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
2390 if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
2391 results.intimelimit = OSP_DEF_TIMELIMIT;
2393 } else if (!strcasecmp(ast_var_name(current), "OSPINNETWORKID")) {
2394 snetid = ast_var_value(current);
2395 } else if (!strcasecmp(ast_var_name(current), "OSPINNPRN")) {
2396 np.rn = ast_var_value(current);
2397 } else if (!strcasecmp(ast_var_name(current), "OSPINNPCIC")) {
2398 np.cic = ast_var_value(current);
2399 } else if (!strcasecmp(ast_var_name(current), "OSPINNPDI")) {
2400 if (ast_true(ast_var_value(current))) {
2403 } else if (!strcasecmp(ast_var_name(current), "OSPINSPID")) {
2404 np.opname[OSPC_OPNAME_SPID] = ast_var_value(current);
2405 } else if (!strcasecmp(ast_var_name(current), "OSPINOCN")) {
2406 np.opname[OSPC_OPNAME_OCN] = ast_var_value(current);
2407 } else if (!strcasecmp(ast_var_name(current), "OSPINSPN")) {
2408 np.opname[OSPC_OPNAME_SPN] = ast_var_value(current);
2409 } else if (!strcasecmp(ast_var_name(current), "OSPINALTSPN")) {
2410 np.opname[OSPC_OPNAME_ALTSPN] = ast_var_value(current);
2411 } else if (!strcasecmp(ast_var_name(current), "OSPINMCC")) {
2412 np.opname[OSPC_OPNAME_MCC] = ast_var_value(current);
2413 } else if (!strcasecmp(ast_var_name(current), "OSPINMNC")) {
2414 np.opname[OSPC_OPNAME_MNC] = ast_var_value(current);
2415 } else if (!strcasecmp(ast_var_name(current), "OSPINTOHOST")) {
2416 ast_copy_string(results.dest, ast_var_value(current), sizeof(results.dest));
2417 } else if (!strcasecmp(ast_var_name(current), "OSPINDIVUSER")) {
2418 div.user = ast_var_value(current);
2419 } else if (!strcasecmp(ast_var_name(current), "OSPINDIVHOST")) {
2420 div.host = ast_var_value(current);
2421 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO1")) {
2422 cinfo[0] = ast_var_value(current);
2423 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO2")) {
2424 cinfo[1] = ast_var_value(current);
2425 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO3")) {
2426 cinfo[2] = ast_var_value(current);
2427 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO4")) {
2428 cinfo[3] = ast_var_value(current);
2429 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO5")) {
2430 cinfo[4] = ast_var_value(current);
2431 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO6")) {
2432 cinfo[5] = ast_var_value(current);
2433 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO7")) {
2434 cinfo[6] = ast_var_value(current);
2435 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO8")) {
2436 cinfo[7] = ast_var_value(current);
2439 ast_debug(1, "OSPLookup: actual source device '%s'\n", actualsrc);
2440 ast_debug(1, "OSPLookup: source device '%s'\n", srcdev);
2441 ast_debug(1, "OSPLookup: OSPINHANDLE '%d'\n", results.inhandle);
2442 ast_debug(1, "OSPLookup: OSPINTIMELIMIT '%d'\n", results.intimelimit);
2443 ast_debug(1, "OSPLookup: OSPINNETWORKID '%s'\n", snetid);
2444 ast_debug(1, "OSPLookup: OSPINNPRN '%s'\n", np.rn);
2445 ast_debug(1, "OSPLookup: OSPINNPCIC '%s'\n", np.cic);
2446 ast_debug(1, "OSPLookup: OSPINNPDI '%d'\n", np.npdi);
2447 ast_debug(1, "OSPLookup: OSPINSPID '%s'\n", np.opname[OSPC_OPNAME_SPID]);
2448 ast_debug(1, "OSPLookup: OSPINOCN '%s'\n", np.opname[OSPC_OPNAME_OCN]);
2449 ast_debug(1, "OSPLookup: OSPINSPN '%s'\n", np.opname[OSPC_OPNAME_SPN]);
2450 ast_debug(1, "OSPLookup: OSPINALTSPN '%s'\n", np.opname[OSPC_OPNAME_ALTSPN]);
2451 ast_debug(1, "OSPLookup: OSPINMCC '%s'\n", np.opname[OSPC_OPNAME_MCC]);
2452 ast_debug(1, "OSPLookup: OSPINMNC '%s'\n", np.opname[OSPC_OPNAME_MNC]);
2453 ast_debug(1, "OSPLookup: OSPINTOHOST '%s'\n", results.dest);
2454 ast_debug(1, "OSPLookup: OSPINDIVUSER '%s'\n", div.user);
2455 ast_debug(1, "OSPLookup: OSPINDIVHOST'%s'\n", div.host);
2456 for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
2457 if (!ast_strlen_zero(cinfo[i])) {
2458 ast_debug(1, "OSPLookup: OSPINCUSTOMINFO%d '%s'\n", i, cinfo[i]);
2462 if ((cres = ast_autoservice_start(chan)) < 0) {
2463 return OSP_AST_ERROR;
2466 res = osp_lookup(provider, callidtypes, actualsrc, srcdev,
2467 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
2468 args.exten, snetid, &np, &div, cinfo, &results);
2470 status = AST_OSP_SUCCESS;
2472 results.tech[0] = '\0';
2473 results.dest[0] = '\0';
2474 results.calling[0] = '\0';
2475 results.called[0] = '\0';
2476 results.token[0] = '\0';
2477 results.networkid[0] = '\0';
2478 results.nprn[0] = '\0';
2479 results.npcic[0] = '\0';
2481 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2482 results.opname[type][0] = '\0';
2484 results.numdests = 0;
2485 results.outtimelimit = OSP_DEF_TIMELIMIT;
2486 results.outcallid.buf[0] = '\0';
2487 results.outcallid.len = 0;
2489 status = AST_OSP_FAILED;
2491 status = AST_OSP_ERROR;
2495 snprintf(buffer, sizeof(buffer), "%d", results.outhandle);
2496 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
2497 ast_debug(1, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
2498 pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.tech);
2499 ast_debug(1, "OSPLookup: OSPOUTTECH '%s'\n", results.tech);
2500 pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
2501 ast_debug(1, "OSPLookup: OSPDESTINATION '%s'\n", results.dest);
2502 pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
2503 ast_debug(1, "OSPLookup: OSPOUTCALLING '%s'\n", results.calling);
2504 pbx_builtin_setvar_helper(chan, "OSPOUTCALLED", results.called);
2505 ast_debug(1, "OSPLookup: OSPOUTCALLED '%s'\n", results.called);
2506 pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", results.networkid);
2507 ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", results.networkid);
2508 pbx_builtin_setvar_helper(chan, "OSPOUTNPRN", results.nprn);
2509 ast_debug(1, "OSPLookup: OSPOUTNPRN '%s'\n", results.nprn);
2510 pbx_builtin_setvar_helper(chan, "OSPOUTNPCIC", results.npcic);
2511 ast_debug(1, "OSPLookup: OSPOUTNPCIC '%s'\n", results.npcic);
2512 snprintf(buffer, sizeof(buffer), "%d", results.npdi);
2513 pbx_builtin_setvar_helper(chan, "OSPOUTNPDI", buffer);
2514 ast_debug(1, "OSPLookup: OSPOUTNPDI'%s'\n", buffer);
2515 pbx_builtin_setvar_helper(chan, "OSPOUTSPID", results.opname[OSPC_OPNAME_SPID]);
2516 ast_debug(1, "OSPLookup: OSPOUTSPID '%s'\n", results.opname[OSPC_OPNAME_SPID]);
2517 pbx_builtin_setvar_helper(chan, "OSPOUTOCN", results.opname[OSPC_OPNAME_OCN]);
2518 ast_debug(1, "OSPLookup: OSPOUTOCN '%s'\n", results.opname[OSPC_OPNAME_OCN]);
2519 pbx_builtin_setvar_helper(chan, "OSPOUTSPN", results.opname[OSPC_OPNAME_SPN]);
2520 ast_debug(1, "OSPLookup: OSPOUTSPN '%s'\n", results.opname[OSPC_OPNAME_SPN]);
2521 pbx_builtin_setvar_helper(chan, "OSPOUTALTSPN", results.opname[OSPC_OPNAME_ALTSPN]);
2522 ast_debug(1, "OSPLookup: OSPOUTALTSPN '%s'\n", results.opname[OSPC_OPNAME_ALTSPN]);
2523 pbx_builtin_setvar_helper(chan, "OSPOUTMCC", results.opname[OSPC_OPNAME_MCC]);
2524 ast_debug(1, "OSPLookup: OSPOUTMCC '%s'\n", results.opname[OSPC_OPNAME_MCC]);
2525 pbx_builtin_setvar_helper(chan, "OSPOUTMNC", results.opname[OSPC_OPNAME_MNC]);
2526 ast_debug(1, "OSPLookup: OSPOUTMNC '%s'\n", results.opname[OSPC_OPNAME_MNC]);
2527 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", results.token);
2528 ast_debug(1, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(results.token));
2529 snprintf(buffer, sizeof(buffer), "%d", results.numdests);
2530 pbx_builtin_setvar_helper(chan, "OSPDESTREMAILS", buffer);
2531 ast_debug(1, "OSPLookup: OSPDESTREMAILS '%s'\n", buffer);
2532 snprintf(buffer, sizeof(buffer), "%d", results.outtimelimit);
2533 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
2534 ast_debug(1, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
2535 snprintf(buffer, sizeof(buffer), "%d", callidtypes);
2536 pbx_builtin_setvar_helper(chan, "OSPOUTCALLIDTYPES", buffer);
2537 ast_debug(1, "OSPLookup: OSPOUTCALLIDTYPES '%s'\n", buffer);
2538 pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
2539 ast_debug(1, "OSPLookup: %s\n", status);
2541 if (!strcasecmp(results.tech, OSP_TECH_SIP)) {
2542 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
2543 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2544 if (!ast_strlen_zero(results.token)) {
2545 snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
2546 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
2547 ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
2549 } else if (!strcasecmp(results.tech, OSP_TECH_H323)) {
2550 if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
2551 osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
2555 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
2556 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
2557 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2558 } else if (!strcasecmp(results.tech, OSP_TECH_IAX)) {
2559 snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.tech, results.dest, results.called);
2560 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2561 } else if (!strcasecmp(results.tech, OSP_TECH_SKYPE)) {
2562 snprintf(buffer, sizeof(buffer), "%s/%s", results.tech, results.called);
2563 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2566 if ((cres = ast_autoservice_stop(chan)) < 0) {
2567 return OSP_AST_ERROR;
2571 res = OSP_AST_ERROR;
2580 * \brief OSP Application OSPNext
2581 * \param chan Channel
2582 * \param data Parameter
2583 * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2585 static int ospnext_exec(
2586 struct ast_channel* chan,
2590 const char* provider = OSP_DEF_PROVIDER;
2592 struct varshead* headp;
2593 struct ast_var_t* current;
2594 struct osp_results results;
2595 OSPE_OPERATOR_NAME type;
2596 char buffer[OSP_SIZE_TOKSTR];
2597 unsigned int callidtypes = OSP_CALLID_UNDEF;
2601 AST_DECLARE_APP_ARGS(args,
2603 AST_APP_ARG(provider);
2604 AST_APP_ARG(options);
2607 if (ast_strlen_zero(data)) {
2608 ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[,provider[,options]])\n");
2609 return OSP_AST_ERROR;
2612 if (!(tmp = ast_strdupa(data))) {
2613 ast_log(LOG_ERROR, "Out of memory\n");
2614 return OSP_AST_ERROR;
2617 AST_STANDARD_APP_ARGS(args, tmp);
2619 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
2622 ast_debug(1, "OSPNext: cause '%d'\n", cause);
2624 if (!ast_strlen_zero(args.provider)) {
2625 provider = args.provider;
2627 ast_debug(1, "OSPlookup: provider '%s'\n", provider);
2629 results.inhandle = OSP_INVALID_HANDLE;
2630 results.outhandle = OSP_INVALID_HANDLE;
2631 results.intimelimit = OSP_DEF_TIMELIMIT;
2632 results.numdests = 0;
2634 headp = &chan->varshead;
2635 AST_LIST_TRAVERSE(headp, current, entries) {
2636 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
2637 if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
2638 results.inhandle = OSP_INVALID_HANDLE;
2640 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
2641 if (sscanf(ast_var_value(current), "%30d", &results.outhandle) != 1) {
2642 results.outhandle = OSP_INVALID_HANDLE;
2644 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
2645 if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
2646 results.intimelimit = OSP_DEF_TIMELIMIT;
2648 } else if (!strcasecmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) {
2649 if (sscanf(ast_var_value(current), "%30d", &callidtypes) != 1) {
2650 callidtypes = OSP_CALLID_UNDEF;
2652 } else if (!strcasecmp(ast_var_name(current), "OSPDESTREMAILS")) {
2653 if (sscanf(ast_var_value(current), "%30d", &results.numdests) != 1) {
2654 results.numdests = 0;
2658 ast_debug(1, "OSPNext: OSPINHANDLE '%d'\n", results.inhandle);
2659 ast_debug(1, "OSPNext: OSPOUTHANDLE '%d'\n", results.outhandle);
2660 ast_debug(1, "OSPNext: OSPINTIMELIMIT '%d'\n", results.intimelimit);
2661 ast_debug(1, "OSPNext: OSPOUTCALLIDTYPES '%d'\n", callidtypes);
2662 ast_debug(1, "OSPNext: OSPDESTREMAILS '%d'\n", results.numdests);
2664 if ((res = osp_next(provider, cause, &results)) > 0) {
2665 status = AST_OSP_SUCCESS;
2667 results.tech[0] = '\0';
2668 results.dest[0] = '\0';
2669 results.calling[0] = '\0';
2670 results.called[0] = '\0';
2671 results.token[0] = '\0';
2672 results.networkid[0] = '\0';
2673 results.nprn[0] = '\0';
2674 results.npcic[0] = '\0';
2676 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2677 results.opname[type][0] = '\0';
2679 results.numdests = 0;
2680 results.outtimelimit = OSP_DEF_TIMELIMIT;
2681 results.outcallid.buf[0] = '\0';
2682 results.outcallid.len = 0;
2684 status = AST_OSP_FAILED;
2686 status = AST_OSP_ERROR;
2690 pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.tech);
2691 ast_debug(1, "OSPNext: OSPOUTTECH '%s'\n", results.tech);
2692 pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
2693 ast_debug(1, "OSPNext: OSPDESTINATION '%s'\n", results.dest);
2694 pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
2695 ast_debug(1, "OSPNext: OSPOUTCALLING '%s'\n", results.calling);
2696 pbx_builtin_setvar_helper(chan, "OSPOUTCALLED", results.called);
2697 ast_debug(1, "OSPNext: OSPOUTCALLED'%s'\n", results.called);
2698 pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", results.networkid);
2699 ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", results.networkid);
2700 pbx_builtin_setvar_helper(chan, "OSPOUTNPRN", results.nprn);
2701 ast_debug(1, "OSPLookup: OSPOUTNPRN '%s'\n", results.nprn);
2702 pbx_builtin_setvar_helper(chan, "OSPOUTNPCIC", results.npcic);
2703 ast_debug(1, "OSPLookup: OSPOUTNPCIC '%s'\n", results.npcic);
2704 snprintf(buffer, sizeof(buffer), "%d", results.npdi);
2705 pbx_builtin_setvar_helper(chan, "OSPOUTNPDI", buffer);
2706 ast_debug(1, "OSPLookup: OSPOUTNPDI'%s'\n", buffer);
2707 pbx_builtin_setvar_helper(chan, "OSPOUTSPID", results.opname[OSPC_OPNAME_SPID]);
2708 ast_debug(1, "OSPLookup: OSPOUTSPID '%s'\n", results.opname[OSPC_OPNAME_SPID]);
2709 pbx_builtin_setvar_helper(chan, "OSPOUTOCN", results.opname[OSPC_OPNAME_OCN]);
2710 ast_debug(1, "OSPLookup: OSPOUTOCN '%s'\n", results.opname[OSPC_OPNAME_OCN]);
2711 pbx_builtin_setvar_helper(chan, "OSPOUTSPN", results.opname[OSPC_OPNAME_SPN]);
2712 ast_debug(1, "OSPLookup: OSPOUTSPN '%s'\n", results.opname[OSPC_OPNAME_SPN]);
2713 pbx_builtin_setvar_helper(chan, "OSPOUTALTSPN", results.opname[OSPC_OPNAME_ALTSPN]);
2714 ast_debug(1, "OSPLookup: OSPOUTALTSPN '%s'\n", results.opname[OSPC_OPNAME_ALTSPN]);
2715 pbx_builtin_setvar_helper(chan, "OSPOUTMCC", results.opname[OSPC_OPNAME_MCC]);
2716 ast_debug(1, "OSPLookup: OSPOUTMCC '%s'\n", results.opname[OSPC_OPNAME_MCC]);
2717 pbx_builtin_setvar_helper(chan, "OSPOUTMNC", results.opname[OSPC_OPNAME_MNC]);
2718 ast_debug(1, "OSPLookup: OSPOUTMNC '%s'\n", results.opname[OSPC_OPNAME_MNC]);
2719 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", results.token);
2720 ast_debug(1, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(results.token));
2721 snprintf(buffer, sizeof(buffer), "%d", results.numdests);
2722 pbx_builtin_setvar_helper(chan, "OSPDESTREMAILS", buffer);
2723 ast_debug(1, "OSPNext: OSPDESTREMAILS '%s'\n", buffer);
2724 snprintf(buffer, sizeof(buffer), "%d", results.outtimelimit);
2725 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
2726 ast_debug(1, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
2727 pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
2728 ast_debug(1, "OSPNext: %s\n", status);
2730 if (!strcasecmp(results.tech, OSP_TECH_SIP)) {
2731 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
2732 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2733 if (!ast_strlen_zero(results.token)) {
2734 snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
2735 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
2736 ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
2738 } else if (!strcasecmp(results.tech, OSP_TECH_H323)) {
2739 if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
2740 osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
2744 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
2745 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
2746 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2747 } else if (!strcasecmp(results.tech, OSP_TECH_IAX)) {
2748 snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.tech, results.dest, results.called);
2749 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2750 } else if (!strcasecmp(results.tech, OSP_TECH_SKYPE)) {
2751 snprintf(buffer, sizeof(buffer), "%s/%s", results.tech, results.called);
2752 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2756 res = OSP_AST_ERROR;
2765 * \brief OSP Application OSPFinish
2766 * \param chan Channel
2767 * \param data Parameter
2768 * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2770 static int ospfinished_exec(
2771 struct ast_channel* chan,
2776 struct varshead* headp;
2777 struct ast_var_t* current;
2778 int inhandle = OSP_INVALID_HANDLE;
2779 int outhandle = OSP_INVALID_HANDLE;
2781 time_t start, connect, end;
2782 unsigned int release;
2783 char buffer[OSP_SIZE_INTSTR];
2784 char inqos[OSP_SIZE_QOSSTR] = { 0 };
2785 char outqos[OSP_SIZE_QOSSTR] = { 0 };
2789 AST_DECLARE_APP_ARGS(args,
2791 AST_APP_ARG(options);
2794 if (!(tmp = ast_strdupa(data))) {
2795 ast_log(LOG_ERROR, "Out of memory\n");
2796 return OSP_AST_ERROR;
2799 AST_STANDARD_APP_ARGS(args, tmp);
2801 headp = &chan->varshead;
2802 AST_LIST_TRAVERSE(headp, current, entries) {
2803 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
2804 if (sscanf(ast_var_value(current), "%30d", &inhandle) != 1) {
2805 inhandle = OSP_INVALID_HANDLE;
2807 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
2808 if (sscanf(ast_var_value(current), "%30d", &outhandle) != 1) {
2809 outhandle = OSP_INVALID_HANDLE;
2811 } else if (!recorded &&
2812 (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") ||
2813 !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") ||
2814 !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS")))
2816 if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) {
2819 } else if (!strcasecmp(ast_var_name(current), "OSPINAUDIOQOS")) {
2820 ast_copy_string(inqos, ast_var_value(current), sizeof(inqos));
2821 } else if (!strcasecmp(ast_var_name(current), "OSPOUTAUDIOQOS")) {
2822 ast_copy_string(outqos, ast_var_value(current), sizeof(outqos));
2825 ast_debug(1, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
2826 ast_debug(1, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
2827 ast_debug(1, "OSPFinish: recorded '%d'\n", recorded);
2828 ast_debug(1, "OSPFinish: OSPINAUDIOQOS '%s'\n", inqos);
2829 ast_debug(1, "OSPFinish: OSPOUTAUDIOQOS '%s'\n", outqos);
2831 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
2834 ast_debug(1, "OSPFinish: cause '%d'\n", cause);
2837 start = chan->cdr->start.tv_sec;
2838 connect = chan->cdr->answer.tv_sec;
2849 ast_debug(1, "OSPFinish: start '%ld'\n", start);
2850 ast_debug(1, "OSPFinish: connect '%ld'\n", connect);
2851 ast_debug(1, "OSPFinish: end '%ld'\n", end);
2853 release = ast_check_hangup(chan) ? 0 : 1;
2855 if (osp_finish(outhandle, recorded, cause, start, connect, end, release, inqos, outqos) <= 0) {
2856 ast_debug(1, "OSPFinish: Unable to report usage for outbound call\n");
2859 case AST_CAUSE_NORMAL_CLEARING:
2862 cause = AST_CAUSE_NO_ROUTE_DESTINATION;
2865 if (osp_finish(inhandle, recorded, cause, start, connect, end, release, inqos, outqos) <= 0) {
2866 ast_debug(1, "OSPFinish: Unable to report usage for inbound call\n");
2868 snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
2869 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
2870 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
2873 status = AST_OSP_SUCCESS;
2875 status = AST_OSP_FAILED;
2877 status = AST_OSP_ERROR;
2879 pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
2882 res = OSP_AST_ERROR;
2890 /* OSP Module APIs */
2892 static int osp_unload(void)
2894 struct osp_provider* provider;
2895 struct osp_provider* next;
2897 if (osp_initialized) {
2898 ast_mutex_lock(&osp_lock);
2899 for (provider = osp_providers; provider; provider = next) {
2900 next = provider->next;
2901 OSPPProviderDelete(provider->handle, 0);
2904 osp_providers = NULL;
2905 ast_mutex_unlock(&osp_lock);
2909 osp_tokenformat = TOKEN_ALGO_SIGNED;
2912 osp_initialized = 0;
2918 static int osp_load(int reload)
2922 struct ast_config* cfg;
2923 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2924 int error = OSPC_ERR_NO_ERROR;
2926 if ((cfg = ast_config_load(OSP_CONFIG_FILE, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
2928 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
2929 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", OSP_CONFIG_FILE);
2938 if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate")) && ast_true(cvar)) {
2939 if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
2940 ast_log(LOG_WARNING, "OSP: Unable to enable hardware accelleration\n");
2948 ast_debug(1, "OSP: osp_hardware '%d'\n", osp_hardware);
2950 if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "securityfeatures")) && ast_true(cvar)) {
2953 ast_debug(1, "OSP: osp_security '%d'\n", osp_security);
2955 if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat"))) {
2956 if ((sscanf(cvar, "%30d", &ivar) == 1) &&
2957 ((ivar == TOKEN_ALGO_SIGNED) || (ivar == TOKEN_ALGO_UNSIGNED) || (ivar == TOKEN_ALGO_BOTH)))
2959 osp_tokenformat = ivar;
2961 ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n",
2962 TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, cvar);
2965 ast_debug(1, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
2967 for (cvar = ast_category_browse(cfg, NULL); cvar != NULL; cvar = ast_category_browse(cfg, cvar)) {
2968 if (strcasecmp(cvar, OSP_GENERAL_CAT)) {
2969 osp_create_provider(cfg, cvar);
2973 osp_initialized = 1;
2975 ast_config_destroy(cfg);
2977 ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
2980 ast_debug(1, "OSP: osp_initialized '%d'\n", osp_initialized);
2985 static char *handle_cli_osp_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2989 struct osp_provider* provider;
2990 const char* name = NULL;
2991 const char* tokenalgo;
2995 e->command = "osp show";
2998 " Displays information on Open Settlement Protocol support\n";
3004 if ((a->argc < 2) || (a->argc > 3)) {
3005 return CLI_SHOWUSAGE;
3013 switch (osp_tokenformat) {
3014 case TOKEN_ALGO_BOTH:
3017 case TOKEN_ALGO_UNSIGNED:
3018 tokenalgo = "Unsigned";
3020 case TOKEN_ALGO_SIGNED:
3022 tokenalgo = "Signed";
3025 ast_cli(a->fd, "OSP: %s/%s/%s/%s\n",
3026 osp_initialized ? "Initialized" : "Uninitialized",
3027 osp_hardware ? "Accelerated" : "Normal",
3028 osp_security ? "Enabled" : "Disabled",
3032 ast_mutex_lock(&osp_lock);
3033 for (provider = osp_providers; provider; provider = provider->next) {
3034 if (!name || !strcasecmp(provider->name, name)) {
3036 ast_cli(a->fd, "\n");
3038 ast_cli(a->fd, " == OSP Provider '%s' == \n", provider->name);
3040 ast_cli(a->fd, "Local Private Key: %s\n", provider->privatekey);
3041 ast_cli(a->fd, "Local Certificate: %s\n", provider->localcert);
3042 for (i = 0; i < provider->canum; i++) {
3043 ast_cli(a->fd, "CA Certificate %d: %s\n", i + 1, provider->cacerts[i]);
3046 for (i = 0; i < provider->spnum; i++) {
3047 ast_cli(a->fd, "Service Point %d: %s\n", i + 1, provider->spoints[i]);
3049 ast_cli(a->fd, "Max Connections: %d\n", provider->maxconnect);
3050 ast_cli(a->fd, "Retry Delay: %d seconds\n", provider->retrydelay);
3051 ast_cli(a->fd, "Retry Limit: %d\n", provider->retrylimit);
3052 ast_cli(a->fd, "Timeout: %d milliseconds\n", provider->timeout);
3053 ast_cli(a->fd, "Source: %s\n", strlen(provider->source) ? provider->source : "<unspecified>");
3054 ast_cli(a->fd, "Auth Policy %d\n", provider->authpolicy);
3055 ast_cli(a->fd, "Default protocol %s\n", provider->defprotocol);
3056 ast_cli(a->fd, "Work mode %d\n", provider->workmode);
3057 ast_cli(a->fd, "Service type %d\n", provider->srvtype);
3058 ast_cli(a->fd, "OSP Handle: %d\n", provider->handle);
3062 ast_mutex_unlock(&osp_lock);
3066 ast_cli(a->fd, "Unable to find OSP provider '%s'\n", name);
3068 ast_cli(a->fd, "No OSP providers configured\n");
3075 /* OSPAuth() dialplan application */
3076 static const char app1[] = "OSPAuth";
3078 /* OSPLookup() dialplan application */
3079 static const char app2[] = "OSPLookup";
3081 /* OSPNext() dialplan application */
3082 static const char app3[] = "OSPNext";
3084 /* OSPFinish() dialplan application */
3085 static const char app4[] = "OSPFinish";
3087 static struct ast_cli_entry cli_osp[] = {
3088 AST_CLI_DEFINE(handle_cli_osp_show, "Displays OSF information")
3091 static int load_module(void)
3096 return AST_MODULE_LOAD_DECLINE;
3098 ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
3099 res = ast_register_application_xml(app1, ospauth_exec);
3100 res |= ast_register_application_xml(app2, osplookup_exec);
3101 res |= ast_register_application_xml(app3, ospnext_exec);
3102 res |= ast_register_application_xml(app4, ospfinished_exec);
3107 static int unload_module(void)
3111 res = ast_unregister_application(app4);
3112 res |= ast_unregister_application(app3);
3113 res |= ast_unregister_application(app2);
3114 res |= ast_unregister_application(app1);
3115 ast_cli_unregister_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
3121 static int reload(void)
3128 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
3129 .load = load_module,
3130 .unload = unload_module,