9dbf39752a4769b07d45a801e7d1eee03dcdb2bb
[asterisk/asterisk.git] / apps / app_osplookup.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
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.
13  *
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.
17  */
18
19 /*!
20  * \file
21  * \brief Open Settlement Protocol (OSP) Applications
22  *
23  * \author Mark Spencer <markster@digium.com>
24  *
25  * \extref The OSP Toolkit: http://www.transnexus.com
26  * \extref OpenSSL http://www.openssl.org
27  *
28  * \ingroup applications
29  */
30
31 /*** MODULEINFO
32         <depend>osptk</depend>
33         <depend>openssl</depend>
34         <support_level>extended</support_level>
35  ***/
36
37 #include "asterisk.h"
38
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
40
41 #include <osp/osp.h>
42 #include <osp/osputils.h>
43 #include <osp/ospb64.h>
44
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"
56
57 /*** DOCUMENTATION
58         <application name="OSPAuth" language="en_US">
59                 <synopsis>
60                         OSP Authentication.
61                 </synopsis>
62                 <syntax>
63                         <parameter name="provider">
64                                 <para>The name of the provider that authenticates the call.</para>
65                         </parameter>
66                         <parameter name="options">
67                                 <para>Reserverd.</para>
68                         </parameter>
69                 </syntax>
70                 <description>
71                         <para>Authenticate a call by OSP.</para>
72                         <para>Input variables:</para>
73                         <variablelist>
74                                 <variable name="OSPINPEERIP">
75                                         <para>The last hop IP address.</para>
76                                 </variable>
77                                 <variable name="OSPINTOKEN">
78                                         <para>The inbound OSP token.</para>
79                                 </variable>
80                         </variablelist>
81                         <para>Output variables:</para>
82                         <variablelist>
83                                 <variable name="OSPINHANDLE">
84                                         <para>The inbound call OSP transaction handle.</para>
85                                 </variable>
86                                 <variable name="OSPINTIMELIMIT">
87                                         <para>The inbound call duration limit in seconds.</para>
88                                 </variable>
89                         </variablelist>
90                         <para>This application sets the following channel variable upon completion:</para>
91                         <variablelist>
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" />
97                                 </variable>
98                         </variablelist>
99                 </description>
100                 <see-also>
101                         <ref type="application">OSPLookup</ref>
102                         <ref type="application">OSPNext</ref>
103                         <ref type="application">OSPFinish</ref>
104                 </see-also>
105         </application>
106         <application name="OSPLookup" language="en_US">
107                 <synopsis>
108                         Lookup destination by OSP.
109                 </synopsis>
110                 <syntax>
111                         <parameter name="exten" required="true">
112                                 <para>The exten of the call.</para>
113                         </parameter>
114                         <parameter name="provider">
115                                 <para>The name of the provider that is used to route the call.</para>
116                         </parameter>
117                         <parameter name="options">
118                                 <enumlist>
119                                         <enum name="h">
120                                                 <para>generate H323 call id for the outbound call</para>
121                                         </enum>
122                                         <enum name="s">
123                                                 <para>generate SIP call id for the outbound call. Have not been implemented</para>
124                                         </enum>
125                                         <enum name="i">
126                                                 <para>generate IAX call id for the outbound call. Have not been implemented</para>
127                                         </enum>
128                                 </enumlist>
129                         </parameter>
130                 </syntax>
131                 <description>
132                         <para>Looks up destination via OSP.</para>
133                         <para>Input variables:</para>
134                         <variablelist>
135                                 <variable name="OSPINACTUALSRC">
136                                         <para>The actual source device IP address in indirect mode.</para>
137                                 </variable>
138                                 <variable name="OSPINPEERIP">
139                                         <para>The last hop IP address.</para>
140                                 </variable>
141                                 <variable name="OSPINHANDLE">
142                                         <para>The inbound call OSP transaction handle.</para>
143                                 </variable>
144                                 <variable name="OSPINTIMELIMIT">
145                                         <para>The inbound call duration limit in seconds.</para>
146                                 </variable>
147                                 <variable name="OSPINNETWORKID">
148                                         <para>The inbound source network ID.</para>
149                                 </variable>
150                                 <variable name="OSPINNPRN">
151                                         <para>The inbound routing number.</para>
152                                 </variable>
153                                 <variable name="OSPINNPCIC">
154                                         <para>The inbound carrier identification code.</para>
155                                 </variable>
156                                 <variable name="OSPINNPDI">
157                                         <para>The inbound number portability database dip indicator.</para>
158                                 </variable>
159                                 <variable name="OSPINSPID">
160                                         <para>The inbound service provider identity.</para>
161                                 </variable>
162                                 <variable name="OSPINOCN">
163                                         <para>The inbound operator company number.</para>
164                                 </variable>
165                                 <variable name="OSPINSPN">
166                                         <para>The inbound service provider name.</para>
167                                 </variable>
168                                 <variable name="OSPINALTSPN">
169                                         <para>The inbound alternate service provider name.</para>
170                                 </variable>
171                                 <variable name="OSPINMCC">
172                                         <para>The inbound mobile country code.</para>
173                                 </variable>
174                                 <variable name="OSPINMNC">
175                                         <para>The inbound mobile network code.</para>
176                                 </variable>
177                                 <variable name="OSPINTOHOST">
178                                         <para>The inbound To header host part.</para>
179                                 </variable>
180                                 <variable name="OSPINDIVUSER">
181                                         <para>The inbound Diversion header user part.</para>
182                                 </variable>
183                                 <variable name="OSPINDIVHOST">
184                                         <para>The inbound Diversion header host part.</para>
185                                 </variable>
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>
189                                 </variable>
190                         </variablelist>
191                         <para>Output variables:</para>
192                         <variablelist>
193                                 <variable name="OSPOUTHANDLE">
194                                         <para>The outbound call OSP transaction handle.</para>
195                                 </variable>
196                                 <variable name="OSPOUTTECH">
197                                         <para>The outbound channel technology for the call.</para>
198                                 </variable>
199                                 <variable name="OSPDESTINATION">
200                                         <para>The outbound destination IP address.</para>
201                                 </variable>
202                                 <variable name="OSPOUTCALLING">
203                                         <para>The outbound calling number.</para>
204                                 </variable>
205                                 <variable name="OSPOUTCALLED">
206                                         <para>The outbound called number.</para>
207                                 </variable>
208                                 <variable name="OSPOUTNETWORKID">
209                                         <para>The outbound destination network ID.</para>
210                                 </variable>
211                                 <variable name="OSPOUTNPRN">
212                                         <para>The outbound routing number.</para>
213                                 </variable>
214                                 <variable name="OSPOUTNPCIC">
215                                         <para>The outbound carrier identification code.</para>
216                                 </variable>
217                                 <variable name="OSPOUTNPDI">
218                                         <para>The outbound number portability database dip indicator.</para>
219                                 </variable>
220                                 <variable name="OSPOUTSPID">
221                                         <para>The outbound service provider identity.</para>
222                                 </variable>
223                                 <variable name="OSPOUTOCN">
224                                         <para>The outbound operator company number.</para>
225                                 </variable>
226                                 <variable name="OSPOUTSPN">
227                                         <para>The outbound service provider name.</para>
228                                 </variable>
229                                 <variable name="OSPOUTALTSPN">
230                                         <para>The outbound alternate service provider name.</para>
231                                 </variable>
232                                 <variable name="OSPOUTMCC">
233                                         <para>The outbound mobile country code.</para>
234                                 </variable>
235                                 <variable name="OSPOUTMNC">
236                                         <para>The outbound mobile network code.</para>
237                                 </variable>
238                                 <variable name="OSPOUTTOKEN">
239                                         <para>The outbound OSP token.</para>
240                                 </variable>
241                                 <variable name="OSPDESTREMAILS">
242                                         <para>The number of remained destinations.</para>
243                                 </variable>
244                                 <variable name="OSPOUTTIMELIMIT">
245                                         <para>The outbound call duration limit in seconds.</para>
246                                 </variable>
247                                 <variable name="OSPOUTCALLIDTYPES">
248                                         <para>The outbound Call-ID types.</para>
249                                 </variable>
250                                 <variable name="OSPOUTCALLID">
251                                         <para>The outbound Call-ID. Only for H.323.</para>
252                                 </variable>
253                                 <variable name="OSPDIALSTR">
254                                         <para>The outbound Dial command string.</para>
255                                 </variable>
256                         </variablelist>
257                         <para>This application sets the following channel variable upon completion:</para>
258                         <variablelist>
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" />
264                                 </variable>
265                         </variablelist>
266                 </description>
267                 <see-also>
268                         <ref type="application">OSPAuth</ref>
269                         <ref type="application">OSPNext</ref>
270                         <ref type="application">OSPFinish</ref>
271                 </see-also>
272         </application>
273         <application name="OSPNext" language="en_US">
274                 <synopsis>
275                         Lookup next destination by OSP.
276                 </synopsis>
277                 <description>
278                         <para>Looks up the next destination via OSP.</para>
279                         <para>Input variables:</para>
280                         <variablelist>
281                                 <variable name="OSPINHANDLE">
282                                         <para>The inbound call OSP transaction handle.</para>
283                                 </variable>
284                                 <variable name="OSPOUTHANDLE">
285                                         <para>The outbound call OSP transaction handle.</para>
286                                 </variable>
287                                 <variable name="OSPINTIMELIMIT">
288                                         <para>The inbound call duration limit in seconds.</para>
289                                 </variable>
290                                 <variable name="OSPOUTCALLIDTYPES">
291                                         <para>The outbound Call-ID types.</para>
292                                 </variable>
293                                 <variable name="OSPDESTREMAILS">
294                                         <para>The number of remained destinations.</para>
295                                 </variable>
296                         </variablelist>
297                         <para>Output variables:</para>
298                         <variablelist>
299                                 <variable name="OSPOUTTECH">
300                                         <para>The outbound channel technology.</para>
301                                 </variable>
302                                 <variable name="OSPDESTINATION">
303                                         <para>The destination IP address.</para>
304                                 </variable>
305                                 <variable name="OSPOUTCALLING">
306                                         <para>The outbound calling number.</para>
307                                 </variable>
308                                 <variable name="OSPOUTCALLED">
309                                         <para>The outbound called number.</para>
310                                 </variable>
311                                 <variable name="OSPOUTNETWORKID">
312                                         <para>The outbound destination network ID.</para>
313                                 </variable>
314                                 <variable name="OSPOUTNPRN">
315                                         <para>The outbound routing number.</para>
316                                 </variable>
317                                 <variable name="OSPOUTNPCIC">
318                                         <para>The outbound carrier identification code.</para>
319                                 </variable>
320                                 <variable name="OSPOUTNPDI">
321                                         <para>The outbound number portability database dip indicator.</para>
322                                 </variable>
323                                 <variable name="OSPOUTSPID">
324                                         <para>The outbound service provider identity.</para>
325                                 </variable>
326                                 <variable name="OSPOUTOCN">
327                                         <para>The outbound operator company number.</para>
328                                 </variable>
329                                 <variable name="OSPOUTSPN">
330                                         <para>The outbound service provider name.</para>
331                                 </variable>
332                                 <variable name="OSPOUTALTSPN">
333                                         <para>The outbound alternate service provider name.</para>
334                                 </variable>
335                                 <variable name="OSPOUTMCC">
336                                         <para>The outbound mobile country code.</para>
337                                 </variable>
338                                 <variable name="OSPOUTMNC">
339                                         <para>The outbound mobile network code.</para>
340                                 </variable>
341                                 <variable name="OSPOUTTOKEN">
342                                         <para>The outbound OSP token.</para>
343                                 </variable>
344                                 <variable name="OSPDESTREMAILS">
345                                         <para>The number of remained destinations.</para>
346                                 </variable>
347                                 <variable name="OSPOUTTIMELIMIT">
348                                         <para>The outbound call duration limit in seconds.</para>
349                                 </variable>
350                                 <variable name="OSPOUTCALLID">
351                                         <para>The outbound Call-ID. Only for H.323.</para>
352                                 </variable>
353                                 <variable name="OSPDIALSTR">
354                                         <para>The outbound Dial command string.</para>
355                                 </variable>
356                         </variablelist>
357                         <para>This application sets the following channel variable upon completion:</para>
358                         <variablelist>
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" />
364                                 </variable>
365                         </variablelist>
366                 </description>
367                 <see-also>
368                         <ref type="application">OSPAuth</ref>
369                         <ref type="application">OSPLookup</ref>
370                         <ref type="application">OSPFinish</ref>
371                 </see-also>
372         </application>
373         <application name="OSPFinish" language="en_US">
374                 <synopsis>
375                         Report OSP entry.
376                 </synopsis>
377                 <syntax>
378                         <parameter name="cause">
379                                 <para>Hangup cause.</para>
380                         </parameter>
381                         <parameter name="options">
382                                 <para>Reserved.</para>
383                         </parameter>
384                 </syntax>
385                 <description>
386                         <para>Report call state.</para>
387                         <para>Input variables:</para>
388                         <variablelist>
389                                 <variable name="OSPINHANDLE">
390                                         <para>The inbound call OSP transaction handle.</para>
391                                 </variable>
392                                 <variable name="OSPOUTHANDLE">
393                                         <para>The outbound call OSP transaction handle.</para>
394                                 </variable>
395                                 <variable name="OSPAUTHSTATUS">
396                                         <para>The OSPAuth status.</para>
397                                 </variable>
398                                 <variable name="OSPLOOKUPSTATUS">
399                                         <para>The OSPLookup status.</para>
400                                 </variable>
401                                 <variable name="OSPNEXTSTATUS">
402                                         <para>The OSPNext status.</para>
403                                 </variable>
404                                 <variable name="OSPINAUDIOQOS">
405                                         <para>The inbound call leg audio QoS string.</para>
406                                 </variable>
407                                 <variable name="OSPOUTAUDIOQOS">
408                                         <para>The outbound call leg audio QoS string.</para>
409                                 </variable>
410                         </variablelist>
411                         <para>This application sets the following channel variable upon completion:</para>
412                         <variablelist>
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" />
418                                 </variable>
419                         </variablelist>
420                 </description>
421                 <see-also>
422                         <ref type="application">OSPAuth</ref>
423                         <ref type="application">OSPLookup</ref>
424                         <ref type="application">OSPNext</ref>
425                 </see-also>
426         </application>
427  ***/
428
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 */
438
439 /* Call ID Type*/
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 */
445
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 */
451
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 */
457
458 /* SIP OSP header field name */
459 #define OSP_SIP_HEADER          ((const char*)"P-OSP-Auth-Token")
460
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 */
466 };
467
468 /* OSP Work Mode */
469 enum osp_workmode {
470         OSP_MODE_DIRECT= 0,     /* Direct */
471         OSP_MODE_INDIRECT       /* Indirect */
472 };
473
474 /* OSP Service Type */
475 enum osp_srvtype {
476         OSP_SRV_VOICE = 0,      /* Normal voice service */
477         OSP_SRV_NPQUERY         /* Ported number query service */
478 };
479
480 /* OSP Constants */
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 */
519
520 /* OSP Provider */
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 */
540 };
541
542 /* Call ID */
543 struct osp_callid {
544         unsigned char buf[OSP_SIZE_NORSTR];             /* Call ID string */
545         unsigned int len;                                               /* Call ID length */
546 };
547
548 /* Number Portability Data */
549 struct osp_npdata {
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 */
554 };
555
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 */
560 };
561
562 /* OSP Application In/Output Results */
563 struct osp_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 */
580 };
581
582 /* OSP Call Leg */
583 enum osp_callleg {
584         OSP_CALL_INBOUND,       /* Inbound call leg */
585         OSP_CALL_OUTBOUND       /* Outbound call leg */
586 };
587
588 /* OSP Media Stream Direction */
589 enum osp_direction {
590         OSP_DIR_RX = 0,         /* Receive */
591         OSP_DIR_TX,                     /* Send */
592         OSP_DIR_NUMBER          /* Number of directions */
593 };
594
595 /* OSP Metrics */
596 struct osp_metrics {
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 */
603 };
604
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 */
612
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=";
617
618 /* OSP Client Wrapper APIs */
619
620 /*!
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
625  */
626 static int osp_create_provider(
627         struct ast_config* cfg,
628         const char* name)
629 {
630         int res = OSP_FAILED;
631         struct ast_variable* var;
632         struct osp_provider* provider;
633         OSPTPRIVATEKEY privatekey;
634         OSPT_CERT localcert;
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;
642
643         if (!(provider = ast_calloc(1, sizeof(*provider)))) {
644                 ast_log(LOG_ERROR, "Out of memory\n");
645                 return OSP_ERROR;
646         }
647
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;
662
663         for (var = ast_variable_browse(cfg, name); var != NULL; var = var->next) {
664                 if (!strcasecmp(var->name, "privatekey")) {
665                         if (osp_security) {
666                                 if (var->value[0] == '/') {
667                                         ast_copy_string(provider->privatekey, var->value, sizeof(provider->privatekey));
668                                 } else {
669                                         snprintf(provider->privatekey, sizeof(provider->privatekey), "%s/%s", ast_config_AST_KEY_DIR, var->value);
670                                 }
671                                 ast_debug(1, "OSP: privatekey '%s'\n", provider->privatekey);
672                         }
673                 } else if (!strcasecmp(var->name, "localcert")) {
674                         if (osp_security) {
675                                 if (var->value[0] == '/') {
676                                         ast_copy_string(provider->localcert, var->value, sizeof(provider->localcert));
677                                 } else {
678                                         snprintf(provider->localcert, sizeof(provider->localcert), "%s/%s", ast_config_AST_KEY_DIR, var->value);
679                                 }
680                                 ast_debug(1, "OSP: localcert '%s'\n", provider->localcert);
681                         }
682                 } else if (!strcasecmp(var->name, "cacert")) {
683                         if (osp_security) {
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]));
687                                         } else {
688                                                 snprintf(provider->cacerts[provider->canum], sizeof(provider->cacerts[provider->canum]), "%s/%s", ast_config_AST_KEY_DIR, var->value);
689                                         }
690                                         ast_debug(1, "OSP: cacerts[%d]: '%s'\n", provider->canum, provider->cacerts[provider->canum]);
691                                         provider->canum++;
692                                 } else {
693                                         ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", var->lineno);
694                                 }
695                         }
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]);
700                                 provider->spnum++;
701                         } else {
702                                 ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", var->lineno);
703                         }
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);
708                         } else {
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);
711                         }
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);
716                         } else {
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);
719                         }
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);
724                         } else {
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);
727                         }
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);
732                         } else {
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);
735                         }
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);
743                         } else {
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);
746                         }
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");
760                         } else {
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);
763                         }
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);
768                         } else {
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);
771                         }
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);
776                         } else {
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);
779                         }
780                 }
781         }
782
783         if (provider->canum == 0) {
784                 provider->canum = 1;
785         }
786
787         for (i = 0; i < provider->spnum; i++) {
788                 pspoints[i] = provider->spoints[i];
789         }
790
791         if (osp_security) {
792                 privatekey.PrivateKeyData = NULL;
793                 privatekey.PrivateKeyLength = 0;
794
795                 localcert.CertData = NULL;
796                 localcert.CertDataLength = 0;
797
798                 for (i = 0; i < provider->canum; i++) {
799                         cacerts[i].CertData = NULL;
800                         cacerts[i].CertDataLength = 0;
801                 }
802
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);
807                 } else {
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);
811                                         break;
812                                 } else {
813                                         pcacerts[i] = &cacerts[i];
814                                 }
815                         }
816                 }
817         } else {
818                 privatekey.PrivateKeyData = privatekeydata;
819                 privatekey.PrivateKeyLength = sizeof(privatekeydata);
820
821                 localcert.CertData = localcertdata;
822                 localcert.CertDataLength = sizeof(localcertdata);
823
824                 cacerts[0].CertData = cacertdata;
825                 cacerts[0].CertDataLength = sizeof(cacertdata);
826                 pcacerts[0] = &cacerts[0];
827
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);
834                 }
835         }
836
837         if (error == OSPC_ERR_NO_ERROR) {
838                 error = OSPPProviderNew(provider->spnum,
839                         pspoints,
840                         NULL,
841                         OSP_AUDIT_URL,
842                         &privatekey,
843                         &localcert,
844                         provider->canum,
845                         pcacerts,
846                         OSP_LOCAL_VALIDATION,
847                         OSP_SSL_LIFETIME,
848                         provider->maxconnect,
849                         OSP_HTTP_PERSISTENCE,
850                         provider->retrydelay,
851                         provider->retrylimit,
852                         provider->timeout,
853                         OSP_CUSTOMER_ID,
854                         OSP_DEVICE_ID,
855                         &provider->handle);
856                 if (error != OSPC_ERR_NO_ERROR) {
857                         ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", name, error);
858                         res = OSP_ERROR;
859                 } else {
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);
865                         res = OSP_OK;
866                 }
867         }
868
869         if (osp_security) {
870                 for (i = 0; i < provider->canum; i++) {
871                         if (cacerts[i].CertData) {
872                                 ast_free(cacerts[i].CertData);
873                         }
874                 }
875                 if (localcert.CertData) {
876                         ast_free(localcert.CertData);
877                 }
878                 if (privatekey.PrivateKeyData) {
879                         ast_free(privatekey.PrivateKeyData);
880                 }
881         }
882
883         if (res != OSP_OK) {
884                 ast_free(provider);
885         }
886
887         return res;
888 }
889
890 /*!
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
895  */
896 static int osp_get_provider(
897         const char* name,
898         struct osp_provider** provider)
899 {
900         int res = OSP_FAILED;
901         struct osp_provider* p;
902
903         *provider = NULL;
904
905         ast_mutex_lock(&osp_lock);
906         for (p = osp_providers; p != NULL; p = p->next) {
907                 if (!strcasecmp(p->name, name)) {
908                         *provider = p;
909                         ast_debug(1, "OSP: find provider '%s'\n", name);
910                         res = OSP_OK;
911                         break;
912                 }
913         }
914         ast_mutex_unlock(&osp_lock);
915
916         return res;
917 }
918
919 /*!
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
926  */
927 static int osp_create_transaction(
928         const char* name,
929         int* trans,
930         char* source,
931         unsigned int srcsize)
932 {
933         int res = OSP_FAILED;
934         struct osp_provider* provider;
935         int error;
936
937         if ((trans == NULL) || (source == NULL) || (srcsize <= 0)) {
938                 ast_log(LOG_ERROR, "Invalid parameters\n");
939                 return OSP_ERROR;
940         }
941
942         *trans = OSP_INVALID_HANDLE;
943         *source = '\0';
944
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);
953                                 res = OSP_OK;
954                         } else {
955                                 *trans = OSP_INVALID_HANDLE;
956                                 ast_debug(1, "OSP: Unable to create transaction handle, error '%d'\n", error);
957                                 *source = '\0';
958                                 res = OSP_ERROR;
959                         }
960                         break;
961                 }
962         }
963         ast_mutex_unlock(&osp_lock);
964
965         return res;
966 }
967
968 /*!
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
973  */
974 static void osp_convert_inout(
975         const char* src,
976         char* dest,
977         unsigned int destsize)
978 {
979         struct in_addr inp;
980         char buffer[OSP_SIZE_NORSTR];
981         char* port;
982
983         if ((dest != NULL) && (destsize > 0)) {
984                 if (!ast_strlen_zero(src)) {
985                         ast_copy_string(buffer, src, sizeof(buffer));
986
987                         if((port = strchr(buffer, ':')) != NULL) {
988                                 *port = '\0';
989                                 port++;
990                         }
991
992                         if (inet_pton(AF_INET, buffer, &inp) == 1) {
993                                 if (port != NULL) {
994                                         snprintf(dest, destsize, "[%s]:%s", buffer, port);
995                                 } else {
996                                         snprintf(dest, destsize, "[%s]", buffer);
997                                 }
998                                 dest[destsize - 1] = '\0';
999                         } else {
1000                                 ast_copy_string(dest, src, destsize);
1001                         }
1002                 } else {
1003                         *dest = '\0';
1004                 }
1005         }
1006 }
1007
1008 /*!
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
1013  */
1014 static void osp_convert_outin(
1015         const char* src,
1016         char* dest,
1017         unsigned int destsize)
1018 {
1019         char buffer[OSP_SIZE_NORSTR];
1020         char* end;
1021         char* port;
1022
1023         if ((dest != NULL) && (destsize > 0)) {
1024                 if (!ast_strlen_zero(src)) {
1025                         ast_copy_string(buffer, src, sizeof(buffer));
1026
1027                         if (buffer[0] == '[') {
1028                                 if((port = strchr(buffer + 1, ':')) != NULL) {
1029                                         *port = '\0';
1030                                         port++;
1031                                 }
1032
1033                                 if ((end = strchr(buffer + 1, ']')) != NULL) {
1034                                         *end = '\0';
1035                                 }
1036
1037                                 if (port != NULL) {
1038                                         snprintf(dest, destsize, "%s:%s", buffer + 1, port);
1039                                         dest[destsize - 1] = '\0';
1040                                 } else {
1041                                         ast_copy_string(dest, buffer + 1, destsize);
1042                                 }
1043                         } else {
1044                                 ast_copy_string(dest, src, destsize);
1045                         }
1046                 } else {
1047                         *dest = '\0';
1048                 }
1049         }
1050 }
1051
1052 /*!
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
1062  */
1063 static int osp_validate_token(
1064         int trans,
1065         const char* source,
1066         const char* destination,
1067         const char* calling,
1068         const char* called,
1069         const char* token,
1070         unsigned int* timelimit)
1071 {
1072         int res;
1073         int tokenlen;
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;
1079         int error;
1080
1081         if (timelimit == NULL) {
1082                 ast_log(LOG_ERROR, "Invalid parameters\n");
1083                 return OSP_ERROR;
1084         }
1085
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,
1090                 src,
1091                 dest,
1092                 NULL,
1093                 NULL,
1094                 calling ? calling : "",
1095                 OSPC_NFORMAT_E164,
1096                 called,
1097                 OSPC_NFORMAT_E164,
1098                 0,
1099                 NULL,
1100                 tokenlen,
1101                 (char*)tokenstr,
1102                 &authorised,
1103                 timelimit,
1104                 &dummy,
1105                 NULL,
1106                 osp_tokenformat);
1107         if (error != OSPC_ERR_NO_ERROR) {
1108                 ast_log(LOG_WARNING, "OSP: Unable to validate inbound token, error '%d'\n", error);
1109                 *timelimit = 0;
1110                 res = OSP_ERROR;
1111         } else if (authorised) {
1112                 ast_debug(1, "OSP: Authorised\n");
1113                 res = OSP_OK;
1114         } else {
1115                 ast_debug(1, "OSP: Unauthorised\n");
1116                 res = OSP_FAILED;
1117         }
1118
1119         return res;
1120 }
1121
1122 /*!
1123  * \brief Choose min duration limit
1124  * \param in Inbound duration limit
1125  * \param out Outbound duration limit
1126  * \return min duration limit
1127  */
1128 static unsigned int osp_choose_timelimit(
1129         unsigned int in,
1130         unsigned int out)
1131 {
1132         if (in == OSP_DEF_TIMELIMIT) {
1133                 return out;
1134         } else if (out == OSP_DEF_TIMELIMIT) {
1135                 return in;
1136         } else {
1137                 return in < out ? in : out;
1138         }
1139 }
1140
1141 /*!
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
1152  */
1153 static int osp_check_destination(
1154         struct osp_provider* provider,
1155         const char* calling,
1156         const char* called,
1157         const char* destination,
1158         unsigned int tokenlen,
1159         const char* token,
1160         OSPEFAILREASON* reason,
1161         struct osp_results* results)
1162 {
1163         int res;
1164         OSPE_DEST_OSPENABLED enabled;
1165         OSPE_DEST_PROTOCOL protocol;
1166         char dest[OSP_SIZE_NORSTR];
1167         OSPE_OPERATOR_NAME type;
1168         int error;
1169
1170         if ((provider == NULL) || (reason == NULL) || (results == NULL)) {
1171                 ast_log(LOG_ERROR, "Invalid parameters\n");
1172                 return OSP_ERROR;
1173         }
1174
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;
1178                 return OSP_ERROR;
1179         }
1180
1181         if (enabled == OSPC_DOSP_FALSE) {
1182                 results->token[0] = '\0';
1183         } else {
1184                 ast_base64encode(results->token, (const unsigned char*)token, tokenlen, sizeof(results->token) - 1);
1185         }
1186
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';
1190         }
1191
1192         error = OSPPTransactionGetNumberPortabilityParameters(results->outhandle,
1193                 sizeof(results->nprn),
1194                 results->nprn,
1195                 sizeof(results->npcic),
1196                 results->npcic,
1197                 &results->npdi);
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';
1202                 results->npdi = 0;
1203         }
1204
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';
1210                 }
1211         }
1212
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';
1220                 results->npdi = 0;
1221                 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1222                         results->opname[type][0] = '\0';
1223                 }
1224                 return OSP_ERROR;
1225         }
1226
1227         res = OSP_OK;
1228         osp_convert_outin(destination, dest, sizeof(dest));
1229         switch(protocol) {
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));
1236                 break;
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));
1243                 break;
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));
1250                 break;
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));
1257                 break;
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));
1266                 break;
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:
1272         default:
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';
1279                 results->npdi = 0;
1280                 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1281                         results->opname[type][0] = '\0';
1282                 }
1283                 res = OSP_FAILED;
1284                 break;
1285         }
1286
1287         return res;
1288 }
1289
1290 /*!
1291  * \brief Convert Asterisk status to TC code
1292  * \param cause Asterisk hangup cause
1293  * \return OSP TC code
1294  */
1295 static OSPEFAILREASON asterisk2osp(
1296         int cause)
1297 {
1298         return (OSPEFAILREASON)cause;
1299 }
1300
1301 /*!
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
1311  */
1312 static int osp_auth(
1313         const char* name,
1314         int* trans,
1315         const char* source,
1316         const char* calling,
1317         const char* called,
1318         const char* token,
1319         unsigned int* timelimit)
1320 {
1321         int res;
1322         struct osp_provider* provider = NULL;
1323         char dest[OSP_SIZE_NORSTR];
1324
1325         if ((trans == NULL) || (timelimit == NULL)) {
1326                 ast_log(LOG_ERROR, "Invalid parameters\n");
1327                 return OSP_ERROR;
1328         }
1329
1330         *trans = OSP_INVALID_HANDLE;
1331         *timelimit = OSP_DEF_TIMELIMIT;
1332
1333         if ((res = osp_get_provider(name, &provider)) <= 0) {
1334                 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1335                 return res;
1336         }
1337
1338         switch (provider->authpolicy) {
1339         case OSP_AUTH_NO:
1340                 res = OSP_OK;
1341                 break;
1342         case OSP_AUTH_EXC:
1343                 if (ast_strlen_zero(token)) {
1344                         res = OSP_FAILED;
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;
1348                         res = OSP_FAILED;
1349                 } else if((res = osp_validate_token(*trans, source, dest, calling, called, token, timelimit)) <= 0) {
1350                         OSPPTransactionRecordFailure(*trans, OSPC_FAIL_CALL_REJECTED);
1351                 }
1352                 break;
1353         case OSP_AUTH_YES:
1354         default:
1355                 if (ast_strlen_zero(token)) {
1356                         res = OSP_OK;
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;
1360                         res = OSP_FAILED;
1361                 } else if((res = osp_validate_token(*trans, source, dest, calling, called, token, timelimit)) <= 0) {
1362                         OSPPTransactionRecordFailure(*trans, OSPC_FAIL_CALL_REJECTED);
1363                 }
1364                 break;
1365         }
1366
1367         return res;
1368 }
1369
1370 /*!
1371  * \brief Create a UUID
1372  * \param uuid UUID buffer
1373  * \param bufsize UUID buffer size
1374  * \return OSK_OK Created, OSP_ERROR Error
1375  */
1376 static int osp_create_uuid(
1377         unsigned char* uuid,
1378         unsigned int* bufsize)
1379 {
1380         int i, res;
1381         long int tmp[OSP_SIZE_UUID / sizeof(long int)];
1382
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();
1386                 }
1387                 memcpy(uuid, tmp, OSP_SIZE_UUID);
1388                 *bufsize = OSP_SIZE_UUID;
1389                 res = OSP_OK;
1390         } else {
1391                 ast_log(LOG_ERROR, "Invalid parameters\n");
1392                 res = OSP_ERROR;
1393         }
1394
1395         return res;
1396 }
1397
1398 /*!
1399  * \brief UUID to string
1400  * \param uuid UUID
1401  * \param buffer String buffer
1402  * \param bufsize String buffer size
1403  * \return OSP_OK Successed, OSP_ERROR Error
1404  */
1405 static int osp_uuid2str(
1406         unsigned char* uuid,
1407         char* buffer,
1408         unsigned int bufsize)
1409 {
1410         int res;
1411
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]);
1416                 res = OSP_OK;
1417         } else {
1418                 ast_log(LOG_ERROR, "Invalid parameters\n");
1419                 res = OSP_ERROR;
1420         }
1421
1422         return res;
1423 }
1424
1425 /*!
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
1430  */
1431 static int osp_create_callid(
1432         unsigned int type,
1433         struct osp_callid* callid)
1434 {
1435         int res;
1436
1437         if (callid == NULL) {
1438                 ast_log(LOG_ERROR, "Invalid parameters\n");
1439                 res = OSP_ERROR;
1440         }
1441
1442         callid->len = sizeof(callid->buf);
1443         switch (type) {
1444         case OSP_CALLID_H323:
1445                 res = osp_create_uuid(callid->buf, &callid->len);
1446                 break;
1447         case OSP_CALLID_SIP:
1448         case OSP_CALLID_IAX:
1449                 res = OSP_FAILED;
1450         default:
1451                 res = OSP_ERROR;
1452                 break;
1453         }
1454
1455         if ((res != OSP_OK) && (callid->len != 0)) {
1456                 callid->buf[0] = '\0';
1457                 callid->len = 0;
1458         }
1459
1460         return res;
1461 }
1462
1463 /*!
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
1477  */
1478 static int osp_lookup(
1479         const char* name,
1480         unsigned int callidtypes,
1481         const char* actualsrc,
1482         const char* srcdev,
1483         const char* calling,
1484         const char* called,
1485         const char* snetid,
1486         struct osp_npdata* np,
1487         struct osp_diversion* div,
1488         const char* cinfo[],
1489         struct osp_results* results)
1490 {
1491         int res;
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];
1497         char* tmp;
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;
1511         int error;
1512
1513         if (results == NULL) {
1514                 ast_log(LOG_ERROR, "Invalid parameters\n");
1515                 res = OSP_ERROR;
1516         }
1517
1518         osp_convert_inout(results->dest, dest, sizeof(dest));
1519
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';
1528         results->npdi = 0;
1529         for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1530                 results->opname[type][0] = '\0';
1531         }
1532         results->numdests = 0;
1533         results->outtimelimit = OSP_DEF_TIMELIMIT;
1534
1535         if ((res = osp_get_provider(name, &provider)) <= 0) {
1536                 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1537                 return res;
1538         }
1539
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);
1545                 }
1546                 return OSP_ERROR;
1547         }
1548
1549         if (!ast_strlen_zero(snetid)) {
1550                 OSPPTransactionSetNetworkIds(results->outhandle, snetid, "");
1551         }
1552
1553         OSPPTransactionSetNumberPortability(results->outhandle, np->rn, np->cic, np->npdi);
1554
1555         for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1556                 OSPPTransactionSetOperatorName(results->outhandle, type, np->opname[type]);
1557         }
1558
1559         osp_convert_inout(div->host, host, sizeof(host));
1560         OSPPTransactionSetDiversion(results->outhandle, div->user, host);
1561
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]);
1566                         }
1567                 }
1568         }
1569
1570         ast_copy_string(callednum, called, sizeof(callednum));
1571         if((tmp = strchr(callednum, ';')) != NULL) {
1572                 *tmp = '\0';
1573         }
1574
1575         callidnum = 0;
1576         callids[0] = NULL;
1577         for (i = 0; i < OSP_CALLID_MAXNUM; i++) {
1578                 type = 1 << i;
1579                 if (callidtypes & type) {
1580                         error = osp_create_callid(type, &callid);
1581                         if (error == 1) {
1582                                 callids[callidnum] = OSPPCallIdNew(callid.len, callid.buf);
1583                                 callidnum++;
1584                         }
1585                 }
1586         }
1587
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));
1592                 } else {
1593                         osp_convert_inout(actualsrc, dev, sizeof(dev));
1594                 }
1595         } else {
1596                 osp_convert_inout(source, src, sizeof(src));
1597                 osp_convert_inout(srcdev, dev, sizeof(dev));
1598         }
1599
1600         if (provider->srvtype == OSP_SRV_NPQUERY) {
1601                 OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_NPQUERY);
1602                 if (!ast_strlen_zero(dest)) {
1603                         preferred[0] = dest;
1604                 }
1605                 results->numdests = 1;
1606         } else {
1607                 OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_VOICE);
1608                 results->numdests = OSP_DEF_MAXDESTS;
1609         }
1610         error = OSPPTransactionRequestAuthorisation(results->outhandle,
1611                 src,
1612                 dev,
1613                 calling ? calling : "",
1614                 OSPC_NFORMAT_E164,
1615                 callednum,
1616                 OSPC_NFORMAT_E164,
1617                 NULL,
1618                 callidnum,
1619                 callids,
1620                 preferred,
1621                 &results->numdests,
1622                 &dummy,
1623                 NULL);
1624
1625         for (i = 0; i < callidnum; i++) {
1626                 OSPPCallIdDelete(&callids[i]);
1627         }
1628
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);
1634                 }
1635                 return OSP_ERROR;
1636         }
1637
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);
1642                 }
1643                 return OSP_FAILED;
1644         }
1645
1646         results->outcallid.len = sizeof(results->outcallid.buf);
1647         tokenlen = sizeof(token);
1648         error = OSPPTransactionGetFirstDestination(results->outhandle,
1649                 0,
1650                 NULL,
1651                 NULL,
1652                 &results->outtimelimit,
1653                 &results->outcallid.len,
1654                 results->outcallid.buf,
1655                 sizeof(callednum),
1656                 callednum,
1657                 sizeof(callingnum),
1658                 callingnum,
1659                 sizeof(destination),
1660                 destination,
1661                 0,
1662                 NULL,
1663                 &tokenlen,
1664                 token);
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);
1671                 }
1672                 return OSP_ERROR;
1673         }
1674
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);
1682
1683         if ((res = osp_check_destination(provider, callingnum, callednum, destination, tokenlen, token, &reason, results)) > 0) {
1684                 return OSP_OK;
1685         }
1686
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);
1693                 }
1694                 return OSP_FAILED;
1695         }
1696
1697         while(results->numdests) {
1698                 results->outcallid.len = sizeof(results->outcallid.buf);
1699                 tokenlen = sizeof(token);
1700                 error = OSPPTransactionGetNextDestination(results->outhandle,
1701                         reason,
1702                         0,
1703                         NULL,
1704                         NULL,
1705                         &results->outtimelimit,
1706                         &results->outcallid.len,
1707                         results->outcallid.buf,
1708                         sizeof(callednum),
1709                         callednum,
1710                         sizeof(callingnum),
1711                         callingnum,
1712                         sizeof(destination),
1713                         destination,
1714                         0,
1715                         NULL,
1716                         &tokenlen,
1717                         token);
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);
1726
1727                         if ((res = osp_check_destination(provider, callingnum, callednum, destination, tokenlen, token, &reason, results)) > 0) {
1728                                 break;
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);
1734                                 }
1735                                 res = OSP_FAILED;
1736                                 break;
1737                         }
1738                 } else {
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);
1744                         }
1745                         res = OSP_ERROR;
1746                         break;
1747                 }
1748         }
1749
1750         return res;
1751 }
1752
1753 /*!
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
1759  */
1760 static int osp_next(
1761         const char* name,
1762         int cause,
1763         struct osp_results* results)
1764 {
1765         int res;
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;
1774         int error;
1775
1776         if (results == NULL) {
1777                 ast_log(LOG_ERROR, "Invalid parameters\n");
1778                 res = OSP_ERROR;
1779         }
1780
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';
1789         results->npdi = 0;
1790         for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1791                 results->opname[type][0] = '\0';
1792         }
1793         results->outtimelimit = OSP_DEF_TIMELIMIT;
1794
1795         if ((res = osp_get_provider(name, &provider)) <= 0) {
1796                 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1797                 return res;
1798         }
1799
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);
1805                 }
1806                 return OSP_ERROR;
1807         }
1808
1809         reason = asterisk2osp(cause);
1810
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);
1816                 }
1817                 return OSP_FAILED;
1818         }
1819
1820         while(results->numdests) {
1821                 results->outcallid.len = sizeof(results->outcallid.buf);
1822                 tokenlen = sizeof(token);
1823                 error = OSPPTransactionGetNextDestination(
1824                         results->outhandle,
1825                         reason,
1826                         0,
1827                         NULL,
1828                         NULL,
1829                         &results->outtimelimit,
1830                         &results->outcallid.len,
1831                         results->outcallid.buf,
1832                         sizeof(called),
1833                         called,
1834                         sizeof(calling),
1835                         calling,
1836                         sizeof(dest),
1837                         dest,
1838                         0,
1839                         NULL,
1840                         &tokenlen,
1841                         token);
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);
1850
1851                         if ((res = osp_check_destination(provider, calling, called, dest, tokenlen, token, &reason, results)) > 0) {
1852                                 res = OSP_OK;
1853                                 break;
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);
1859                                 }
1860                                 res = OSP_FAILED;
1861                                 break;
1862                         }
1863                 } else {
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);
1870                         }
1871                         res = OSP_ERROR;
1872                         break;
1873                 }
1874         }
1875
1876         return res;
1877 }
1878
1879 /*!
1880  * \brief Get integer from variable string
1881  * \param vstr Variable string
1882  * \return OSP_DEF_INTSTATS Error
1883  */
1884 static int osp_get_varint(
1885         const char* vstr)
1886 {
1887         char* tmp;
1888         int value = OSP_DEF_INTSTATS;
1889
1890         if (!ast_strlen_zero(vstr)) {
1891                 if ((tmp = strchr(vstr, '=')) != NULL) {
1892                         tmp++;
1893                         if (sscanf(tmp, "%30d", &value) != 1) {
1894                                 value = OSP_DEF_INTSTATS;
1895                         }
1896                 }
1897         }
1898
1899         return value;
1900 }
1901
1902 /*!
1903  * \brief Get float from variable string
1904  * \param vstr Variable string
1905  * \return OSP_DEF_FLOATSTATS Error
1906  */
1907 static float osp_get_varfloat(
1908         const char* vstr)
1909 {
1910         char* tmp;
1911         float value = OSP_DEF_FLOATSTATS;
1912
1913         if (!ast_strlen_zero(vstr)) {
1914                 if ((tmp = strchr(vstr, '=')) != NULL) {
1915                         tmp++;
1916                         if (sscanf(tmp, "%30f", &value) != 1) {
1917                                 value = OSP_DEF_FLOATSTATS;
1918                         }
1919                 }
1920         }
1921
1922         return value;
1923 }
1924
1925 /*!
1926  * \brief Report QoS
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
1931  */
1932 static int osp_report_qos(
1933         int trans,
1934         enum osp_callleg leg,
1935         const char* qos)
1936 {
1937         int res = OSP_FAILED;
1938         enum osp_direction dir;
1939         char buffer[OSP_SIZE_NORSTR];
1940         char* tmp;
1941         char* item;
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;
1946         int value;
1947
1948         if (!ast_strlen_zero(qos)) {
1949                 for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
1950                         totalpackets[dir] = OSP_DEF_INTSTATS;
1951                 }
1952
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;
1959                 }
1960
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;
1967                 }
1968
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;
1974
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);
2031                         }
2032                 }
2033
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);
2062
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;
2068                         } else {
2069                                 value = (int)lost[OSP_DIR_RX].avg;
2070                         }
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;
2074                         } else {
2075                                 value = (int)lost[OSP_DIR_TX].avg;
2076                         }
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;
2080                         } else {
2081                                 value = (int)jitter[OSP_DIR_RX].avg;
2082                         }
2083                         OSPPTransactionSetJitter(trans,
2084                                 OSPC_SMETRIC_RTP,
2085                                 OSPC_SFLOW_DOWNSTREAM,
2086                                 OSP_DEF_INTSTATS,
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;
2092                         } else {
2093                                 value = (int)jitter[OSP_DIR_TX].avg;
2094                         }
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);
2097                 } else {
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;
2104                         } else {
2105                                 value = (int)jitter[OSP_DIR_RX].avg;
2106                         }
2107                         OSPPTransactionSetJitter(trans,
2108                                 OSPC_SMETRIC_RTP,
2109                                 OSPC_SFLOW_UPSTREAM,
2110                                 OSP_DEF_INTSTATS,
2111                                 (int)jitter[OSP_DIR_RX].min,
2112                                 (int)jitter[OSP_DIR_RX].max,
2113                                 value,
2114                                 jitter[OSP_DIR_RX].sdev);
2115                         if (jitter[OSP_DIR_TX].value >= 0) {
2116                                 value = jitter[OSP_DIR_TX].value;
2117                         } else {
2118                                 value = (int)jitter[OSP_DIR_TX].avg;
2119                         }
2120                         OSPPTransactionSetJitter(trans,
2121                                 OSPC_SMETRIC_RTCP,
2122                                 OSPC_SFLOW_DOWNSTREAM,
2123                                 OSP_DEF_INTSTATS,
2124                                 (int)jitter[OSP_DIR_TX].min,
2125                                 (int)jitter[OSP_DIR_TX].max,
2126                                 value,
2127                                 jitter[OSP_DIR_TX].sdev);
2128                 }
2129                 if (rtt.value >= 0) {
2130                         value = rtt.value;
2131                 } else {
2132                         value = (int)rtt.avg;
2133                 }
2134                 OSPPTransactionSetRoundTripDelay(trans, OSP_DEF_INTSTATS, (int)rtt.min, (int)rtt.max, value, rtt.sdev);
2135
2136                 res = OSP_OK;
2137         }
2138
2139         return res;
2140 }
2141
2142 /*!
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
2154  */
2155 static int osp_finish(
2156         int trans,
2157         int recorded,
2158         int cause,
2159         time_t start,
2160         time_t connect,
2161         time_t end,
2162         unsigned int release,
2163         const char* inqos,
2164         const char* outqos)
2165 {
2166         int res;
2167         OSPEFAILREASON reason;
2168         time_t alert = 0;
2169         unsigned isPddInfoPresent = 0;
2170         unsigned pdd = 0;
2171         unsigned int dummy = 0;
2172         int error;
2173
2174         if (trans == OSP_INVALID_HANDLE) {
2175                 return OSP_FAILED;
2176         }
2177
2178         if (!recorded) {
2179                 reason = asterisk2osp(cause);
2180                 OSPPTransactionRecordFailure(trans, reason);
2181         }
2182
2183         osp_report_qos(trans, OSP_CALL_INBOUND, inqos);
2184         osp_report_qos(trans, OSP_CALL_OUTBOUND, outqos);
2185
2186         error = OSPPTransactionReportUsage(trans,
2187                 difftime(end, connect),
2188                 start,
2189                 end,
2190                 alert,
2191                 connect,
2192                 isPddInfoPresent,
2193                 pdd,
2194                 release,
2195                 NULL,
2196                 OSP_DEF_INTSTATS,
2197                 OSP_DEF_INTSTATS,
2198                 OSP_DEF_INTSTATS,
2199                 OSP_DEF_INTSTATS,
2200                 &dummy,
2201                 NULL);
2202         if (error == OSPC_ERR_NO_ERROR) {
2203                 ast_debug(1, "OSP: Usage reported\n");
2204                 res = OSP_OK;
2205         } else {
2206                 ast_debug(1, "OSP: Unable to report usage, error '%d'\n", error);
2207                 res = OSP_ERROR;
2208         }
2209         OSPPTransactionDelete(trans);
2210
2211         return res;
2212 }
2213
2214 /* OSP Application APIs */
2215
2216 /*!
2217  * \brief OSP Application OSPAuth
2218  * \param chan Channel
2219  * \param data Parameter
2220  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2221  */
2222 static int ospauth_exec(
2223         struct ast_channel *chan,
2224         const char *data)
2225 {
2226         int res;
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 = "";
2232         int handle;
2233         unsigned int timelimit;
2234         char buffer[OSP_SIZE_INTSTR];
2235         const char* status;
2236         char* tmp;
2237
2238         AST_DECLARE_APP_ARGS(args,
2239                 AST_APP_ARG(provider);
2240                 AST_APP_ARG(options);
2241         );
2242
2243         if (!(tmp = ast_strdupa(data))) {
2244                 ast_log(LOG_ERROR, "Out of memory\n");
2245                 return OSP_AST_ERROR;
2246         }
2247
2248         AST_STANDARD_APP_ARGS(args, tmp);
2249
2250         if (!ast_strlen_zero(args.provider)) {
2251                 provider = args.provider;
2252         }
2253         ast_debug(1, "OSPAuth: provider '%s'\n", provider);
2254
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);
2261                 }
2262         }
2263
2264         ast_debug(1, "OSPAuth: source '%s'\n", source);
2265         ast_debug(1, "OSPAuth: token size '%zd'\n", strlen(token));
2266
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);
2270         if (res > 0) {
2271                 status = AST_OSP_SUCCESS;
2272         } else {
2273                 timelimit = OSP_DEF_TIMELIMIT;
2274                 if (!res) {
2275                         status = AST_OSP_FAILED;
2276                 } else {
2277                         status = AST_OSP_ERROR;
2278                 }
2279         }
2280
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);
2289
2290         if(res != OSP_OK) {
2291                 res = OSP_AST_ERROR;
2292         } else {
2293                 res = OSP_AST_OK;
2294         }
2295
2296         return res;
2297 }
2298
2299 /*!
2300  * \brief OSP Application OSPLookup
2301  * \param chan Channel
2302  * \param data Parameter
2303  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2304  */
2305 static int osplookup_exec(
2306         struct ast_channel* chan,
2307         const char * data)
2308 {
2309         int res, cres;
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;
2320         unsigned int i;
2321         const char* cinfo[OSP_MAX_CUSTOMINFO] = { NULL };
2322         char buffer[OSP_SIZE_TOKSTR];
2323         struct osp_results results;
2324         const char* status;
2325         char* tmp;
2326
2327         AST_DECLARE_APP_ARGS(args,
2328                 AST_APP_ARG(exten);
2329                 AST_APP_ARG(provider);
2330                 AST_APP_ARG(options);
2331         );
2332
2333         if (ast_strlen_zero(data)) {
2334                 ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[,provider[,options]])\n");
2335                 return OSP_AST_ERROR;
2336         }
2337
2338         if (!(tmp = ast_strdupa(data))) {
2339                 ast_log(LOG_ERROR, "Out of memory\n");
2340                 return OSP_AST_ERROR;
2341         }
2342
2343         AST_STANDARD_APP_ARGS(args, tmp);
2344
2345         ast_debug(1, "OSPLookup: exten '%s'\n", args.exten);
2346
2347         if (!ast_strlen_zero(args.provider)) {
2348                 provider = args.provider;
2349         }
2350         ast_debug(1, "OSPlookup: provider '%s'\n", provider);
2351
2352         if (args.options) {
2353                 if (strchr(args.options, 'h')) {
2354                         callidtypes |= OSP_CALLID_H323;
2355                 }
2356                 if (strchr(args.options, 's')) {
2357                         callidtypes |= OSP_CALLID_SIP;
2358                 }
2359                 if (strchr(args.options, 'i')) {
2360                         callidtypes |= OSP_CALLID_IAX;
2361                 }
2362         }
2363         ast_debug(1, "OSPLookup: call id types '%d'\n", callidtypes);
2364
2365         results.inhandle = OSP_INVALID_HANDLE;
2366         results.intimelimit = OSP_DEF_TIMELIMIT;
2367         results.dest[0] = '\0';
2368
2369         np.rn = "";
2370         np.cic = "";
2371         np.npdi = 0;
2372         for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2373                 np.opname[type] = "";
2374         }
2375
2376         div.user = "";
2377         div.host = "";
2378
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;
2388                         }
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;
2392                         }
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))) {
2401                                 np.npdi = 1;
2402                         }
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);
2437                 }
2438         }
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]);
2459                 }
2460         }
2461
2462         if ((cres = ast_autoservice_start(chan)) < 0) {
2463                 return OSP_AST_ERROR;
2464         }
2465
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);
2469         if (res > 0) {
2470                 status = AST_OSP_SUCCESS;
2471         } else {
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';
2480                 results.npdi = 0;
2481                 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2482                         results.opname[type][0] = '\0';
2483                 }
2484                 results.numdests = 0;
2485                 results.outtimelimit = OSP_DEF_TIMELIMIT;
2486                 results.outcallid.buf[0] = '\0';
2487                 results.outcallid.len = 0;
2488                 if (!res) {
2489                         status = AST_OSP_FAILED;
2490                 } else {
2491                         status = AST_OSP_ERROR;
2492                 }
2493         }
2494
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);
2540
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));
2548                 }
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));
2552                 } else {
2553                         buffer[0] = '\0';
2554                 }
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);
2564         }
2565
2566         if ((cres = ast_autoservice_stop(chan)) < 0) {
2567                 return OSP_AST_ERROR;
2568         }
2569
2570         if(res != OSP_OK) {
2571                 res = OSP_AST_ERROR;
2572         } else {
2573                 res = OSP_AST_OK;
2574         }
2575
2576         return res;
2577 }
2578
2579 /*!
2580  * \brief OSP Application OSPNext
2581  * \param chan Channel
2582  * \param data Parameter
2583  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2584  */
2585 static int ospnext_exec(
2586         struct ast_channel* chan,
2587         const char * data)
2588 {
2589         int res;
2590         const char* provider = OSP_DEF_PROVIDER;
2591         int cause = 0;
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;
2598         const char* status;
2599         char* tmp;
2600
2601         AST_DECLARE_APP_ARGS(args,
2602                 AST_APP_ARG(cause);
2603                 AST_APP_ARG(provider);
2604                 AST_APP_ARG(options);
2605         );
2606
2607         if (ast_strlen_zero(data)) {
2608                 ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[,provider[,options]])\n");
2609                 return OSP_AST_ERROR;
2610         }
2611
2612         if (!(tmp = ast_strdupa(data))) {
2613                 ast_log(LOG_ERROR, "Out of memory\n");
2614                 return OSP_AST_ERROR;
2615         }
2616
2617         AST_STANDARD_APP_ARGS(args, tmp);
2618
2619         if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
2620                 cause = 0;
2621         }
2622         ast_debug(1, "OSPNext: cause '%d'\n", cause);
2623
2624         if (!ast_strlen_zero(args.provider)) {
2625                 provider = args.provider;
2626         }
2627         ast_debug(1, "OSPlookup: provider '%s'\n", provider);
2628
2629         results.inhandle = OSP_INVALID_HANDLE;
2630         results.outhandle = OSP_INVALID_HANDLE;
2631         results.intimelimit = OSP_DEF_TIMELIMIT;
2632         results.numdests = 0;
2633
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;
2639                         }
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;
2643                         }
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;
2647                         }
2648                 } else if (!strcasecmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) {
2649                         if (sscanf(ast_var_value(current), "%30d", &callidtypes) != 1) {
2650                                 callidtypes = OSP_CALLID_UNDEF;
2651                         }
2652                 } else if (!strcasecmp(ast_var_name(current), "OSPDESTREMAILS")) {
2653                         if (sscanf(ast_var_value(current), "%30d", &results.numdests) != 1) {
2654                                 results.numdests = 0;
2655                         }
2656                 }
2657         }
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);
2663
2664         if ((res = osp_next(provider, cause, &results)) > 0) {
2665                 status = AST_OSP_SUCCESS;
2666         } else {
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';
2675                 results.npdi = 0;
2676                 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2677                         results.opname[type][0] = '\0';
2678                 }
2679                 results.numdests = 0;
2680                 results.outtimelimit = OSP_DEF_TIMELIMIT;
2681                 results.outcallid.buf[0] = '\0';
2682                 results.outcallid.len = 0;
2683                 if (!res) {
2684                         status = AST_OSP_FAILED;
2685                 } else {
2686                         status = AST_OSP_ERROR;
2687                 }
2688         }
2689
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);
2729
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));
2737                 }
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));
2741                 } else {
2742                         buffer[0] = '\0';
2743                 }
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);
2753         }
2754
2755         if(res != OSP_OK) {
2756                 res = OSP_AST_ERROR;
2757         } else {
2758                 res = OSP_AST_OK;
2759         }
2760
2761         return res;
2762 }
2763
2764 /*!
2765  * \brief OSP Application OSPFinish
2766  * \param chan Channel
2767  * \param data Parameter
2768  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2769  */
2770 static int ospfinished_exec(
2771         struct ast_channel* chan,
2772         const char * data)
2773 {
2774         int res = OSP_OK;
2775         int cause = 0;
2776         struct varshead* headp;
2777         struct ast_var_t* current;
2778         int inhandle = OSP_INVALID_HANDLE;
2779         int outhandle = OSP_INVALID_HANDLE;
2780         int recorded = 0;
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 };
2786         const char* status;
2787         char* tmp;
2788
2789         AST_DECLARE_APP_ARGS(args,
2790                 AST_APP_ARG(cause);
2791                 AST_APP_ARG(options);
2792         );
2793
2794         if (!(tmp = ast_strdupa(data))) {
2795                 ast_log(LOG_ERROR, "Out of memory\n");
2796                 return OSP_AST_ERROR;
2797         }
2798
2799         AST_STANDARD_APP_ARGS(args, tmp);
2800
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;
2806                         }
2807                 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
2808                         if (sscanf(ast_var_value(current), "%30d", &outhandle) != 1) {
2809                                 outhandle = OSP_INVALID_HANDLE;
2810                         }
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")))
2815                 {
2816                         if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) {
2817                                 recorded = 1;
2818                         }
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));
2823                 }
2824         }
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);
2830
2831         if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
2832                 cause = 0;
2833         }
2834         ast_debug(1, "OSPFinish: cause '%d'\n", cause);
2835
2836         if (chan->cdr) {
2837                 start = chan->cdr->start.tv_sec;
2838                 connect = chan->cdr->answer.tv_sec;
2839                 if (connect) {
2840                         end = time(NULL);
2841                 } else {
2842                         end = connect;
2843                 }
2844         } else {
2845                 start = 0;
2846                 connect = 0;
2847                 end = 0;
2848         }
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);
2852
2853         release = ast_check_hangup(chan) ? 0 : 1;
2854
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");
2857         }
2858         switch (cause) {
2859         case AST_CAUSE_NORMAL_CLEARING:
2860                 break;
2861         default:
2862                 cause = AST_CAUSE_NO_ROUTE_DESTINATION;
2863                 break;
2864         }
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");
2867         }
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);
2871
2872         if (res > 0) {
2873                 status = AST_OSP_SUCCESS;
2874         } else if (!res) {
2875                 status = AST_OSP_FAILED;
2876         } else {
2877                 status = AST_OSP_ERROR;
2878         }
2879         pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
2880
2881         if(res != OSP_OK) {
2882                 res = OSP_AST_ERROR;
2883         } else {
2884                 res = OSP_AST_OK;
2885         }
2886
2887         return res;
2888 }
2889
2890 /* OSP Module APIs */
2891
2892 static int osp_unload(void)
2893 {
2894         struct osp_provider* provider;
2895         struct osp_provider* next;
2896
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);
2902                         ast_free(provider);
2903                 }
2904                 osp_providers = NULL;
2905                 ast_mutex_unlock(&osp_lock);
2906
2907                 OSPPCleanup();
2908
2909                 osp_tokenformat = TOKEN_ALGO_SIGNED;
2910                 osp_security = 0;
2911                 osp_hardware = 0;
2912                 osp_initialized = 0;
2913         }
2914
2915         return 0;
2916 }
2917
2918 static int osp_load(int reload)
2919 {
2920         const char* cvar;
2921         unsigned int ivar;
2922         struct ast_config* cfg;
2923         struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2924         int error = OSPC_ERR_NO_ERROR;
2925
2926         if ((cfg = ast_config_load(OSP_CONFIG_FILE, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
2927                 return 0;
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);
2930                 return 0;
2931         }
2932
2933         if (cfg) {
2934                 if (reload) {
2935                         osp_unload();
2936                 }
2937
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");
2941                                 OSPPInit(0);
2942                         } else {
2943                                 osp_hardware = 1;
2944                         }
2945                 } else {
2946                         OSPPInit(0);
2947                 }
2948                 ast_debug(1, "OSP: osp_hardware '%d'\n", osp_hardware);
2949
2950                 if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "securityfeatures")) && ast_true(cvar)) {
2951                         osp_security = 1;
2952                 }
2953                 ast_debug(1, "OSP: osp_security '%d'\n", osp_security);
2954
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)))
2958                         {
2959                                 osp_tokenformat = ivar;
2960                         } else {
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);
2963                         }
2964                 }
2965                 ast_debug(1, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
2966
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);
2970                         }
2971                 }
2972
2973                 osp_initialized = 1;
2974
2975                 ast_config_destroy(cfg);
2976         } else {
2977                 ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
2978                 return 0;
2979         }
2980         ast_debug(1, "OSP: osp_initialized '%d'\n", osp_initialized);
2981
2982         return 1;
2983 }
2984
2985 static char *handle_cli_osp_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2986 {
2987         int i;
2988         int found = 0;
2989         struct osp_provider* provider;
2990         const char* name = NULL;
2991         const char* tokenalgo;
2992
2993         switch (cmd) {
2994         case CLI_INIT:
2995                 e->command = "osp show";
2996                 e->usage =
2997                         "Usage: osp show\n"
2998                         "       Displays information on Open Settlement Protocol support\n";
2999                 return NULL;
3000         case CLI_GENERATE:
3001                 return NULL;
3002         }
3003
3004         if ((a->argc < 2) || (a->argc > 3)) {
3005                 return CLI_SHOWUSAGE;
3006         }
3007
3008         if (a->argc > 2) {
3009                 name = a->argv[2];
3010         }
3011
3012         if (!name) {
3013                 switch (osp_tokenformat) {
3014                 case TOKEN_ALGO_BOTH:
3015                         tokenalgo = "Both";
3016                         break;
3017                 case TOKEN_ALGO_UNSIGNED:
3018                         tokenalgo = "Unsigned";
3019                         break;
3020                 case TOKEN_ALGO_SIGNED:
3021                 default:
3022                         tokenalgo = "Signed";
3023                         break;
3024                 }
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",
3029                         tokenalgo);
3030         }
3031
3032         ast_mutex_lock(&osp_lock);
3033         for (provider = osp_providers; provider; provider = provider->next) {
3034                 if (!name || !strcasecmp(provider->name, name)) {
3035                         if (found) {
3036                                 ast_cli(a->fd, "\n");
3037                         }
3038                         ast_cli(a->fd, " == OSP Provider '%s' == \n", provider->name);
3039                         if (osp_security) {
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]);
3044                                 }
3045                         }
3046                         for (i = 0; i < provider->spnum; i++) {
3047                                 ast_cli(a->fd, "Service Point %d:   %s\n", i + 1, provider->spoints[i]);
3048                         }
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);
3059                         found++;
3060                 }
3061         }
3062         ast_mutex_unlock(&osp_lock);
3063
3064         if (!found) {
3065                 if (name) {
3066                         ast_cli(a->fd, "Unable to find OSP provider '%s'\n", name);
3067                 } else {
3068                         ast_cli(a->fd, "No OSP providers configured\n");
3069                 }
3070         }
3071
3072         return CLI_SUCCESS;
3073 }
3074
3075 /* OSPAuth() dialplan application */
3076 static const char app1[] = "OSPAuth";
3077
3078 /* OSPLookup() dialplan application */
3079 static const char app2[] = "OSPLookup";
3080
3081 /* OSPNext() dialplan application */
3082 static const char app3[] = "OSPNext";
3083
3084 /* OSPFinish() dialplan application */
3085 static const char app4[] = "OSPFinish";
3086
3087 static struct ast_cli_entry cli_osp[] = {
3088         AST_CLI_DEFINE(handle_cli_osp_show, "Displays OSF information")
3089 };
3090
3091 static int load_module(void)
3092 {
3093         int res;
3094
3095         if (!osp_load(0))
3096                 return AST_MODULE_LOAD_DECLINE;
3097
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);
3103
3104         return res;
3105 }
3106
3107 static int unload_module(void)
3108 {
3109         int res;
3110
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));
3116         osp_unload();
3117
3118         return res;
3119 }
3120
3121 static int reload(void)
3122 {
3123         osp_load(1);
3124
3125         return 0;
3126 }
3127
3128 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
3129         .load = load_module,
3130         .unload = unload_module,
3131         .reload = reload,
3132 );