Merge "res_musiconhold: Start playlist after initial announcement"
[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 #include <osp/osp.h>
40 #include <osp/osputils.h>
41 #include <osp/ospb64.h>
42
43 #include "asterisk/paths.h"
44 #include "asterisk/lock.h"
45 #include "asterisk/config.h"
46 #include "asterisk/utils.h"
47 #include "asterisk/causes.h"
48 #include "asterisk/channel.h"
49 #include "asterisk/app.h"
50 #include "asterisk/module.h"
51 #include "asterisk/pbx.h"
52 #include "asterisk/cli.h"
53 #include "asterisk/astosp.h"
54
55 /*** DOCUMENTATION
56         <application name="OSPAuth" language="en_US">
57                 <synopsis>
58                         OSP Authentication.
59                 </synopsis>
60                 <syntax>
61                         <parameter name="provider">
62                                 <para>The name of the provider that authenticates the call.</para>
63                         </parameter>
64                         <parameter name="options">
65                                 <para>Reserverd.</para>
66                         </parameter>
67                 </syntax>
68                 <description>
69                         <para>Authenticate a call by OSP.</para>
70                         <para>Input variables:</para>
71                         <variablelist>
72                                 <variable name="OSPINPEERIP">
73                                         <para>The last hop IP address.</para>
74                                 </variable>
75                                 <variable name="OSPINTOKEN">
76                                         <para>The inbound OSP token.</para>
77                                 </variable>
78                         </variablelist>
79                         <para>Output variables:</para>
80                         <variablelist>
81                                 <variable name="OSPINHANDLE">
82                                         <para>The inbound call OSP transaction handle.</para>
83                                 </variable>
84                                 <variable name="OSPINTIMELIMIT">
85                                         <para>The inbound call duration limit in seconds.</para>
86                                 </variable>
87                         </variablelist>
88                         <para>This application sets the following channel variable upon completion:</para>
89                         <variablelist>
90                                 <variable name="OSPAUTHSTATUS">
91                                         <para>The status of OSPAuth attempt as a text string, one of</para>
92                                         <value name="SUCCESS" />
93                                         <value name="FAILED" />
94                                         <value name="ERROR" />
95                                 </variable>
96                         </variablelist>
97                 </description>
98                 <see-also>
99                         <ref type="application">OSPLookup</ref>
100                         <ref type="application">OSPNext</ref>
101                         <ref type="application">OSPFinish</ref>
102                 </see-also>
103         </application>
104         <application name="OSPLookup" language="en_US">
105                 <synopsis>
106                         Lookup destination by OSP.
107                 </synopsis>
108                 <syntax>
109                         <parameter name="exten" required="true">
110                                 <para>The exten of the call.</para>
111                         </parameter>
112                         <parameter name="provider">
113                                 <para>The name of the provider that is used to route the call.</para>
114                         </parameter>
115                         <parameter name="options">
116                                 <enumlist>
117                                         <enum name="h">
118                                                 <para>generate H323 call id for the outbound call</para>
119                                         </enum>
120                                         <enum name="s">
121                                                 <para>generate SIP call id for the outbound call. Have not been implemented</para>
122                                         </enum>
123                                         <enum name="i">
124                                                 <para>generate IAX call id for the outbound call. Have not been implemented</para>
125                                         </enum>
126                                 </enumlist>
127                         </parameter>
128                 </syntax>
129                 <description>
130                         <para>Looks up destination via OSP.</para>
131                         <para>Input variables:</para>
132                         <variablelist>
133                                 <variable name="OSPINACTUALSRC">
134                                         <para>The actual source device IP address in indirect mode.</para>
135                                 </variable>
136                                 <variable name="OSPINPEERIP">
137                                         <para>The last hop IP address.</para>
138                                 </variable>
139                                 <variable name="OSPINTECH">
140                                         <para>The inbound channel technology for the call.</para>
141                                 </variable>
142                                 <variable name="OSPINHANDLE">
143                                         <para>The inbound call OSP transaction handle.</para>
144                                 </variable>
145                                 <variable name="OSPINTIMELIMIT">
146                                         <para>The inbound call duration limit in seconds.</para>
147                                 </variable>
148                                 <variable name="OSPINNETWORKID">
149                                         <para>The inbound source network ID.</para>
150                                 </variable>
151                                 <variable name="OSPINNPRN">
152                                         <para>The inbound routing number.</para>
153                                 </variable>
154                                 <variable name="OSPINNPCIC">
155                                         <para>The inbound carrier identification code.</para>
156                                 </variable>
157                                 <variable name="OSPINNPDI">
158                                         <para>The inbound number portability database dip indicator.</para>
159                                 </variable>
160                                 <variable name="OSPINSPID">
161                                         <para>The inbound service provider identity.</para>
162                                 </variable>
163                                 <variable name="OSPINOCN">
164                                         <para>The inbound operator company number.</para>
165                                 </variable>
166                                 <variable name="OSPINSPN">
167                                         <para>The inbound service provider name.</para>
168                                 </variable>
169                                 <variable name="OSPINALTSPN">
170                                         <para>The inbound alternate service provider name.</para>
171                                 </variable>
172                                 <variable name="OSPINMCC">
173                                         <para>The inbound mobile country code.</para>
174                                 </variable>
175                                 <variable name="OSPINMNC">
176                                         <para>The inbound mobile network code.</para>
177                                 </variable>
178                                 <variable name="OSPINTOHOST">
179                                         <para>The inbound To header host part.</para>
180                                 </variable>
181                                 <variable name="OSPINRPIDUSER">
182                                         <para>The inbound Remote-Party-ID header user part.</para>
183                                 </variable>
184                                 <variable name="OSPINPAIUSER">
185                                         <para>The inbound P-Asserted-Identify header user part.</para>
186                                 </variable>
187                                 <variable name="OSPINDIVUSER">
188                                         <para>The inbound Diversion header user part.</para>
189                                 </variable>
190                                 <variable name="OSPINDIVHOST">
191                                         <para>The inbound Diversion header host part.</para>
192                                 </variable>
193                                 <variable name="OSPINPCIUSER">
194                                         <para>The inbound P-Charge-Info header user part.</para>
195                                 </variable>
196                                 <variable name="OSPINCUSTOMINFOn">
197                                         <para>The inbound custom information, where <literal>n</literal> is the index beginning with <literal>1</literal>
198                                         upto <literal>8</literal>.</para>
199                                 </variable>
200                         </variablelist>
201                         <para>Output variables:</para>
202                         <variablelist>
203                                 <variable name="OSPOUTHANDLE">
204                                         <para>The outbound call OSP transaction handle.</para>
205                                 </variable>
206                                 <variable name="OSPOUTTECH">
207                                         <para>The outbound channel technology for the call.</para>
208                                 </variable>
209                                 <variable name="OSPDESTINATION">
210                                         <para>The outbound destination IP address.</para>
211                                 </variable>
212                                 <variable name="OSPOUTCALLING">
213                                         <para>The outbound calling number.</para>
214                                 </variable>
215                                 <variable name="OSPOUTCALLED">
216                                         <para>The outbound called number.</para>
217                                 </variable>
218                                 <variable name="OSPOUTNETWORKID">
219                                         <para>The outbound destination network ID.</para>
220                                 </variable>
221                                 <variable name="OSPOUTNPRN">
222                                         <para>The outbound routing number.</para>
223                                 </variable>
224                                 <variable name="OSPOUTNPCIC">
225                                         <para>The outbound carrier identification code.</para>
226                                 </variable>
227                                 <variable name="OSPOUTNPDI">
228                                         <para>The outbound number portability database dip indicator.</para>
229                                 </variable>
230                                 <variable name="OSPOUTSPID">
231                                         <para>The outbound service provider identity.</para>
232                                 </variable>
233                                 <variable name="OSPOUTOCN">
234                                         <para>The outbound operator company number.</para>
235                                 </variable>
236                                 <variable name="OSPOUTSPN">
237                                         <para>The outbound service provider name.</para>
238                                 </variable>
239                                 <variable name="OSPOUTALTSPN">
240                                         <para>The outbound alternate service provider name.</para>
241                                 </variable>
242                                 <variable name="OSPOUTMCC">
243                                         <para>The outbound mobile country code.</para>
244                                 </variable>
245                                 <variable name="OSPOUTMNC">
246                                         <para>The outbound mobile network code.</para>
247                                 </variable>
248                                 <variable name="OSPOUTTOKEN">
249                                         <para>The outbound OSP token.</para>
250                                 </variable>
251                                 <variable name="OSPDESTREMAILS">
252                                         <para>The number of remained destinations.</para>
253                                 </variable>
254                                 <variable name="OSPOUTTIMELIMIT">
255                                         <para>The outbound call duration limit in seconds.</para>
256                                 </variable>
257                                 <variable name="OSPOUTCALLIDTYPES">
258                                         <para>The outbound Call-ID types.</para>
259                                 </variable>
260                                 <variable name="OSPOUTCALLID">
261                                         <para>The outbound Call-ID. Only for H.323.</para>
262                                 </variable>
263                                 <variable name="OSPDIALSTR">
264                                         <para>The outbound Dial command string.</para>
265                                 </variable>
266                         </variablelist>
267                         <para>This application sets the following channel variable upon completion:</para>
268                         <variablelist>
269                                 <variable name="OSPLOOKUPSTATUS">
270                                         <para>The status of OSPLookup attempt as a text string, one of</para>
271                                         <value name="SUCCESS" />
272                                         <value name="FAILED" />
273                                         <value name="ERROR" />
274                                 </variable>
275                         </variablelist>
276                 </description>
277                 <see-also>
278                         <ref type="application">OSPAuth</ref>
279                         <ref type="application">OSPNext</ref>
280                         <ref type="application">OSPFinish</ref>
281                 </see-also>
282         </application>
283         <application name="OSPNext" language="en_US">
284                 <synopsis>
285                         Lookup next destination by OSP.
286                 </synopsis>
287                 <description>
288                         <para>Looks up the next destination via OSP.</para>
289                         <para>Input variables:</para>
290                         <variablelist>
291                                 <variable name="OSPINHANDLE">
292                                         <para>The inbound call OSP transaction handle.</para>
293                                 </variable>
294                                 <variable name="OSPOUTHANDLE">
295                                         <para>The outbound call OSP transaction handle.</para>
296                                 </variable>
297                                 <variable name="OSPINTIMELIMIT">
298                                         <para>The inbound call duration limit in seconds.</para>
299                                 </variable>
300                                 <variable name="OSPOUTCALLIDTYPES">
301                                         <para>The outbound Call-ID types.</para>
302                                 </variable>
303                                 <variable name="OSPDESTREMAILS">
304                                         <para>The number of remained destinations.</para>
305                                 </variable>
306                         </variablelist>
307                         <para>Output variables:</para>
308                         <variablelist>
309                                 <variable name="OSPOUTTECH">
310                                         <para>The outbound channel technology.</para>
311                                 </variable>
312                                 <variable name="OSPDESTINATION">
313                                         <para>The destination IP address.</para>
314                                 </variable>
315                                 <variable name="OSPOUTCALLING">
316                                         <para>The outbound calling number.</para>
317                                 </variable>
318                                 <variable name="OSPOUTCALLED">
319                                         <para>The outbound called number.</para>
320                                 </variable>
321                                 <variable name="OSPOUTNETWORKID">
322                                         <para>The outbound destination network ID.</para>
323                                 </variable>
324                                 <variable name="OSPOUTNPRN">
325                                         <para>The outbound routing number.</para>
326                                 </variable>
327                                 <variable name="OSPOUTNPCIC">
328                                         <para>The outbound carrier identification code.</para>
329                                 </variable>
330                                 <variable name="OSPOUTNPDI">
331                                         <para>The outbound number portability database dip indicator.</para>
332                                 </variable>
333                                 <variable name="OSPOUTSPID">
334                                         <para>The outbound service provider identity.</para>
335                                 </variable>
336                                 <variable name="OSPOUTOCN">
337                                         <para>The outbound operator company number.</para>
338                                 </variable>
339                                 <variable name="OSPOUTSPN">
340                                         <para>The outbound service provider name.</para>
341                                 </variable>
342                                 <variable name="OSPOUTALTSPN">
343                                         <para>The outbound alternate service provider name.</para>
344                                 </variable>
345                                 <variable name="OSPOUTMCC">
346                                         <para>The outbound mobile country code.</para>
347                                 </variable>
348                                 <variable name="OSPOUTMNC">
349                                         <para>The outbound mobile network code.</para>
350                                 </variable>
351                                 <variable name="OSPOUTTOKEN">
352                                         <para>The outbound OSP token.</para>
353                                 </variable>
354                                 <variable name="OSPDESTREMAILS">
355                                         <para>The number of remained destinations.</para>
356                                 </variable>
357                                 <variable name="OSPOUTTIMELIMIT">
358                                         <para>The outbound call duration limit in seconds.</para>
359                                 </variable>
360                                 <variable name="OSPOUTCALLID">
361                                         <para>The outbound Call-ID. Only for H.323.</para>
362                                 </variable>
363                                 <variable name="OSPDIALSTR">
364                                         <para>The outbound Dial command string.</para>
365                                 </variable>
366                         </variablelist>
367                         <para>This application sets the following channel variable upon completion:</para>
368                         <variablelist>
369                                 <variable name="OSPNEXTSTATUS">
370                                         <para>The status of the OSPNext attempt as a text string, one of</para>
371                                         <value name="SUCCESS" />
372                                         <value name="FAILED" />
373                                         <value name="ERROR" />
374                                 </variable>
375                         </variablelist>
376                 </description>
377                 <see-also>
378                         <ref type="application">OSPAuth</ref>
379                         <ref type="application">OSPLookup</ref>
380                         <ref type="application">OSPFinish</ref>
381                 </see-also>
382         </application>
383         <application name="OSPFinish" language="en_US">
384                 <synopsis>
385                         Report OSP entry.
386                 </synopsis>
387                 <syntax>
388                         <parameter name="cause">
389                                 <para>Hangup cause.</para>
390                         </parameter>
391                         <parameter name="options">
392                                 <para>Reserved.</para>
393                         </parameter>
394                 </syntax>
395                 <description>
396                         <para>Report call state.</para>
397                         <para>Input variables:</para>
398                         <variablelist>
399                                 <variable name="OSPINHANDLE">
400                                         <para>The inbound call OSP transaction handle.</para>
401                                 </variable>
402                                 <variable name="OSPOUTHANDLE">
403                                         <para>The outbound call OSP transaction handle.</para>
404                                 </variable>
405                                 <variable name="OSPAUTHSTATUS">
406                                         <para>The OSPAuth status.</para>
407                                 </variable>
408                                 <variable name="OSPLOOKUPSTATUS">
409                                         <para>The OSPLookup status.</para>
410                                 </variable>
411                                 <variable name="OSPNEXTSTATUS">
412                                         <para>The OSPNext status.</para>
413                                 </variable>
414                                 <variable name="OSPINAUDIOQOS">
415                                         <para>The inbound call leg audio QoS string.</para>
416                                 </variable>
417                                 <variable name="OSPOUTAUDIOQOS">
418                                         <para>The outbound call leg audio QoS string.</para>
419                                 </variable>
420                         </variablelist>
421                         <para>This application sets the following channel variable upon completion:</para>
422                         <variablelist>
423                                 <variable name="OSPFINISHSTATUS">
424                                         <para>The status of the OSPFinish attempt as a text string, one of</para>
425                                         <value name="SUCCESS" />
426                                         <value name="FAILED" />
427                                         <value name="ERROR" />
428                                 </variable>
429                         </variablelist>
430                 </description>
431                 <see-also>
432                         <ref type="application">OSPAuth</ref>
433                         <ref type="application">OSPLookup</ref>
434                         <ref type="application">OSPNext</ref>
435                 </see-also>
436         </application>
437  ***/
438
439 /* OSP Buffer Sizes */
440 #define OSP_SIZE_INTSTR         ((unsigned int)16)                      /* OSP signed/unsigned int string buffer size */
441 #define OSP_SIZE_NORSTR         ((unsigned int)256)                     /* OSP normal string buffer size */
442 #define OSP_SIZE_KEYSTR         ((unsigned int)1024)            /* OSP certificate string buffer size */
443 #define OSP_SIZE_TOKSTR         ((unsigned int)4096)            /* OSP token string buffer size */
444 #define OSP_SIZE_TECHSTR        ((unsigned int)32)                      /* OSP signed/unsigned int string buffer size */
445 #define OSP_SIZE_UUID           ((unsigned int)16)                      /* UUID size */
446 #define OSP_SIZE_UUIDSTR        ((unsigned int)36)                      /* UUID string size */
447 #define OSP_SIZE_QOSSTR         ((unsigned int)1024)            /* QoS string buffer size */
448
449 /* Call ID Type*/
450 #define OSP_CALLID_UNDEF        ((unsigned int)0)                       /* Undefined */
451 #define OSP_CALLID_SIP          ((unsigned int)(1 << 0))        /* SIP */
452 #define OSP_CALLID_H323         ((unsigned int)(1 << 1))        /* H.323 */
453 #define OSP_CALLID_IAX          ((unsigned int)(1 << 2))        /* IAX2 */
454 #define OSP_CALLID_MAXNUM       ((unsigned int)3)                       /* Max number of call ID types */
455
456 /* OSP Supported Destination Protocols */
457 #define OSP_PROT_SIP            ((const char*)"SIP")            /* SIP protocol name */
458 #define OSP_PROT_H323           ((const char*)"H323")           /* H.323 Q.931 protocol name*/
459 #define OSP_PROT_IAX            ((const char*)"IAX")            /* IAX2 protocol name */
460 #define OSP_PROT_SKYPE          ((const char*)"SKYPE")          /* Skype protocol name */
461
462 /* OSP supported Destination Tech */
463 #define OSP_TECH_SIP            ((const char*)"SIP")            /* SIP tech name */
464 #define OSP_TECH_H323           ((const char*)"H323")           /* OH323 tech name */
465 #define OSP_TECH_IAX            ((const char*)"IAX2")           /* IAX2 tech name */
466 #define OSP_TECH_SKYPE          ((const char*)"SKYPE")          /* Skype tech name */
467
468 /* SIP OSP header field name */
469 #define OSP_SIP_HEADER          ((const char*)"P-OSP-Auth-Token")
470
471 /* OSP Authentication Policy */
472 enum osp_authpolicy {
473         OSP_AUTH_NO = 0,        /* Accept any call */
474         OSP_AUTH_YES,           /* Accept call with valid OSP token or without OSP token */
475         OSP_AUTH_EXC            /* Only accept call with valid OSP token */
476 };
477
478 /* OSP Work Mode */
479 enum osp_workmode {
480         OSP_MODE_DIRECT= 0,     /* Direct */
481         OSP_MODE_INDIRECT       /* Indirect */
482 };
483
484 /* OSP Service Type */
485 enum osp_srvtype {
486         OSP_SRV_VOICE = 0,      /* Normal voice service */
487         OSP_SRV_NPQUERY         /* Ported number query service */
488 };
489
490 /* OSP Constants */
491 #define OSP_OK                                  ((int)1)                                        /* OSP function call successful */
492 #define OSP_FAILED                              ((int)0)                                        /* OSP function call failed */
493 #define OSP_ERROR                               ((int)-1)                                       /* OSP function call error */
494 #define OSP_AST_OK                              ((int)0)                                        /* Asterisk function call successful */
495 #define OSP_AST_ERROR                   ((int)-1)                                       /* Asterisk function call error */
496 #define OSP_INVALID_HANDLE              ((int)-1)                                       /* Invalid OSP handle, provider, transaction etc. */
497 #define OSP_CONFIG_FILE                 ((const char*)"osp.conf")       /* OSP configuration file name */
498 #define OSP_GENERAL_CAT                 ((const char*)"general")        /* OSP global configuration context name */
499 #define OSP_DEF_PROVIDER                ((const char*)"default")        /* OSP default provider context name */
500 #define OSP_MAX_CERTS                   ((unsigned int)10)                      /* OSP max number of cacerts */
501 #define OSP_MAX_SPOINTS                 ((unsigned int)10)                      /* OSP max number of service points */
502 #define OSP_DEF_MAXCONNECT              ((unsigned int)20)                      /* OSP default max_connections */
503 #define OSP_MIN_MAXCONNECT              ((unsigned int)1)                       /* OSP min max_connections */
504 #define OSP_MAX_MAXCONNECT              ((unsigned int)1000)            /* OSP max max_connections */
505 #define OSP_DEF_RETRYDELAY              ((unsigned int)0)                       /* OSP default retry delay */
506 #define OSP_MIN_RETRYDELAY              ((unsigned int)0)                       /* OSP min retry delay */
507 #define OSP_MAX_RETRYDELAY              ((unsigned int)10)                      /* OSP max retry delay */
508 #define OSP_DEF_RETRYLIMIT              ((unsigned int)2)                       /* OSP default retry times */
509 #define OSP_MIN_RETRYLIMIT              ((unsigned int)0)                       /* OSP min retry times */
510 #define OSP_MAX_RETRYLIMIT              ((unsigned int)100)                     /* OSP max retry times */
511 #define OSP_DEF_TIMEOUT                 ((unsigned int)500)                     /* OSP default timeout in ms */
512 #define OSP_MIN_TIMEOUT                 ((unsigned int)200)                     /* OSP min timeout in ms */
513 #define OSP_MAX_TIMEOUT                 ((unsigned int)10000)           /* OSP max timeout in ms */
514 #define OSP_DEF_AUTHPOLICY              OSP_AUTH_YES                            /* OSP default auth policy, yes */
515 #define OSP_AUDIT_URL                   ((const char*)"localhost")      /* OSP default Audit URL */
516 #define OSP_LOCAL_VALIDATION    ((int)1)                                        /* Validate OSP token locally */
517 #define OSP_SSL_LIFETIME                ((unsigned int)300)                     /* SSL life time, in seconds */
518 #define OSP_HTTP_PERSISTENCE    ((int)1)                                        /* In seconds */
519 #define OSP_CUSTOMER_ID                 ((const char*)"")                       /* OSP customer ID */
520 #define OSP_DEVICE_ID                   ((const char*)"")                       /* OSP device ID */
521 #define OSP_DEF_MAXDESTS                ((unsigned int)12)                      /* OSP default max number of destinations */
522 #define OSP_DEF_TIMELIMIT               ((unsigned int)0)                       /* OSP default duration limit, no limit */
523 #define OSP_DEF_PROTOCOL                OSP_PROT_SIP                            /* OSP default signaling protocol, SIP */
524 #define OSP_DEF_WORKMODE                OSP_MODE_DIRECT                         /* OSP default work mode, direct */
525 #define OSP_DEF_SRVTYPE                 OSP_SRV_VOICE                           /* OSP default service type, voice */
526 #define OSP_MAX_CUSTOMINFO              ((unsigned int)8)                       /* OSP max number of custom info */
527 #define OSP_DEF_INTSTATS                ((int)-1)                                       /* OSP default int statistic */
528 #define OSP_DEF_FLOATSTATS              ((float)-1)                                     /* OSP default float statistic */
529
530 /* OSP Provider */
531 struct osp_provider {
532         OSPTPROVHANDLE handle;                                                  /* OSP provider handle */
533         char name[OSP_SIZE_NORSTR];                                             /* OSP provider context name */
534         char privatekey[OSP_SIZE_NORSTR];                               /* OSP private key file name */
535         char localcert[OSP_SIZE_NORSTR];                                /* OSP local cert file name */
536         unsigned int canum;                                                             /* Number of cacerts */
537         char cacerts[OSP_MAX_CERTS][OSP_SIZE_NORSTR];   /* Cacert file names */
538         unsigned int spnum;                                                             /* Number of service points */
539         char spoints[OSP_MAX_SPOINTS][OSP_SIZE_NORSTR]; /* Service point URLs */
540         unsigned int maxconnect;                                                /* Max number of connections */
541         unsigned int retrydelay;                                                /* Retry delay */
542         unsigned int retrylimit;                                                /* Retry limit */
543         unsigned int timeout;                                                   /* Timeout in ms */
544         char source[OSP_SIZE_NORSTR];                                   /* IP of self */
545         enum osp_authpolicy authpolicy;                                 /* OSP authentication policy */
546         const char* defprotocol;                                                /* OSP default signaling protocol */
547         enum osp_workmode workmode;                                             /* OSP work mode */
548         enum osp_srvtype srvtype;                                               /* OSP service type */
549         struct osp_provider* next;                                              /* Pointer to next OSP provider */
550 };
551
552 /* Call ID */
553 struct osp_callid {
554         unsigned char buf[OSP_SIZE_NORSTR];             /* Call ID string */
555         unsigned int len;                                               /* Call ID length */
556 };
557
558 /* Number Portability Data */
559 struct osp_npdata {
560         const char* rn;                                                 /* Rounding Number */
561         const char* cic;                                                /* Carrier Identification Code */
562         int npdi;                                                               /* NP Database Dip Indicator */
563         const char* opname[OSPC_OPNAME_NUMBER]; /* Operator Names */
564 };
565
566 /* SIP Header Parameters */
567 struct osp_headers {
568         const char* rpiduser;                                   /* Remote-Party-ID header user info */
569         const char* paiuser;                                    /* P-Asserted-Identity header user info */
570         const char* divuser;                                    /* Diversion header user info */
571         const char* divhost;                                    /* Diversion header host info */
572         const char* pciuser;                                    /* P-Charge-Info header user info */
573 };
574
575 /* OSP Application In/Output Results */
576 struct osp_results {
577         int inhandle;                                                                           /* Inbound transaction handle */
578         int outhandle;                                                                          /* Outbound transaction handle */
579         unsigned int intimelimit;                                                       /* Inbound duration limit */
580         unsigned int outtimelimit;                                                      /* Outbound duration limit */
581         char intech[OSP_SIZE_TECHSTR];                                          /* Inbound Asterisk TECH string */
582         char outtech[OSP_SIZE_TECHSTR];                                         /* Outbound Asterisk TECH string */
583         char dest[OSP_SIZE_NORSTR];                                                     /* Outbound destination IP address */
584         char calling[OSP_SIZE_NORSTR];                                          /* Outbound calling number, may be translated */
585         char called[OSP_SIZE_NORSTR];                                           /* Outbound called number, may be translated */
586         char token[OSP_SIZE_TOKSTR];                                            /* Outbound OSP token */
587         char networkid[OSP_SIZE_NORSTR];                                        /* Outbound network ID */
588         char nprn[OSP_SIZE_NORSTR];                                                     /* Outbound NP routing number */
589         char npcic[OSP_SIZE_NORSTR];                                            /* Outbound NP carrier identification code */
590         int npdi;                                                                                       /* Outbound NP database dip indicator */
591         char opname[OSPC_OPNAME_NUMBER][OSP_SIZE_NORSTR];       /* Outbound Operator names */
592         unsigned int numdests;                                                          /* Number of remain outbound destinations */
593         struct osp_callid outcallid;                                            /* Outbound call ID */
594 };
595
596 /* OSP Call Leg */
597 enum osp_callleg {
598         OSP_CALL_INBOUND,       /* Inbound call leg */
599         OSP_CALL_OUTBOUND       /* Outbound call leg */
600 };
601
602 /* OSP Media Stream Direction */
603 enum osp_direction {
604         OSP_DIR_RX = 0,         /* Receive */
605         OSP_DIR_TX,                     /* Send */
606         OSP_DIR_NUMBER          /* Number of directions */
607 };
608
609 /* OSP Metrics */
610 struct osp_metrics {
611         int value;                      /* Value */
612         float min;                      /* Minimum */
613         float max;                      /* Maximum */
614         float avg;                      /* Average */
615         float sdev;                     /* Standard deviation */
616 };
617
618 /* OSP Module Global Variables */
619 AST_MUTEX_DEFINE_STATIC(osp_lock);                                                      /* Lock of OSP provider list */
620 static int osp_initialized = 0;                                                         /* Init flag */
621 static int osp_hardware = 0;                                                            /* Hardware acceleration flag */
622 static int osp_security = 0;                                                            /* Using security features flag */
623 static struct osp_provider* osp_providers = NULL;                       /* OSP provider list */
624 static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED;        /* Token format supported */
625
626 /* OSP default certificates */
627 const char* B64PKey = "MIIBOgIBAAJBAK8t5l+PUbTC4lvwlNxV5lpl+2dwSZGW46dowTe6y133XyVEwNiiRma2YNk3xKs/TJ3Wl9Wpns2SYEAJsFfSTukCAwEAAQJAPz13vCm2GmZ8Zyp74usTxLCqSJZNyMRLHQWBM0g44Iuy4wE3vpi7Wq+xYuSOH2mu4OddnxswCP4QhaXVQavTAQIhAOBVCKXtppEw9UaOBL4vW0Ed/6EA/1D8hDW6St0h7EXJAiEAx+iRmZKhJD6VT84dtX5ZYNVk3j3dAcIOovpzUj9a0CECIEduTCapmZQ5xqAEsLXuVlxRtQgLTUD4ZxDElPn8x0MhAiBE2HlcND0+qDbvtwJQQOUzDgqg5xk3w8capboVdzAlQQIhAMC+lDL7+gDYkNAft5Mu+NObJmQs4Cr+DkDFsKqoxqrm";
628 const char* B64LCert = "MIIBeTCCASMCEHqkOHVRRWr+1COq3CR/xsowDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTA1MDYyMzAwMjkxOFoXDTA2MDYyNDAwMjkxOFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCvLeZfj1G0wuJb8JTcVeZaZftncEmRluOnaME3ustd918lRMDYokZmtmDZN8SrP0yd1pfVqZ7NkmBACbBX0k7pAgMBAAEwDQYJKoZIhvcNAQEEBQADQQDnV8QNFVVJx/+7IselU0wsepqMurivXZzuxOmTEmTVDzCJx1xhA8jd3vGAj7XDIYiPub1PV23eY5a2ARJuw5w9";
629 const char* B64CACert = "MIIBYDCCAQoCAQEwDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTAyMDIwNDE4MjU1MloXDTEyMDIwMzE4MjU1MlowOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPGeGwV41EIhX0jEDFLRXQhDEr50OUQPq+f55VwQd0TQNts06BP29+UiNdRW3c3IRHdZcJdC1Cg68ME9cgeq0h8CAwEAATANBgkqhkiG9w0BAQQFAANBAGkzBSj1EnnmUxbaiG1N4xjIuLAWydun7o3bFk2tV8dBIhnuh445obYyk1EnQ27kI7eACCILBZqi2MHDOIMnoN0=";
630
631 /* OSP Client Wrapper APIs */
632
633 /*!
634  * \brief Create OSP provider handle according to configuration
635  * \param cfg OSP configuration
636  * \param name OSP provider context name
637  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
638  */
639 static int osp_create_provider(
640         struct ast_config* cfg,
641         const char* name)
642 {
643         int res = OSP_FAILED;
644         struct ast_variable* var;
645         struct osp_provider* provider;
646         OSPTPRIVATEKEY privatekey;
647         OSPT_CERT localcert;
648         OSPT_CERT cacerts[OSP_MAX_CERTS];
649         const OSPT_CERT* pcacerts[OSP_MAX_CERTS];
650         const char* pspoints[OSP_MAX_SPOINTS];
651         unsigned char privatekeydata[OSP_SIZE_KEYSTR];
652         unsigned char localcertdata[OSP_SIZE_KEYSTR];
653         unsigned char cacertdata[OSP_SIZE_KEYSTR];
654         int i, num, error = OSPC_ERR_NO_ERROR;
655
656         if (!(provider = ast_calloc(1, sizeof(*provider)))) {
657                 ast_log(LOG_ERROR, "Out of memory\n");
658                 return OSP_ERROR;
659         }
660
661         /* ast_calloc has set 0 in provider */
662         provider->handle = OSP_INVALID_HANDLE;
663         ast_copy_string(provider->name, name, sizeof(provider->name));
664         snprintf(provider->privatekey, sizeof(provider->privatekey), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, name);
665         snprintf(provider->localcert, sizeof(provider->localcert), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, name);
666         snprintf(provider->cacerts[0], sizeof(provider->cacerts[0]), "%s/%s-cacert_0.pem", ast_config_AST_KEY_DIR, name);
667         provider->maxconnect = OSP_DEF_MAXCONNECT;
668         provider->retrydelay = OSP_DEF_RETRYDELAY;
669         provider->retrylimit = OSP_DEF_RETRYLIMIT;
670         provider->timeout = OSP_DEF_TIMEOUT;
671         provider->authpolicy = OSP_DEF_AUTHPOLICY;
672         provider->defprotocol = OSP_DEF_PROTOCOL;
673         provider->workmode = OSP_DEF_WORKMODE;
674         provider->srvtype = OSP_DEF_SRVTYPE;
675
676         for (var = ast_variable_browse(cfg, name); var != NULL; var = var->next) {
677                 if (!strcasecmp(var->name, "privatekey")) {
678                         if (osp_security) {
679                                 if (var->value[0] == '/') {
680                                         ast_copy_string(provider->privatekey, var->value, sizeof(provider->privatekey));
681                                 } else {
682                                         snprintf(provider->privatekey, sizeof(provider->privatekey), "%s/%s", ast_config_AST_KEY_DIR, var->value);
683                                 }
684                                 ast_debug(1, "OSP: privatekey '%s'\n", provider->privatekey);
685                         }
686                 } else if (!strcasecmp(var->name, "localcert")) {
687                         if (osp_security) {
688                                 if (var->value[0] == '/') {
689                                         ast_copy_string(provider->localcert, var->value, sizeof(provider->localcert));
690                                 } else {
691                                         snprintf(provider->localcert, sizeof(provider->localcert), "%s/%s", ast_config_AST_KEY_DIR, var->value);
692                                 }
693                                 ast_debug(1, "OSP: localcert '%s'\n", provider->localcert);
694                         }
695                 } else if (!strcasecmp(var->name, "cacert")) {
696                         if (osp_security) {
697                                 if (provider->canum < OSP_MAX_CERTS) {
698                                         if (var->value[0] == '/') {
699                                                 ast_copy_string(provider->cacerts[provider->canum], var->value, sizeof(provider->cacerts[provider->canum]));
700                                         } else {
701                                                 snprintf(provider->cacerts[provider->canum], sizeof(provider->cacerts[provider->canum]), "%s/%s", ast_config_AST_KEY_DIR, var->value);
702                                         }
703                                         ast_debug(1, "OSP: cacerts[%d]: '%s'\n", provider->canum, provider->cacerts[provider->canum]);
704                                         provider->canum++;
705                                 } else {
706                                         ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", var->lineno);
707                                 }
708                         }
709                 } else if (!strcasecmp(var->name, "servicepoint")) {
710                         if (provider->spnum < OSP_MAX_SPOINTS) {
711                                 ast_copy_string(provider->spoints[provider->spnum], var->value, sizeof(provider->spoints[provider->spnum]));
712                                 ast_debug(1, "OSP: servicepoint[%d]: '%s'\n", provider->spnum, provider->spoints[provider->spnum]);
713                                 provider->spnum++;
714                         } else {
715                                 ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", var->lineno);
716                         }
717                 } else if (!strcasecmp(var->name, "maxconnect")) {
718                         if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_MAXCONNECT) && (num <= OSP_MAX_MAXCONNECT)) {
719                                 provider->maxconnect = num;
720                                 ast_debug(1, "OSP: maxconnect '%d'\n", num);
721                         } else {
722                                 ast_log(LOG_WARNING, "OSP: maxconnect should be an integer from %d to %d, not '%s' at line %d\n",
723                                         OSP_MIN_MAXCONNECT, OSP_MAX_MAXCONNECT, var->value, var->lineno);
724                         }
725                 } else if (!strcasecmp(var->name, "retrydelay")) {
726                         if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_RETRYDELAY) && (num <= OSP_MAX_RETRYDELAY)) {
727                                 provider->retrydelay = num;
728                                 ast_debug(1, "OSP: retrydelay '%d'\n", num);
729                         } else {
730                                 ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n",
731                                         OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY, var->value, var->lineno);
732                         }
733                 } else if (!strcasecmp(var->name, "retrylimit")) {
734                         if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_RETRYLIMIT) && (num <= OSP_MAX_RETRYLIMIT)) {
735                                 provider->retrylimit = num;
736                                 ast_debug(1, "OSP: retrylimit '%d'\n", num);
737                         } else {
738                                 ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n",
739                                         OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT, var->value, var->lineno);
740                         }
741                 } else if (!strcasecmp(var->name, "timeout")) {
742                         if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_TIMEOUT) && (num <= OSP_MAX_TIMEOUT)) {
743                                 provider->timeout = num;
744                                 ast_debug(1, "OSP: timeout '%d'\n", num);
745                         } else {
746                                 ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n",
747                                         OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT, var->value, var->lineno);
748                         }
749                 } else if (!strcasecmp(var->name, "source")) {
750                         ast_copy_string(provider->source, var->value, sizeof(provider->source));
751                         ast_debug(1, "OSP: source '%s'\n", provider->source);
752                 } else if (!strcasecmp(var->name, "authpolicy")) {
753                         if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_AUTH_NO) || (num == OSP_AUTH_YES) || (num == OSP_AUTH_EXC))) {
754                                 provider->authpolicy = num;
755                                 ast_debug(1, "OSP: authpolicy '%d'\n", num);
756                         } else {
757                                 ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n",
758                                         OSP_AUTH_NO, OSP_AUTH_YES, OSP_AUTH_EXC, var->value, var->lineno);
759                         }
760                 } else if (!strcasecmp(var->name, "defprotocol")) {
761                         if (!strcasecmp(var->value, OSP_PROT_SIP)) {
762                                 provider->defprotocol = OSP_PROT_SIP;
763                                 ast_debug(1, "OSP: default protocol SIP\n");
764                         } else if (!strcasecmp(var->value, OSP_PROT_H323)) {
765                                 provider->defprotocol = OSP_PROT_H323;
766                                 ast_debug(1, "OSP: default protocol H.323\n");
767                         } else if (!strcasecmp(var->value, OSP_PROT_IAX)) {
768                                 provider->defprotocol = OSP_PROT_IAX;
769                                 ast_debug(1, "OSP: default protocol IAX\n");
770                         } else if (!strcasecmp(var->value, OSP_PROT_SKYPE)) {
771                                 provider->defprotocol = OSP_PROT_SKYPE;
772                                 ast_debug(1, "OSP: default protocol Skype\n");
773                         } else {
774                                 ast_log(LOG_WARNING, "OSP: default protocol should be %s, %s, %s or %s not '%s' at line %d\n",
775                                         OSP_PROT_SIP, OSP_PROT_H323, OSP_PROT_IAX, OSP_PROT_SKYPE, var->value, var->lineno);
776                         }
777                 } else if (!strcasecmp(var->name, "workmode")) {
778                         if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_MODE_DIRECT) || (num == OSP_MODE_INDIRECT))) {
779                                 provider->workmode = num;
780                                 ast_debug(1, "OSP: workmode '%d'\n", num);
781                         } else {
782                                 ast_log(LOG_WARNING, "OSP: workmode should be %d or %d, not '%s' at line %d\n",
783                                         OSP_MODE_DIRECT, OSP_MODE_INDIRECT, var->value, var->lineno);
784                         }
785                 } else if (!strcasecmp(var->name, "servicetype")) {
786                         if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_SRV_VOICE) || (num == OSP_SRV_NPQUERY))) {
787                                 provider->srvtype = num;
788                                 ast_debug(1, "OSP: servicetype '%d'\n", num);
789                         } else {
790                                 ast_log(LOG_WARNING, "OSP: servicetype should be %d or %d, not '%s' at line %d\n",
791                                         OSP_SRV_VOICE, OSP_SRV_NPQUERY, var->value, var->lineno);
792                         }
793                 }
794         }
795
796         if (provider->canum == 0) {
797                 provider->canum = 1;
798         }
799
800         for (i = 0; i < provider->spnum; i++) {
801                 pspoints[i] = provider->spoints[i];
802         }
803
804         if (osp_security) {
805                 privatekey.PrivateKeyData = NULL;
806                 privatekey.PrivateKeyLength = 0;
807
808                 localcert.CertData = NULL;
809                 localcert.CertDataLength = 0;
810
811                 for (i = 0; i < provider->canum; i++) {
812                         cacerts[i].CertData = NULL;
813                         cacerts[i].CertDataLength = 0;
814                 }
815
816                 if ((error = OSPPUtilLoadPEMPrivateKey((unsigned char*)provider->privatekey, &privatekey)) != OSPC_ERR_NO_ERROR) {
817                         ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", provider->privatekey, error);
818                 } else if ((error = OSPPUtilLoadPEMCert((unsigned char*)provider->localcert, &localcert)) != OSPC_ERR_NO_ERROR) {
819                         ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", provider->localcert, error);
820                 } else {
821                         for (i = 0; i < provider->canum; i++) {
822                                 if ((error = OSPPUtilLoadPEMCert((unsigned char*)provider->cacerts[i], &cacerts[i])) != OSPC_ERR_NO_ERROR) {
823                                         ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", provider->cacerts[i], error);
824                                         break;
825                                 } else {
826                                         pcacerts[i] = &cacerts[i];
827                                 }
828                         }
829                 }
830         } else {
831                 privatekey.PrivateKeyData = privatekeydata;
832                 privatekey.PrivateKeyLength = sizeof(privatekeydata);
833
834                 localcert.CertData = localcertdata;
835                 localcert.CertDataLength = sizeof(localcertdata);
836
837                 cacerts[0].CertData = cacertdata;
838                 cacerts[0].CertDataLength = sizeof(cacertdata);
839                 pcacerts[0] = &cacerts[0];
840
841                 if ((error = OSPPBase64Decode(B64PKey, strlen(B64PKey), privatekey.PrivateKeyData, &privatekey.PrivateKeyLength)) != OSPC_ERR_NO_ERROR) {
842                         ast_log(LOG_WARNING, "OSP: Unable to decode private key, error '%d'\n", error);
843                 } else if ((error = OSPPBase64Decode(B64LCert, strlen(B64LCert), localcert.CertData, &localcert.CertDataLength)) != OSPC_ERR_NO_ERROR) {
844                         ast_log(LOG_WARNING, "OSP: Unable to decode local cert, error '%d'\n", error);
845                 } else if ((error = OSPPBase64Decode(B64CACert, strlen(B64CACert), cacerts[0].CertData, &cacerts[0].CertDataLength)) != OSPC_ERR_NO_ERROR) {
846                         ast_log(LOG_WARNING, "OSP: Unable to decode cacert, error '%d'\n", error);
847                 }
848         }
849
850         if (error == OSPC_ERR_NO_ERROR) {
851                 error = OSPPProviderNew(provider->spnum,
852                         pspoints,
853                         NULL,
854                         OSP_AUDIT_URL,
855                         &privatekey,
856                         &localcert,
857                         provider->canum,
858                         pcacerts,
859                         OSP_LOCAL_VALIDATION,
860                         OSP_SSL_LIFETIME,
861                         provider->maxconnect,
862                         OSP_HTTP_PERSISTENCE,
863                         provider->retrydelay,
864                         provider->retrylimit,
865                         provider->timeout,
866                         OSP_CUSTOMER_ID,
867                         OSP_DEVICE_ID,
868                         &provider->handle);
869                 if (error != OSPC_ERR_NO_ERROR) {
870                         ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", name, error);
871                         res = OSP_ERROR;
872                 } else {
873                         ast_debug(1, "OSP: provider '%s'\n", name);
874                         ast_mutex_lock(&osp_lock);
875                         provider->next = osp_providers;
876                         osp_providers = provider;
877                         ast_mutex_unlock(&osp_lock);
878                         res = OSP_OK;
879                 }
880         }
881
882         if (osp_security) {
883                 for (i = 0; i < provider->canum; i++) {
884                         if (cacerts[i].CertData) {
885                                 ast_free(cacerts[i].CertData);
886                         }
887                 }
888                 if (localcert.CertData) {
889                         ast_free(localcert.CertData);
890                 }
891                 if (privatekey.PrivateKeyData) {
892                         ast_free(privatekey.PrivateKeyData);
893                 }
894         }
895
896         if (res != OSP_OK) {
897                 ast_free(provider);
898         }
899
900         return res;
901 }
902
903 /*!
904  * \brief Get OSP provider by name
905  * \param name OSP provider context name
906  * \param provider OSP provider structure
907  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
908  */
909 static int osp_get_provider(
910         const char* name,
911         struct osp_provider** provider)
912 {
913         int res = OSP_FAILED;
914         struct osp_provider* p;
915
916         *provider = NULL;
917
918         ast_mutex_lock(&osp_lock);
919         for (p = osp_providers; p != NULL; p = p->next) {
920                 if (!strcasecmp(p->name, name)) {
921                         *provider = p;
922                         ast_debug(1, "OSP: find provider '%s'\n", name);
923                         res = OSP_OK;
924                         break;
925                 }
926         }
927         ast_mutex_unlock(&osp_lock);
928
929         return res;
930 }
931
932 /*!
933  * \brief Create OSP transaction handle
934  * \param name OSP provider context name
935  * \param trans OSP transaction handle, output
936  * \param source Source of provider, output
937  * \param srcsize Size of source buffer, in
938  * \return OSK_OK Success, OSK_FAILED Failed, OSP_ERROR Error
939  */
940 static int osp_create_transaction(
941         const char* name,
942         int* trans,
943         char* source,
944         unsigned int srcsize)
945 {
946         int res = OSP_FAILED;
947         struct osp_provider* provider;
948         int error;
949
950         if ((trans == NULL) || (source == NULL) || (srcsize <= 0)) {
951                 ast_log(LOG_ERROR, "Invalid parameters\n");
952                 return OSP_ERROR;
953         }
954
955         *trans = OSP_INVALID_HANDLE;
956         *source = '\0';
957
958         ast_mutex_lock(&osp_lock);
959         for (provider = osp_providers; provider; provider = provider->next) {
960                 if (!strcasecmp(provider->name, name)) {
961                         error = OSPPTransactionNew(provider->handle, trans);
962                         if (error == OSPC_ERR_NO_ERROR) {
963                                 ast_debug(1, "OSP: transaction '%d'\n", *trans);
964                                 ast_copy_string(source, provider->source, srcsize);
965                                 ast_debug(1, "OSP: source '%s'\n", source);
966                                 res = OSP_OK;
967                         } else {
968                                 *trans = OSP_INVALID_HANDLE;
969                                 ast_debug(1, "OSP: Unable to create transaction handle, error '%d'\n", error);
970                                 *source = '\0';
971                                 res = OSP_ERROR;
972                         }
973                         break;
974                 }
975         }
976         ast_mutex_unlock(&osp_lock);
977
978         return res;
979 }
980
981 /*!
982  * \brief Convert "address:port" to "[x.x.x.x]:port" or "hostname:port" format
983  * \param src Source address string
984  * \param dest Destination address string
985  * \param destsize Size of dest buffer
986  */
987 static void osp_convert_inout(
988         const char* src,
989         char* dest,
990         unsigned int destsize)
991 {
992         struct in_addr inp;
993         char buffer[OSP_SIZE_NORSTR];
994         char* port;
995
996         if ((dest != NULL) && (destsize > 0)) {
997                 if (!ast_strlen_zero(src)) {
998                         ast_copy_string(buffer, src, sizeof(buffer));
999
1000                         if((port = strchr(buffer, ':')) != NULL) {
1001                                 *port = '\0';
1002                                 port++;
1003                         }
1004
1005                         if (inet_pton(AF_INET, buffer, &inp) == 1) {
1006                                 if (port != NULL) {
1007                                         snprintf(dest, destsize, "[%s]:%s", buffer, port);
1008                                 } else {
1009                                         snprintf(dest, destsize, "[%s]", buffer);
1010                                 }
1011                                 dest[destsize - 1] = '\0';
1012                         } else {
1013                                 ast_copy_string(dest, src, destsize);
1014                         }
1015                 } else {
1016                         *dest = '\0';
1017                 }
1018         }
1019 }
1020
1021 /*!
1022  * \brief Convert "[x.x.x.x]:port" or "hostname:prot" to "address:port" format
1023  * \param src Source address string
1024  * \param dest Destination address string
1025  * \param destsize Size of dest buffer
1026  */
1027 static void osp_convert_outin(
1028         const char* src,
1029         char* dest,
1030         unsigned int destsize)
1031 {
1032         char buffer[OSP_SIZE_NORSTR];
1033         char* end;
1034         char* port;
1035
1036         if ((dest != NULL) && (destsize > 0)) {
1037                 if (!ast_strlen_zero(src)) {
1038                         ast_copy_string(buffer, src, sizeof(buffer));
1039
1040                         if (buffer[0] == '[') {
1041                                 if((port = strchr(buffer + 1, ':')) != NULL) {
1042                                         *port = '\0';
1043                                         port++;
1044                                 }
1045
1046                                 if ((end = strchr(buffer + 1, ']')) != NULL) {
1047                                         *end = '\0';
1048                                 }
1049
1050                                 if (port != NULL) {
1051                                         snprintf(dest, destsize, "%s:%s", buffer + 1, port);
1052                                         dest[destsize - 1] = '\0';
1053                                 } else {
1054                                         ast_copy_string(dest, buffer + 1, destsize);
1055                                 }
1056                         } else {
1057                                 ast_copy_string(dest, src, destsize);
1058                         }
1059                 } else {
1060                         *dest = '\0';
1061                 }
1062         }
1063 }
1064
1065 /*!
1066  * \brief Validate OSP token of inbound call
1067  * \param trans OSP transaction handle
1068  * \param source Source of inbound call
1069  * \param destination Destination of inbound call
1070  * \param calling Calling number
1071  * \param called Called number
1072  * \param token OSP token, may be empty
1073  * \param timelimit Call duration limit, output
1074  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
1075  */
1076 static int osp_validate_token(
1077         int trans,
1078         const char* source,
1079         const char* destination,
1080         const char* calling,
1081         const char* called,
1082         const char* token,
1083         unsigned int* timelimit)
1084 {
1085         int res;
1086         int tokenlen;
1087         unsigned char tokenstr[OSP_SIZE_TOKSTR];
1088         char src[OSP_SIZE_NORSTR];
1089         char dest[OSP_SIZE_NORSTR];
1090         unsigned int authorised;
1091         unsigned int dummy = 0;
1092         int error;
1093
1094         if (timelimit == NULL) {
1095                 ast_log(LOG_ERROR, "Invalid parameters\n");
1096                 return OSP_ERROR;
1097         }
1098
1099         tokenlen = ast_base64decode(tokenstr, token, strlen(token));
1100         osp_convert_inout(source, src, sizeof(src));
1101         osp_convert_inout(destination, dest, sizeof(dest));
1102         error = OSPPTransactionValidateAuthorisation(trans,
1103                 src,
1104                 dest,
1105                 NULL,
1106                 NULL,
1107                 calling ? calling : "",
1108                 OSPC_NFORMAT_E164,
1109                 called,
1110                 OSPC_NFORMAT_E164,
1111                 0,
1112                 NULL,
1113                 tokenlen,
1114                 (char*)tokenstr,
1115                 &authorised,
1116                 timelimit,
1117                 &dummy,
1118                 NULL,
1119                 osp_tokenformat);
1120         if (error != OSPC_ERR_NO_ERROR) {
1121                 ast_log(LOG_WARNING, "OSP: Unable to validate inbound token, error '%d'\n", error);
1122                 *timelimit = 0;
1123                 res = OSP_ERROR;
1124         } else if (authorised) {
1125                 ast_debug(1, "OSP: Authorised\n");
1126                 res = OSP_OK;
1127         } else {
1128                 ast_debug(1, "OSP: Unauthorised\n");
1129                 res = OSP_FAILED;
1130         }
1131
1132         return res;
1133 }
1134
1135 /*!
1136  * \brief Choose min duration limit
1137  * \param in Inbound duration limit
1138  * \param out Outbound duration limit
1139  * \return min duration limit
1140  */
1141 static unsigned int osp_choose_timelimit(
1142         unsigned int in,
1143         unsigned int out)
1144 {
1145         if (in == OSP_DEF_TIMELIMIT) {
1146                 return out;
1147         } else if (out == OSP_DEF_TIMELIMIT) {
1148                 return in;
1149         } else {
1150                 return in < out ? in : out;
1151         }
1152 }
1153
1154 /*!
1155  * \brief Choose min duration limit
1156  * \param provider OSP provider
1157  * \param calling Calling number
1158  * \param called Called number
1159  * \param destination Destination IP in '[x.x.x.x]' format
1160  * \param tokenlen OSP token length
1161  * \param token OSP token
1162  * \param reason Failure reason, output
1163  * \param results OSP lookup results, in/output
1164  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
1165  */
1166 static int osp_check_destination(
1167         struct osp_provider* provider,
1168         const char* calling,
1169         const char* called,
1170         const char* destination,
1171         unsigned int tokenlen,
1172         const char* token,
1173         OSPEFAILREASON* reason,
1174         struct osp_results* results)
1175 {
1176         int res;
1177         OSPE_DEST_OSPENABLED enabled;
1178         OSPE_PROTOCOL_NAME protocol;
1179         char dest[OSP_SIZE_NORSTR];
1180         OSPE_OPERATOR_NAME type;
1181         int error;
1182
1183         if ((provider == NULL) || (reason == NULL) || (results == NULL)) {
1184                 ast_log(LOG_ERROR, "Invalid parameters\n");
1185                 return OSP_ERROR;
1186         }
1187
1188         if ((error = OSPPTransactionIsDestOSPEnabled(results->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) {
1189                 ast_debug(1, "OSP: Unable to get destination OSP version, error '%d'\n", error);
1190                 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
1191                 return OSP_ERROR;
1192         }
1193
1194         if (enabled == OSPC_DOSP_FALSE) {
1195                 results->token[0] = '\0';
1196         } else {
1197                 ast_base64encode(results->token, (const unsigned char*)token, tokenlen, sizeof(results->token) - 1);
1198         }
1199
1200         if ((error = OSPPTransactionGetDestinationNetworkId(results->outhandle, sizeof(results->networkid), results->networkid)) != OSPC_ERR_NO_ERROR) {
1201                 ast_debug(1, "OSP: Unable to get destination network ID, error '%d'\n", error);
1202                 results->networkid[0] = '\0';
1203         }
1204
1205         error = OSPPTransactionGetNumberPortabilityParameters(results->outhandle,
1206                 sizeof(results->nprn),
1207                 results->nprn,
1208                 sizeof(results->npcic),
1209                 results->npcic,
1210                 &results->npdi);
1211         if (error != OSPC_ERR_NO_ERROR) {
1212                 ast_debug(1, "OSP: Unable to get number portability parameters, error '%d'\n", error);
1213                 results->nprn[0] = '\0';
1214                 results->npcic[0] = '\0';
1215                 results->npdi = 0;
1216         }
1217
1218         for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1219                 error = OSPPTransactionGetOperatorName(results->outhandle, type, sizeof(results->opname[type]), results->opname[type]);
1220                 if (error != OSPC_ERR_NO_ERROR) {
1221                         ast_debug(1, "OSP: Unable to get operator name of type '%d', error '%d'\n", type, error);
1222                         results->opname[type][0] = '\0';
1223                 }
1224         }
1225
1226         if ((error = OSPPTransactionGetDestProtocol(results->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
1227                 ast_debug(1, "OSP: Unable to get destination protocol, error '%d'\n", error);
1228                 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
1229                 results->token[0] = '\0';
1230                 results->networkid[0] = '\0';
1231                 results->nprn[0] = '\0';
1232                 results->npcic[0] = '\0';
1233                 results->npdi = 0;
1234                 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1235                         results->opname[type][0] = '\0';
1236                 }
1237                 return OSP_ERROR;
1238         }
1239
1240         res = OSP_OK;
1241         osp_convert_outin(destination, dest, sizeof(dest));
1242         switch(protocol) {
1243         case OSPC_PROTNAME_SIP:
1244                 ast_debug(1, "OSP: protocol SIP\n");
1245                 ast_copy_string(results->outtech, OSP_TECH_SIP, sizeof(results->outtech));
1246                 ast_copy_string(results->dest, dest, sizeof(results->dest));
1247                 ast_copy_string(results->calling, calling, sizeof(results->calling));
1248                 ast_copy_string(results->called, called, sizeof(results->called));
1249                 break;
1250         case OSPC_PROTNAME_Q931:
1251                 ast_debug(1, "OSP: protocol Q.931\n");
1252                 ast_copy_string(results->outtech, OSP_TECH_H323, sizeof(results->outtech));
1253                 ast_copy_string(results->dest, dest, sizeof(results->dest));
1254                 ast_copy_string(results->calling, calling, sizeof(results->calling));
1255                 ast_copy_string(results->called, called, sizeof(results->called));
1256                 break;
1257         case OSPC_PROTNAME_IAX:
1258                 ast_debug(1, "OSP: protocol IAX\n");
1259                 ast_copy_string(results->outtech, OSP_TECH_IAX, sizeof(results->outtech));
1260                 ast_copy_string(results->dest, dest, sizeof(results->dest));
1261                 ast_copy_string(results->calling, calling, sizeof(results->calling));
1262                 ast_copy_string(results->called, called, sizeof(results->called));
1263                 break;
1264         case OSPC_PROTNAME_SKYPE:
1265                 ast_debug(1, "OSP: protocol Skype\n");
1266                 ast_copy_string(results->outtech, OSP_TECH_SKYPE, sizeof(results->outtech));
1267                 ast_copy_string(results->dest, dest, sizeof(results->dest));
1268                 ast_copy_string(results->calling, calling, sizeof(results->calling));
1269                 ast_copy_string(results->called, called, sizeof(results->called));
1270                 break;
1271         case OSPC_PROTNAME_UNDEFINED:
1272         case OSPC_PROTNAME_UNKNOWN:
1273                 ast_debug(1, "OSP: unknown/undefined protocol '%d'\n", protocol);
1274                 ast_debug(1, "OSP: use default protocol '%s'\n", provider->defprotocol);
1275                 ast_copy_string(results->outtech, provider->defprotocol, sizeof(results->outtech));
1276                 ast_copy_string(results->dest, dest, sizeof(results->dest));
1277                 ast_copy_string(results->calling, calling, sizeof(results->calling));
1278                 ast_copy_string(results->called, called, sizeof(results->called));
1279                 break;
1280         case OSPC_PROTNAME_LRQ:
1281         case OSPC_PROTNAME_T37:
1282         case OSPC_PROTNAME_T38:
1283         case OSPC_PROTNAME_SMPP:
1284         case OSPC_PROTNAME_XMPP:
1285         default:
1286                 ast_log(LOG_WARNING, "OSP: unsupported protocol '%d'\n", protocol);
1287                 *reason = OSPC_FAIL_PROTOCOL_ERROR;
1288                 results->token[0] = '\0';
1289                 results->networkid[0] = '\0';
1290                 results->nprn[0] = '\0';
1291                 results->npcic[0] = '\0';
1292                 results->npdi = 0;
1293                 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1294                         results->opname[type][0] = '\0';
1295                 }
1296                 res = OSP_FAILED;
1297                 break;
1298         }
1299
1300         return res;
1301 }
1302
1303 /*!
1304  * \brief Convert Asterisk status to TC code
1305  * \param cause Asterisk hangup cause
1306  * \return OSP TC code
1307  */
1308 static OSPEFAILREASON asterisk2osp(
1309         int cause)
1310 {
1311         return (OSPEFAILREASON)cause;
1312 }
1313
1314 /*!
1315  * \brief OSP Authentication function
1316  * \param name OSP provider context name
1317  * \param trans OSP transaction handle, output
1318  * \param source Source of inbound call
1319  * \param calling Calling number
1320  * \param called Called number
1321  * \param token OSP token, may be empty
1322  * \param timelimit Call duration limit, output
1323  * \return OSP_OK Authenricated, OSP_FAILED Unauthenticated, OSP_ERROR Error
1324  */
1325 static int osp_auth(
1326         const char* name,
1327         int* trans,
1328         const char* source,
1329         const char* calling,
1330         const char* called,
1331         const char* token,
1332         unsigned int* timelimit)
1333 {
1334         int res;
1335         struct osp_provider* provider = NULL;
1336         char dest[OSP_SIZE_NORSTR];
1337
1338         if ((trans == NULL) || (timelimit == NULL)) {
1339                 ast_log(LOG_ERROR, "Invalid parameters\n");
1340                 return OSP_ERROR;
1341         }
1342
1343         *trans = OSP_INVALID_HANDLE;
1344         *timelimit = OSP_DEF_TIMELIMIT;
1345
1346         if ((res = osp_get_provider(name, &provider)) <= 0) {
1347                 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1348                 return res;
1349         }
1350
1351         switch (provider->authpolicy) {
1352         case OSP_AUTH_NO:
1353                 res = OSP_OK;
1354                 break;
1355         case OSP_AUTH_EXC:
1356                 if (ast_strlen_zero(token)) {
1357                         res = OSP_FAILED;
1358                 } else if ((res = osp_create_transaction(name, trans, dest, sizeof(dest))) <= 0) {
1359                         ast_debug(1, "OSP: Unable to generate transaction handle\n");
1360                         *trans = OSP_INVALID_HANDLE;
1361                         res = OSP_FAILED;
1362                 } else if((res = osp_validate_token(*trans, source, dest, calling, called, token, timelimit)) <= 0) {
1363                         OSPPTransactionRecordFailure(*trans, OSPC_FAIL_CALL_REJECTED);
1364                 }
1365                 break;
1366         case OSP_AUTH_YES:
1367         default:
1368                 if (ast_strlen_zero(token)) {
1369                         res = OSP_OK;
1370                 } else if ((res = osp_create_transaction(name, trans, dest, sizeof(dest))) <= 0) {
1371                         ast_debug(1, "OSP: Unable to generate transaction handle\n");
1372                         *trans = OSP_INVALID_HANDLE;
1373                         res = OSP_FAILED;
1374                 } else if((res = osp_validate_token(*trans, source, dest, calling, called, token, timelimit)) <= 0) {
1375                         OSPPTransactionRecordFailure(*trans, OSPC_FAIL_CALL_REJECTED);
1376                 }
1377                 break;
1378         }
1379
1380         return res;
1381 }
1382
1383 /*!
1384  * \brief Create a UUID
1385  * \param uuid UUID buffer
1386  * \param bufsize UUID buffer size
1387  * \return OSK_OK Created, OSP_ERROR Error
1388  */
1389 static int osp_create_uuid(
1390         unsigned char* uuid,
1391         unsigned int* bufsize)
1392 {
1393         int i, res;
1394         long int tmp[OSP_SIZE_UUID / sizeof(long int)];
1395
1396         if ((uuid != NULL) && (*bufsize >= OSP_SIZE_UUID)) {
1397                 for (i = 0; i < OSP_SIZE_UUID / sizeof(long int); i++) {
1398                         tmp[i] = ast_random();
1399                 }
1400                 memcpy(uuid, tmp, OSP_SIZE_UUID);
1401                 *bufsize = OSP_SIZE_UUID;
1402                 res = OSP_OK;
1403         } else {
1404                 ast_log(LOG_ERROR, "Invalid parameters\n");
1405                 res = OSP_ERROR;
1406         }
1407
1408         return res;
1409 }
1410
1411 /*!
1412  * \brief UUID to string
1413  * \param uuid UUID
1414  * \param buffer String buffer
1415  * \param bufsize String buffer size
1416  * \return OSP_OK Successed, OSP_ERROR Error
1417  */
1418 static int osp_uuid2str(
1419         unsigned char* uuid,
1420         char* buffer,
1421         unsigned int bufsize)
1422 {
1423         int res;
1424
1425         if ((uuid != NULL) && (bufsize > OSP_SIZE_UUIDSTR)) {
1426                 snprintf(buffer, bufsize, "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-"
1427                                           "%02hhx%02hhx-%02hhx%02hhx-"
1428                                           "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
1429                         uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
1430                         uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
1431                 res = OSP_OK;
1432         } else {
1433                 ast_log(LOG_ERROR, "Invalid parameters\n");
1434                 res = OSP_ERROR;
1435         }
1436
1437         return res;
1438 }
1439
1440 /*!
1441  * \brief Create a call ID according to the type
1442  * \param type Call ID type
1443  * \param callid Call ID buffer
1444  * \return OSK_OK Created, OSP_FAILED Not create, OSP_ERROR Error
1445  */
1446 static int osp_create_callid(
1447         unsigned int type,
1448         struct osp_callid* callid)
1449 {
1450         int res;
1451
1452         if (callid == NULL) {
1453                 ast_log(LOG_ERROR, "Invalid parameters\n");
1454                 return OSP_ERROR;
1455         }
1456
1457         callid->len = sizeof(callid->buf);
1458         switch (type) {
1459         case OSP_CALLID_H323:
1460                 res = osp_create_uuid(callid->buf, &callid->len);
1461                 break;
1462         case OSP_CALLID_SIP:
1463         case OSP_CALLID_IAX:
1464                 res = OSP_FAILED;
1465                 break;
1466         default:
1467                 res = OSP_ERROR;
1468                 break;
1469         }
1470
1471         if ((res != OSP_OK) && (callid->len != 0)) {
1472                 callid->buf[0] = '\0';
1473                 callid->len = 0;
1474         }
1475
1476         return res;
1477 }
1478
1479 /*!
1480  * \brief OSP Lookup function
1481  * \param name OSP provider context name
1482  * \param callidtypes Call ID types
1483  * \param actualsrc Actual source device in indirect mode
1484  * \param srcdev Source device of outbound call
1485  * \param calling Calling number
1486  * \param called Called number
1487  * \param snetid Source network ID
1488  * \param np NP parameters
1489  * \param headers SIP header parameters
1490  * \param cinfo Custom info
1491  * \param results Lookup results
1492  * \return OSP_OK Found , OSP_FAILED No route, OSP_ERROR Error
1493  */
1494 static int osp_lookup(
1495         const char* name,
1496         unsigned int callidtypes,
1497         const char* actualsrc,
1498         const char* srcdev,
1499         const char* calling,
1500         const char* called,
1501         const char* snetid,
1502         struct osp_npdata* np,
1503         struct osp_headers* headers,
1504         const char* cinfo[],
1505         struct osp_results* results)
1506 {
1507         int res;
1508         struct osp_provider* provider = NULL;
1509         OSPE_PROTOCOL_NAME protocol;
1510         char source[OSP_SIZE_NORSTR];
1511         char callingnum[OSP_SIZE_NORSTR];
1512         char callednum[OSP_SIZE_NORSTR];
1513         char destination[OSP_SIZE_NORSTR];
1514         char* tmp;
1515         unsigned int tokenlen;
1516         char token[OSP_SIZE_TOKSTR];
1517         char src[OSP_SIZE_NORSTR];
1518         char dev[OSP_SIZE_NORSTR];
1519         char host[OSP_SIZE_NORSTR];
1520         unsigned int i, type;
1521         struct osp_callid callid;
1522         unsigned int callidnum;
1523         OSPT_CALL_ID* callids[OSP_CALLID_MAXNUM];
1524         char dest[OSP_SIZE_NORSTR];
1525         const char* preferred[2] = { NULL };
1526         unsigned int dummy = 0;
1527         OSPEFAILREASON reason;
1528         int error;
1529
1530         if (results == NULL) {
1531                 ast_log(LOG_ERROR, "Invalid parameters\n");
1532                 return OSP_ERROR;
1533         }
1534
1535         osp_convert_inout(results->dest, dest, sizeof(dest));
1536
1537         results->outhandle = OSP_INVALID_HANDLE;
1538         results->outtech[0] = '\0';
1539         results->calling[0] = '\0';
1540         results->called[0] = '\0';
1541         results->token[0] = '\0';
1542         results->networkid[0] = '\0';
1543         results->nprn[0] = '\0';
1544         results->npcic[0] = '\0';
1545         results->npdi = 0;
1546         for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1547                 results->opname[type][0] = '\0';
1548         }
1549         results->numdests = 0;
1550         results->outtimelimit = OSP_DEF_TIMELIMIT;
1551
1552         if ((res = osp_get_provider(name, &provider)) <= 0) {
1553                 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1554                 return res;
1555         }
1556
1557         if ((res = osp_create_transaction(name, &results->outhandle, source, sizeof(source))) <= 0) {
1558                 ast_debug(1, "OSP: Unable to generate transaction handle\n");
1559                 results->outhandle = OSP_INVALID_HANDLE;
1560                 if (results->inhandle != OSP_INVALID_HANDLE) {
1561                         OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1562                 }
1563                 return OSP_ERROR;
1564         }
1565
1566         if (!strcasecmp(results->intech, OSP_TECH_SIP)) {
1567                 protocol = OSPC_PROTNAME_SIP;
1568         } else if (!strcasecmp(results->intech, OSP_TECH_H323)) {
1569                 protocol = OSPC_PROTNAME_Q931;
1570         } else if (!strcasecmp(results->intech, OSP_TECH_IAX)) {
1571                 protocol = OSPC_PROTNAME_IAX;
1572         } else if (!strcasecmp(results->intech, OSP_TECH_SKYPE)) {
1573                 protocol = OSPC_PROTNAME_SKYPE;
1574         } else {
1575                 protocol = OSPC_PROTNAME_SIP;
1576         }
1577         OSPPTransactionSetProtocol(results->outhandle, OSPC_PROTTYPE_SOURCE, protocol);
1578
1579         if (!ast_strlen_zero(snetid)) {
1580                 OSPPTransactionSetNetworkIds(results->outhandle, snetid, "");
1581         }
1582
1583         OSPPTransactionSetNumberPortability(results->outhandle, np->rn, np->cic, np->npdi);
1584
1585         for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1586                 OSPPTransactionSetOperatorName(results->outhandle, type, np->opname[type]);
1587         }
1588
1589     OSPPTransactionSetRemotePartyId(results->outhandle, OSPC_NFORMAT_E164, headers->rpiduser);
1590     OSPPTransactionSetAssertedId(results->outhandle, OSPC_NFORMAT_E164, headers->paiuser);
1591         osp_convert_inout(headers->divhost, host, sizeof(host));
1592         OSPPTransactionSetDiversion(results->outhandle, headers->divuser, host);
1593     OSPPTransactionSetChargeInfo(results->outhandle, OSPC_NFORMAT_E164, headers->pciuser);
1594
1595         if (cinfo != NULL) {
1596                 for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
1597                         if (!ast_strlen_zero(cinfo[i])) {
1598                                 OSPPTransactionSetCustomInfo(results->outhandle, i, cinfo[i]);
1599                         }
1600                 }
1601         }
1602
1603         ast_copy_string(callednum, called, sizeof(callednum));
1604         if((tmp = strchr(callednum, ';')) != NULL) {
1605                 *tmp = '\0';
1606         }
1607
1608         callidnum = 0;
1609         callids[0] = NULL;
1610         for (i = 0; i < OSP_CALLID_MAXNUM; i++) {
1611                 type = 1 << i;
1612                 if (callidtypes & type) {
1613                         error = osp_create_callid(type, &callid);
1614                         if (error == 1) {
1615                                 callids[callidnum] = OSPPCallIdNew(callid.len, callid.buf);
1616                                 callidnum++;
1617                         }
1618                 }
1619         }
1620
1621         if (provider->workmode == OSP_MODE_INDIRECT) {
1622                 osp_convert_inout(srcdev, src, sizeof(src));
1623                 if (ast_strlen_zero(actualsrc)) {
1624                         osp_convert_inout(srcdev, dev, sizeof(dev));
1625                 } else {
1626                         osp_convert_inout(actualsrc, dev, sizeof(dev));
1627                 }
1628         } else {
1629                 osp_convert_inout(source, src, sizeof(src));
1630                 osp_convert_inout(srcdev, dev, sizeof(dev));
1631         }
1632
1633         if (provider->srvtype == OSP_SRV_NPQUERY) {
1634                 OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_NPQUERY);
1635                 if (!ast_strlen_zero(dest)) {
1636                         preferred[0] = dest;
1637                 }
1638                 results->numdests = 1;
1639         } else {
1640                 OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_VOICE);
1641                 results->numdests = OSP_DEF_MAXDESTS;
1642         }
1643
1644         error = OSPPTransactionRequestAuthorisation(results->outhandle,
1645                 src,
1646                 dev,
1647                 calling ? calling : "",
1648                 OSPC_NFORMAT_E164,
1649                 callednum,
1650                 OSPC_NFORMAT_E164,
1651                 NULL,
1652                 callidnum,
1653                 callids,
1654                 preferred,
1655                 &results->numdests,
1656                 &dummy,
1657                 NULL);
1658
1659         for (i = 0; i < callidnum; i++) {
1660                 OSPPCallIdDelete(&callids[i]);
1661         }
1662
1663         if (error != OSPC_ERR_NO_ERROR) {
1664                 ast_log(LOG_WARNING, "OSP: Unable to request authorization, error '%d'\n", error);
1665                 results->numdests = 0;
1666                 if (results->inhandle != OSP_INVALID_HANDLE) {
1667                         OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1668                 }
1669                 return OSP_ERROR;
1670         }
1671
1672         if (!results->numdests) {
1673                 ast_debug(1, "OSP: No more destination\n");
1674                 if (results->inhandle != OSP_INVALID_HANDLE) {
1675                         OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1676                 }
1677                 return OSP_FAILED;
1678         }
1679
1680         results->outcallid.len = sizeof(results->outcallid.buf);
1681         tokenlen = sizeof(token);
1682         error = OSPPTransactionGetFirstDestination(results->outhandle,
1683                 0,
1684                 NULL,
1685                 NULL,
1686                 &results->outtimelimit,
1687                 &results->outcallid.len,
1688                 results->outcallid.buf,
1689                 sizeof(callednum),
1690                 callednum,
1691                 sizeof(callingnum),
1692                 callingnum,
1693                 sizeof(destination),
1694                 destination,
1695                 0,
1696                 NULL,
1697                 &tokenlen,
1698                 token);
1699         if (error != OSPC_ERR_NO_ERROR) {
1700                 ast_debug(1, "OSP: Unable to get first route, error '%d'\n", error);
1701                 results->numdests = 0;
1702                 results->outtimelimit = OSP_DEF_TIMELIMIT;
1703                 if (results->inhandle != OSP_INVALID_HANDLE) {
1704                         OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1705                 }
1706                 return OSP_ERROR;
1707         }
1708
1709         results->numdests--;
1710         results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
1711         ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
1712         ast_debug(1, "OSP: calling '%s'\n", callingnum);
1713         ast_debug(1, "OSP: called '%s'\n", callednum);
1714         ast_debug(1, "OSP: destination '%s'\n", destination);
1715         ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1716
1717         if ((res = osp_check_destination(provider, callingnum, callednum, destination, tokenlen, token, &reason, results)) > 0) {
1718                 return OSP_OK;
1719         }
1720
1721         if (!results->numdests) {
1722                 ast_debug(1, "OSP: No more destination\n");
1723                 results->outtimelimit = OSP_DEF_TIMELIMIT;
1724                 OSPPTransactionRecordFailure(results->outhandle, reason);
1725                 if (results->inhandle != OSP_INVALID_HANDLE) {
1726                         OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1727                 }
1728                 return OSP_FAILED;
1729         }
1730
1731         while(results->numdests) {
1732                 results->outcallid.len = sizeof(results->outcallid.buf);
1733                 tokenlen = sizeof(token);
1734                 error = OSPPTransactionGetNextDestination(results->outhandle,
1735                         reason,
1736                         0,
1737                         NULL,
1738                         NULL,
1739                         &results->outtimelimit,
1740                         &results->outcallid.len,
1741                         results->outcallid.buf,
1742                         sizeof(callednum),
1743                         callednum,
1744                         sizeof(callingnum),
1745                         callingnum,
1746                         sizeof(destination),
1747                         destination,
1748                         0,
1749                         NULL,
1750                         &tokenlen,
1751                         token);
1752                 if (error == OSPC_ERR_NO_ERROR) {
1753                         results->numdests--;
1754                         results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
1755                         ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
1756                         ast_debug(1, "OSP: calling '%s'\n", callingnum);
1757                         ast_debug(1, "OSP: called '%s'\n", callednum);
1758                         ast_debug(1, "OSP: destination '%s'\n", destination);
1759                         ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1760
1761                         if ((res = osp_check_destination(provider, callingnum, callednum, destination, tokenlen, token, &reason, results)) > 0) {
1762                                 break;
1763                         } else if (!results->numdests) {
1764                                 ast_debug(1, "OSP: No more destination\n");
1765                                 OSPPTransactionRecordFailure(results->outhandle, reason);
1766                                 if (results->inhandle != OSP_INVALID_HANDLE) {
1767                                         OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1768                                 }
1769                                 res = OSP_FAILED;
1770                                 break;
1771                         }
1772                 } else {
1773                         ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
1774                         results->numdests = 0;
1775                         results->outtimelimit = OSP_DEF_TIMELIMIT;
1776                         if (results->inhandle != OSP_INVALID_HANDLE) {
1777                                 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1778                         }
1779                         res = OSP_ERROR;
1780                         break;
1781                 }
1782         }
1783
1784         return res;
1785 }
1786
1787 /*!
1788  * \brief OSP Lookup Next function
1789  * \param name OSP provider name
1790  * \param cause Asterisk hangup cause
1791  * \param results Lookup results, in/output
1792  * \return OSP_OK Found , OSP_FAILED No route, OSP_ERROR Error
1793  */
1794 static int osp_next(
1795         const char* name,
1796         int cause,
1797         struct osp_results* results)
1798 {
1799         int res;
1800         struct osp_provider* provider = NULL;
1801         char calling[OSP_SIZE_NORSTR];
1802         char called[OSP_SIZE_NORSTR];
1803         char dest[OSP_SIZE_NORSTR];
1804         unsigned int tokenlen;
1805         char token[OSP_SIZE_TOKSTR];
1806         OSPEFAILREASON reason;
1807         OSPE_OPERATOR_NAME type;
1808         int error;
1809
1810         if (results == NULL) {
1811                 ast_log(LOG_ERROR, "Invalid parameters\n");
1812                 return OSP_ERROR;
1813         }
1814
1815         results->outtech[0] = '\0';
1816         results->dest[0] = '\0';
1817         results->calling[0] = '\0';
1818         results->called[0] = '\0';
1819         results->token[0] = '\0';
1820         results->networkid[0] = '\0';
1821         results->nprn[0] = '\0';
1822         results->npcic[0] = '\0';
1823         results->npdi = 0;
1824         for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
1825                 results->opname[type][0] = '\0';
1826         }
1827         results->outtimelimit = OSP_DEF_TIMELIMIT;
1828
1829         if ((res = osp_get_provider(name, &provider)) <= 0) {
1830                 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
1831                 return res;
1832         }
1833
1834         if (results->outhandle == OSP_INVALID_HANDLE) {
1835                 ast_debug(1, "OSP: Transaction handle undefined\n");
1836                 results->numdests = 0;
1837                 if (results->inhandle != OSP_INVALID_HANDLE) {
1838                         OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1839                 }
1840                 return OSP_ERROR;
1841         }
1842
1843         reason = asterisk2osp(cause);
1844
1845         if (!results->numdests) {
1846                 ast_debug(1, "OSP: No more destination\n");
1847                 OSPPTransactionRecordFailure(results->outhandle, reason);
1848                 if (results->inhandle != OSP_INVALID_HANDLE) {
1849                         OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1850                 }
1851                 return OSP_FAILED;
1852         }
1853
1854         while(results->numdests) {
1855                 results->outcallid.len = sizeof(results->outcallid.buf);
1856                 tokenlen = sizeof(token);
1857                 error = OSPPTransactionGetNextDestination(
1858                         results->outhandle,
1859                         reason,
1860                         0,
1861                         NULL,
1862                         NULL,
1863                         &results->outtimelimit,
1864                         &results->outcallid.len,
1865                         results->outcallid.buf,
1866                         sizeof(called),
1867                         called,
1868                         sizeof(calling),
1869                         calling,
1870                         sizeof(dest),
1871                         dest,
1872                         0,
1873                         NULL,
1874                         &tokenlen,
1875                         token);
1876                 if (error == OSPC_ERR_NO_ERROR) {
1877                         results->numdests--;
1878                         results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
1879                         ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
1880                         ast_debug(1, "OSP: calling '%s'\n", calling);
1881                         ast_debug(1, "OSP: called '%s'\n", called);
1882                         ast_debug(1, "OSP: destination '%s'\n", dest);
1883                         ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1884
1885                         if ((res = osp_check_destination(provider, calling, called, dest, tokenlen, token, &reason, results)) > 0) {
1886                                 res = OSP_OK;
1887                                 break;
1888                         } else if (!results->numdests) {
1889                                 ast_debug(1, "OSP: No more destination\n");
1890                                 OSPPTransactionRecordFailure(results->outhandle, reason);
1891                                 if (results->inhandle != OSP_INVALID_HANDLE) {
1892                                         OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1893                                 }
1894                                 res = OSP_FAILED;
1895                                 break;
1896                         }
1897                 } else {
1898                         ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
1899                         results->token[0] = '\0';
1900                         results->numdests = 0;
1901                         results->outtimelimit = OSP_DEF_TIMELIMIT;
1902                         if (results->inhandle != OSP_INVALID_HANDLE) {
1903                                 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1904                         }
1905                         res = OSP_ERROR;
1906                         break;
1907                 }
1908         }
1909
1910         return res;
1911 }
1912
1913 /*!
1914  * \brief Get integer from variable string
1915  * \param vstr Variable string
1916  * \return OSP_DEF_INTSTATS Error
1917  */
1918 static int osp_get_varint(
1919         const char* vstr)
1920 {
1921         char* tmp;
1922         int value = OSP_DEF_INTSTATS;
1923
1924         if (!ast_strlen_zero(vstr)) {
1925                 if ((tmp = strchr(vstr, '=')) != NULL) {
1926                         tmp++;
1927                         if (sscanf(tmp, "%30d", &value) != 1) {
1928                                 value = OSP_DEF_INTSTATS;
1929                         }
1930                 }
1931         }
1932
1933         return value;
1934 }
1935
1936 /*!
1937  * \brief Get float from variable string
1938  * \param vstr Variable string
1939  * \return OSP_DEF_FLOATSTATS Error
1940  */
1941 static float osp_get_varfloat(
1942         const char* vstr)
1943 {
1944         char* tmp;
1945         float value = OSP_DEF_FLOATSTATS;
1946
1947         if (!ast_strlen_zero(vstr)) {
1948                 if ((tmp = strchr(vstr, '=')) != NULL) {
1949                         tmp++;
1950                         if (sscanf(tmp, "%30f", &value) != 1) {
1951                                 value = OSP_DEF_FLOATSTATS;
1952                         }
1953                 }
1954         }
1955
1956         return value;
1957 }
1958
1959 /*!
1960  * \brief Report QoS
1961  * \param trans OSP in/outbound transaction handle
1962  * \param leg Inbound/outbound
1963  * \param qos QoS string
1964  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
1965  */
1966 static int osp_report_qos(
1967         int trans,
1968         enum osp_callleg leg,
1969         const char* qos)
1970 {
1971         int res = OSP_FAILED;
1972         enum osp_direction dir;
1973         char buffer[OSP_SIZE_NORSTR];
1974         char* tmp;
1975         char* item;
1976         int totalpackets[OSP_DIR_NUMBER];
1977         struct osp_metrics lost[OSP_DIR_NUMBER];
1978         struct osp_metrics jitter[OSP_DIR_NUMBER];
1979         struct osp_metrics rtt;
1980         int value;
1981
1982         if (!ast_strlen_zero(qos)) {
1983                 for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
1984                         totalpackets[dir] = OSP_DEF_INTSTATS;
1985                 }
1986
1987                 for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
1988                         lost[dir].value = OSP_DEF_INTSTATS;
1989                         lost[dir].min = OSP_DEF_FLOATSTATS;
1990                         lost[dir].max = OSP_DEF_FLOATSTATS;
1991                         lost[dir].avg = OSP_DEF_FLOATSTATS;
1992                         lost[dir].sdev = OSP_DEF_FLOATSTATS;
1993                 }
1994
1995                 for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
1996                         jitter[dir].value = OSP_DEF_INTSTATS;
1997                         jitter[dir].min = OSP_DEF_FLOATSTATS;
1998                         jitter[dir].max = OSP_DEF_FLOATSTATS;
1999                         jitter[dir].avg = OSP_DEF_FLOATSTATS;
2000                         jitter[dir].sdev = OSP_DEF_FLOATSTATS;
2001                 }
2002
2003                 rtt.value = OSP_DEF_INTSTATS;
2004                 rtt.min = OSP_DEF_FLOATSTATS;
2005                 rtt.max = OSP_DEF_FLOATSTATS;
2006                 rtt.avg = OSP_DEF_FLOATSTATS;
2007                 rtt.sdev = OSP_DEF_FLOATSTATS;
2008
2009                 ast_copy_string(buffer, qos, sizeof(buffer));
2010                 for (item = strtok_r(buffer, ";", &tmp); item; item = strtok_r(NULL, ";", &tmp)) {
2011                         if (!strncasecmp(item, "rxcount", strlen("rxcount"))) {
2012                                 totalpackets[OSP_DIR_RX] = osp_get_varint(item);
2013                         } else if (!strncasecmp(item, "txcount", strlen("txcount"))) {
2014                                 totalpackets[OSP_DIR_TX] = osp_get_varint(item);
2015                         } else if (!strncasecmp(item, "lp", strlen("lp"))) {
2016                                 lost[OSP_DIR_RX].value = osp_get_varint(item);
2017                         } else if (!strncasecmp(item, "minrxlost", strlen("minrxlost"))) {
2018                                 lost[OSP_DIR_RX].min = osp_get_varfloat(item);
2019                         } else if (!strncasecmp(item, "maxrxlost", strlen("maxrxlost"))) {
2020                                 lost[OSP_DIR_RX].max = osp_get_varfloat(item);
2021                         } else if (!strncasecmp(item, "avgrxlost", strlen("avgrxlost"))) {
2022                                 lost[OSP_DIR_RX].avg = osp_get_varfloat(item);
2023                         } else if (!strncasecmp(item, "stdevrxlost", strlen("stdevrxlost"))) {
2024                                 lost[OSP_DIR_RX].sdev = osp_get_varfloat(item);
2025                         } else if (!strncasecmp(item, "rlp", strlen("rlp"))) {
2026                                 lost[OSP_DIR_TX].value = osp_get_varint(item);
2027                         } else if (!strncasecmp(item, "reported_minlost", strlen("reported_minlost"))) {
2028                                 lost[OSP_DIR_TX].min = osp_get_varfloat(item);
2029                         } else if (!strncasecmp(item, "reported_maxlost", strlen("reported_maxlost"))) {
2030                                 lost[OSP_DIR_TX].max = osp_get_varfloat(item);
2031                         } else if (!strncasecmp(item, "reported_avglost", strlen("reported_avglost"))) {
2032                                 lost[OSP_DIR_TX].avg = osp_get_varfloat(item);
2033                         } else if (!strncasecmp(item, "reported_stdevlost", strlen("reported_stdevlost"))) {
2034                                 lost[OSP_DIR_TX].sdev = osp_get_varfloat(item);
2035                         } else if (!strncasecmp(item, "rxjitter", strlen("rxjitter"))) {
2036                                 jitter[OSP_DIR_RX].value = osp_get_varint(item);
2037                         } else if (!strncasecmp(item, "minrxjitter", strlen("minrxjitter"))) {
2038                                 jitter[OSP_DIR_RX].min = osp_get_varfloat(item);
2039                         } else if (!strncasecmp(item, "maxrxjitter", strlen("maxrxjitter"))) {
2040                                 jitter[OSP_DIR_RX].max = osp_get_varfloat(item);
2041                         } else if (!strncasecmp(item, "avgrxjitter", strlen("avgjitter"))) {
2042                                 jitter[OSP_DIR_RX].avg = osp_get_varfloat(item);
2043                         } else if (!strncasecmp(item, "stdevrxjitter", strlen("stdevjitter"))) {
2044                                 jitter[OSP_DIR_RX].sdev = osp_get_varfloat(item);
2045                         } else if (!strncasecmp(item, "txjitter", strlen("txjitter"))) {
2046                                 jitter[OSP_DIR_TX].value = osp_get_varint(item);
2047                         } else if (!strncasecmp(item, "reported_minjitter", strlen("reported_minjitter"))) {
2048                                 jitter[OSP_DIR_TX].min = osp_get_varfloat(item);
2049                         } else if (!strncasecmp(item, "reported_maxjitter", strlen("reported_maxjitter"))) {
2050                                 jitter[OSP_DIR_TX].max = osp_get_varfloat(item);
2051                         } else if (!strncasecmp(item, "reported_avgjitter", strlen("reported_avgjitter"))) {
2052                                 jitter[OSP_DIR_TX].avg = osp_get_varfloat(item);
2053                         } else if (!strncasecmp(item, "reported_stdevjitter", strlen("reported_stdevjitter"))) {
2054                                 jitter[OSP_DIR_TX].sdev = osp_get_varfloat(item);
2055                         } else if (!strncasecmp(item, "rtt", strlen("rtt"))) {
2056                                 rtt.value = osp_get_varint(item);
2057                         } else if (!strncasecmp(item, "minrtt", strlen("minrtt"))) {
2058                                 rtt.min = osp_get_varfloat(item);
2059                         } else if (!strncasecmp(item, "maxrtt", strlen("maxrtt"))) {
2060                                 rtt.max = osp_get_varfloat(item);
2061                         } else if (!strncasecmp(item, "avgrtt", strlen("avgrtt"))) {
2062                                 rtt.avg = osp_get_varfloat(item);
2063                         } else if (!strncasecmp(item, "stdevrtt", strlen("stdevrtt"))) {
2064                                 rtt.sdev = osp_get_varfloat(item);
2065                         }
2066                 }
2067
2068                 ast_debug(1, "OSP: call leg '%d'\n", leg);
2069                 ast_debug(1, "OSP: rxcount '%d'\n", totalpackets[OSP_DIR_RX]);
2070                 ast_debug(1, "OSP: txcount '%d'\n", totalpackets[OSP_DIR_TX]);
2071                 ast_debug(1, "OSP: lp '%d'\n",lost[OSP_DIR_RX].value);
2072                 ast_debug(1, "OSP: minrxlost '%f'\n", lost[OSP_DIR_RX].min);
2073                 ast_debug(1, "OSP: maxrxlost '%f'\n", lost[OSP_DIR_RX].max);
2074                 ast_debug(1, "OSP: avgrxlost '%f'\n", lost[OSP_DIR_RX].avg);
2075                 ast_debug(1, "OSP: stdevrxlost '%f'\n", lost[OSP_DIR_RX].sdev);
2076                 ast_debug(1, "OSP: rlp '%d'\n", lost[OSP_DIR_TX].value);
2077                 ast_debug(1, "OSP: reported_minlost '%f'\n", lost[OSP_DIR_TX].min);
2078                 ast_debug(1, "OSP: reported_maxlost '%f'\n", lost[OSP_DIR_TX].max);
2079                 ast_debug(1, "OSP: reported_avglost '%f'\n", lost[OSP_DIR_TX].avg);
2080                 ast_debug(1, "OSP: reported_stdevlost '%f'\n", lost[OSP_DIR_TX].sdev);
2081                 ast_debug(1, "OSP: rxjitter '%d'\n", jitter[OSP_DIR_RX].value);
2082                 ast_debug(1, "OSP: minrxjitter '%f'\n", jitter[OSP_DIR_RX].min);
2083                 ast_debug(1, "OSP: maxrxjitter '%f'\n", jitter[OSP_DIR_RX].max);
2084                 ast_debug(1, "OSP: avgrxjitter '%f'\n", jitter[OSP_DIR_RX].avg);
2085                 ast_debug(1, "OSP: stdevrxjitter '%f'\n", jitter[OSP_DIR_RX].sdev);
2086                 ast_debug(1, "OSP: txjitter '%d'\n", jitter[OSP_DIR_TX].value);
2087                 ast_debug(1, "OSP: reported_minjitter '%f'\n", jitter[OSP_DIR_TX].min);
2088                 ast_debug(1, "OSP: reported_maxjitter '%f'\n", jitter[OSP_DIR_TX].max);
2089                 ast_debug(1, "OSP: reported_avgjitter '%f'\n", jitter[OSP_DIR_TX].avg);
2090                 ast_debug(1, "OSP: reported_stdevjitter '%f'\n", jitter[OSP_DIR_TX].sdev);
2091                 ast_debug(1, "OSP: rtt '%d'\n", rtt.value);
2092                 ast_debug(1, "OSP: minrtt '%f'\n", rtt.min);
2093                 ast_debug(1, "OSP: maxrtt '%f'\n", rtt.max);
2094                 ast_debug(1, "OSP: avgrtt '%f'\n", rtt.avg);
2095                 ast_debug(1, "OSP: stdevrtt '%f'\n", rtt.sdev);
2096
2097                 if (leg == OSP_CALL_INBOUND) {
2098                         OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SDIR_SRCREP, totalpackets[OSP_DIR_RX]);
2099                         OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_DESTREP, totalpackets[OSP_DIR_TX]);
2100                         if (lost[OSP_DIR_RX].value >= 0) {
2101                                 value = lost[OSP_DIR_RX].value;
2102                         } else {
2103                                 value = (int)lost[OSP_DIR_RX].avg;
2104                         }
2105                         OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SDIR_SRCREP, value, OSP_DEF_INTSTATS);
2106                         if (lost[OSP_DIR_TX].value >= 0) {
2107                                 value = lost[OSP_DIR_TX].value;
2108                         } else {
2109                                 value = (int)lost[OSP_DIR_TX].avg;
2110                         }
2111                         OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_DESTREP, value, OSP_DEF_INTSTATS);
2112                         if (jitter[OSP_DIR_RX].value >= 0) {
2113                                 value = jitter[OSP_DIR_RX].value;
2114                         } else {
2115                                 value = (int)jitter[OSP_DIR_RX].avg;
2116                         }
2117                         OSPPTransactionSetJitter(trans,
2118                                 OSPC_SMETRIC_RTP,
2119                                 OSPC_SDIR_SRCREP,
2120                                 OSP_DEF_INTSTATS,
2121                                 (int)jitter[OSP_DIR_RX].min,
2122                                 (int)jitter[OSP_DIR_RX].max,
2123                                 value, jitter[OSP_DIR_RX].sdev);
2124                         if (jitter[OSP_DIR_TX].value >= 0) {
2125                                 value = jitter[OSP_DIR_TX].value;
2126                         } else {
2127                                 value = (int)jitter[OSP_DIR_TX].avg;
2128                         }
2129                         OSPPTransactionSetJitter(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_DESTREP,
2130                                 OSP_DEF_INTSTATS, (int)jitter[OSP_DIR_TX].min, (int)jitter[OSP_DIR_TX].max, value, jitter[OSP_DIR_TX].sdev);
2131                 } else {
2132                         OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SDIR_DESTREP, totalpackets[OSP_DIR_RX]);
2133                         OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_SRCREP, totalpackets[OSP_DIR_TX]);
2134                         OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SDIR_DESTREP, lost[OSP_DIR_RX].value, OSP_DEF_INTSTATS);
2135                         OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_SRCREP, lost[OSP_DIR_TX].value, OSP_DEF_INTSTATS);
2136                         if (jitter[OSP_DIR_RX].value >= 0) {
2137                                 value = jitter[OSP_DIR_RX].value;
2138                         } else {
2139                                 value = (int)jitter[OSP_DIR_RX].avg;
2140                         }
2141                         OSPPTransactionSetJitter(trans,
2142                                 OSPC_SMETRIC_RTP,
2143                                 OSPC_SDIR_DESTREP,
2144                                 OSP_DEF_INTSTATS,
2145                                 (int)jitter[OSP_DIR_RX].min,
2146                                 (int)jitter[OSP_DIR_RX].max,
2147                                 value,
2148                                 jitter[OSP_DIR_RX].sdev);
2149                         if (jitter[OSP_DIR_TX].value >= 0) {
2150                                 value = jitter[OSP_DIR_TX].value;
2151                         } else {
2152                                 value = (int)jitter[OSP_DIR_TX].avg;
2153                         }
2154                         OSPPTransactionSetJitter(trans,
2155                                 OSPC_SMETRIC_RTCP,
2156                                 OSPC_SDIR_SRCREP,
2157                                 OSP_DEF_INTSTATS,
2158                                 (int)jitter[OSP_DIR_TX].min,
2159                                 (int)jitter[OSP_DIR_TX].max,
2160                                 value,
2161                                 jitter[OSP_DIR_TX].sdev);
2162                 }
2163
2164                 res = OSP_OK;
2165         }
2166
2167         return res;
2168 }
2169
2170 /*!
2171  * \brief OSP Finish function
2172  * \param trans OSP in/outbound transaction handle
2173  * \param recorded If failure reason has been recorded
2174  * \param cause Asterisk hangup cause
2175  * \param start Call start time
2176  * \param connect Call connect time
2177  * \param end Call end time
2178  * \param release Who release first, 0 source, 1 destination
2179  * \param inqos Inbound QoS string
2180  * \param outqos Outbound QoS string
2181  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
2182  */
2183 static int osp_finish(
2184         int trans,
2185         int recorded,
2186         int cause,
2187         time_t start,
2188         time_t connect,
2189         time_t end,
2190         unsigned int release,
2191         const char* inqos,
2192         const char* outqos)
2193 {
2194         int res;
2195         OSPEFAILREASON reason;
2196         time_t alert = 0;
2197         unsigned isPddInfoPresent = 0;
2198         unsigned pdd = 0;
2199         unsigned int dummy = 0;
2200         int error;
2201
2202         if (trans == OSP_INVALID_HANDLE) {
2203                 return OSP_FAILED;
2204         }
2205
2206         OSPPTransactionSetRoleInfo(trans, OSPC_RSTATE_STOP, OSPC_RFORMAT_OSP, OSPC_RVENDOR_ASTERISK);
2207
2208         if (!recorded) {
2209                 reason = asterisk2osp(cause);
2210                 OSPPTransactionRecordFailure(trans, reason);
2211         }
2212
2213         osp_report_qos(trans, OSP_CALL_INBOUND, inqos);
2214         osp_report_qos(trans, OSP_CALL_OUTBOUND, outqos);
2215
2216         error = OSPPTransactionReportUsage(trans,
2217                 difftime(end, connect),
2218                 start,
2219                 end,
2220                 alert,
2221                 connect,
2222                 isPddInfoPresent,
2223                 pdd,
2224                 release,
2225                 NULL,
2226                 OSP_DEF_INTSTATS,
2227                 OSP_DEF_INTSTATS,
2228                 OSP_DEF_INTSTATS,
2229                 OSP_DEF_INTSTATS,
2230                 &dummy,
2231                 NULL);
2232         if (error == OSPC_ERR_NO_ERROR) {
2233                 ast_debug(1, "OSP: Usage reported\n");
2234                 res = OSP_OK;
2235         } else {
2236                 ast_debug(1, "OSP: Unable to report usage, error '%d'\n", error);
2237                 res = OSP_ERROR;
2238         }
2239         OSPPTransactionDelete(trans);
2240
2241         return res;
2242 }
2243
2244 /* OSP Application APIs */
2245
2246 /*!
2247  * \brief OSP Application OSPAuth
2248  * \param chan Channel
2249  * \param data Parameter
2250  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2251  */
2252 static int ospauth_exec(
2253         struct ast_channel *chan,
2254         const char *data)
2255 {
2256         int res;
2257         const char* provider = OSP_DEF_PROVIDER;
2258         struct varshead* headp;
2259         struct ast_var_t* current;
2260         const char* source = "";
2261         const char* token = "";
2262         int handle;
2263         unsigned int timelimit;
2264         char buffer[OSP_SIZE_INTSTR];
2265         const char* status;
2266         char* tmp;
2267
2268         AST_DECLARE_APP_ARGS(args,
2269                 AST_APP_ARG(provider);
2270                 AST_APP_ARG(options);
2271         );
2272
2273         tmp = ast_strdupa(data);
2274
2275         AST_STANDARD_APP_ARGS(args, tmp);
2276
2277         if (!ast_strlen_zero(args.provider)) {
2278                 provider = args.provider;
2279         }
2280         ast_debug(1, "OSPAuth: provider '%s'\n", provider);
2281
2282         headp = ast_channel_varshead(chan);
2283         AST_LIST_TRAVERSE(headp, current, entries) {
2284                 if (!strcmp(ast_var_name(current), "OSPINPEERIP")) {
2285                         source = ast_var_value(current);
2286                 } else if (!strcmp(ast_var_name(current), "OSPINTOKEN")) {
2287                         token = ast_var_value(current);
2288                 }
2289         }
2290
2291         ast_debug(1, "OSPAuth: source '%s'\n", source);
2292         ast_debug(1, "OSPAuth: token size '%zd'\n", strlen(token));
2293
2294         res = osp_auth(provider, &handle, source,
2295                 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
2296                 ast_channel_exten(chan), token, &timelimit);
2297         if (res > 0) {
2298                 status = AST_OSP_SUCCESS;
2299         } else {
2300                 timelimit = OSP_DEF_TIMELIMIT;
2301                 if (!res) {
2302                         status = AST_OSP_FAILED;
2303                 } else {
2304                         status = AST_OSP_ERROR;
2305                 }
2306         }
2307
2308         snprintf(buffer, sizeof(buffer), "%d", handle);
2309         pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
2310         ast_debug(1, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
2311         snprintf(buffer, sizeof(buffer), "%d", timelimit);
2312         pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
2313         ast_debug(1, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
2314         pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
2315         ast_debug(1, "OSPAuth: %s\n", status);
2316
2317         if(res != OSP_OK) {
2318                 res = OSP_AST_ERROR;
2319         } else {
2320                 res = OSP_AST_OK;
2321         }
2322
2323         return res;
2324 }
2325
2326 /*!
2327  * \brief OSP Application OSPLookup
2328  * \param chan Channel
2329  * \param data Parameter
2330  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2331  */
2332 static int osplookup_exec(
2333         struct ast_channel* chan,
2334         const char * data)
2335 {
2336         int res;
2337         const char* provider = OSP_DEF_PROVIDER;
2338         unsigned int callidtypes = OSP_CALLID_UNDEF;
2339         struct varshead* headp;
2340         struct ast_var_t* current;
2341         const char* actualsrc = "";
2342         const char* srcdev = "";
2343         const char* snetid = "";
2344         struct osp_npdata np;
2345         OSPE_OPERATOR_NAME type;
2346         struct osp_headers headers;
2347         unsigned int i;
2348         const char* cinfo[OSP_MAX_CUSTOMINFO] = { NULL };
2349         char buffer[OSP_SIZE_TOKSTR];
2350         struct osp_results results;
2351         const char* status;
2352         char* tmp;
2353
2354         AST_DECLARE_APP_ARGS(args,
2355                 AST_APP_ARG(exten);
2356                 AST_APP_ARG(provider);
2357                 AST_APP_ARG(options);
2358         );
2359
2360         if (ast_strlen_zero(data)) {
2361                 ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[,provider[,options]])\n");
2362                 return OSP_AST_ERROR;
2363         }
2364
2365         tmp = ast_strdupa(data);
2366
2367         AST_STANDARD_APP_ARGS(args, tmp);
2368
2369         ast_debug(1, "OSPLookup: exten '%s'\n", args.exten);
2370
2371         if (!ast_strlen_zero(args.provider)) {
2372                 provider = args.provider;
2373         }
2374         ast_debug(1, "OSPlookup: provider '%s'\n", provider);
2375
2376         if (args.options) {
2377                 if (strchr(args.options, 'h')) {
2378                         callidtypes |= OSP_CALLID_H323;
2379                 }
2380                 if (strchr(args.options, 's')) {
2381                         callidtypes |= OSP_CALLID_SIP;
2382                 }
2383                 if (strchr(args.options, 'i')) {
2384                         callidtypes |= OSP_CALLID_IAX;
2385                 }
2386         }
2387         ast_debug(1, "OSPLookup: call id types '%d'\n", callidtypes);
2388
2389         results.inhandle = OSP_INVALID_HANDLE;
2390         results.intimelimit = OSP_DEF_TIMELIMIT;
2391         results.dest[0] = '\0';
2392
2393         np.rn = "";
2394         np.cic = "";
2395         np.npdi = 0;
2396         for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2397                 np.opname[type] = "";
2398         }
2399
2400         headers.rpiduser = "";
2401         headers.paiuser = "";
2402         headers.divuser = "";
2403         headers.divhost = "";
2404         headers.pciuser = "";
2405
2406         headp = ast_channel_varshead(chan);
2407         AST_LIST_TRAVERSE(headp, current, entries) {
2408                 if (!strcmp(ast_var_name(current), "OSPINACTUALSRC")) {
2409                         actualsrc = ast_var_value(current);
2410                 } else if (!strcmp(ast_var_name(current), "OSPINPEERIP")) {
2411                         srcdev = ast_var_value(current);
2412                 } else if (!strcmp(ast_var_name(current), "OSPINTECH")) {
2413                         ast_copy_string(results.intech, ast_var_value(current), sizeof(results.intech));
2414                 } else if (!strcmp(ast_var_name(current), "OSPINHANDLE")) {
2415                         if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
2416                                 results.inhandle = OSP_INVALID_HANDLE;
2417                         }
2418                 } else if (!strcmp(ast_var_name(current), "OSPINTIMELIMIT")) {
2419                         if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
2420                                 results.intimelimit = OSP_DEF_TIMELIMIT;
2421                         }
2422                 } else if (!strcmp(ast_var_name(current), "OSPINNETWORKID")) {
2423                         snetid = ast_var_value(current);
2424                 } else if (!strcmp(ast_var_name(current), "OSPINNPRN")) {
2425                         np.rn = ast_var_value(current);
2426                 } else if (!strcmp(ast_var_name(current), "OSPINNPCIC")) {
2427                         np.cic = ast_var_value(current);
2428                 } else if (!strcmp(ast_var_name(current), "OSPINNPDI")) {
2429                         if (ast_true(ast_var_value(current))) {
2430                                 np.npdi = 1;
2431                         }
2432                 } else if (!strcmp(ast_var_name(current), "OSPINSPID")) {
2433                         np.opname[OSPC_OPNAME_SPID] = ast_var_value(current);
2434                 } else if (!strcmp(ast_var_name(current), "OSPINOCN")) {
2435                         np.opname[OSPC_OPNAME_OCN] = ast_var_value(current);
2436                 } else if (!strcmp(ast_var_name(current), "OSPINSPN")) {
2437                         np.opname[OSPC_OPNAME_SPN] = ast_var_value(current);
2438                 } else if (!strcmp(ast_var_name(current), "OSPINALTSPN")) {
2439                         np.opname[OSPC_OPNAME_ALTSPN] = ast_var_value(current);
2440                 } else if (!strcmp(ast_var_name(current), "OSPINMCC")) {
2441                         np.opname[OSPC_OPNAME_MCC] = ast_var_value(current);
2442                 } else if (!strcmp(ast_var_name(current), "OSPINMNC")) {
2443                         np.opname[OSPC_OPNAME_MNC] = ast_var_value(current);
2444                 } else if (!strcmp(ast_var_name(current), "OSPINTOHOST")) {
2445                         ast_copy_string(results.dest, ast_var_value(current), sizeof(results.dest));
2446                 } else if (!strcmp(ast_var_name(current), "OSPINRPIDUSER")) {
2447                         headers.rpiduser = ast_var_value(current);
2448                 } else if (!strcmp(ast_var_name(current), "OSPINPAIUSER")) {
2449                         headers.paiuser = ast_var_value(current);
2450                 } else if (!strcmp(ast_var_name(current), "OSPINDIVUSER")) {
2451                         headers.divuser = ast_var_value(current);
2452                 } else if (!strcmp(ast_var_name(current), "OSPINDIVHOST")) {
2453                         headers.divhost = ast_var_value(current);
2454                 } else if (!strcmp(ast_var_name(current), "OSPINPCIUSER")) {
2455                         headers.pciuser = ast_var_value(current);
2456                 } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO1")) {
2457                         cinfo[0] = ast_var_value(current);
2458                 } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO2")) {
2459                         cinfo[1] = ast_var_value(current);
2460                 } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO3")) {
2461                         cinfo[2] = ast_var_value(current);
2462                 } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO4")) {
2463                         cinfo[3] = ast_var_value(current);
2464                 } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO5")) {
2465                         cinfo[4] = ast_var_value(current);
2466                 } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO6")) {
2467                         cinfo[5] = ast_var_value(current);
2468                 } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO7")) {
2469                         cinfo[6] = ast_var_value(current);
2470                 } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO8")) {
2471                         cinfo[7] = ast_var_value(current);
2472                 }
2473         }
2474         ast_debug(1, "OSPLookup: actual source device '%s'\n", actualsrc);
2475         ast_debug(1, "OSPLookup: source device '%s'\n", srcdev);
2476         ast_debug(1, "OSPLookup: OSPINTECH '%s'\n", results.intech);
2477         ast_debug(1, "OSPLookup: OSPINHANDLE '%d'\n", results.inhandle);
2478         ast_debug(1, "OSPLookup: OSPINTIMELIMIT '%d'\n", results.intimelimit);
2479         ast_debug(1, "OSPLookup: OSPINNETWORKID '%s'\n", snetid);
2480         ast_debug(1, "OSPLookup: OSPINNPRN '%s'\n", np.rn);
2481         ast_debug(1, "OSPLookup: OSPINNPCIC '%s'\n", np.cic);
2482         ast_debug(1, "OSPLookup: OSPINNPDI '%d'\n", np.npdi);
2483         ast_debug(1, "OSPLookup: OSPINSPID '%s'\n", np.opname[OSPC_OPNAME_SPID]);
2484         ast_debug(1, "OSPLookup: OSPINOCN '%s'\n", np.opname[OSPC_OPNAME_OCN]);
2485         ast_debug(1, "OSPLookup: OSPINSPN '%s'\n", np.opname[OSPC_OPNAME_SPN]);
2486         ast_debug(1, "OSPLookup: OSPINALTSPN '%s'\n", np.opname[OSPC_OPNAME_ALTSPN]);
2487         ast_debug(1, "OSPLookup: OSPINMCC '%s'\n", np.opname[OSPC_OPNAME_MCC]);
2488         ast_debug(1, "OSPLookup: OSPINMNC '%s'\n", np.opname[OSPC_OPNAME_MNC]);
2489         ast_debug(1, "OSPLookup: OSPINTOHOST '%s'\n", results.dest);
2490         ast_debug(1, "OSPLookup: OSPINRPIDUSER '%s'\n", headers.rpiduser);
2491         ast_debug(1, "OSPLookup: OSPINPAIUSER '%s'\n", headers.paiuser);
2492         ast_debug(1, "OSPLookup: OSPINDIVUSER '%s'\n", headers.divuser);
2493         ast_debug(1, "OSPLookup: OSPINDIVHOST'%s'\n", headers.divhost);
2494         ast_debug(1, "OSPLookup: OSPINPCIUSER '%s'\n", headers.pciuser);
2495         for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
2496                 if (!ast_strlen_zero(cinfo[i])) {
2497                         ast_debug(1, "OSPLookup: OSPINCUSTOMINFO%d '%s'\n", i, cinfo[i]);
2498                 }
2499         }
2500
2501         if (ast_autoservice_start(chan) < 0) {
2502                 return OSP_AST_ERROR;
2503         }
2504
2505         res = osp_lookup(provider, callidtypes, actualsrc, srcdev,
2506                 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
2507                 args.exten, snetid, &np, &headers, cinfo, &results);
2508         if (res > 0) {
2509                 status = AST_OSP_SUCCESS;
2510         } else {
2511                 results.outtech[0] = '\0';
2512                 results.dest[0] = '\0';
2513                 results.calling[0] = '\0';
2514                 results.called[0] = '\0';
2515                 results.token[0] = '\0';
2516                 results.networkid[0] = '\0';
2517                 results.nprn[0] = '\0';
2518                 results.npcic[0] = '\0';
2519                 results.npdi = 0;
2520                 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2521                         results.opname[type][0] = '\0';
2522                 }
2523                 results.numdests = 0;
2524                 results.outtimelimit = OSP_DEF_TIMELIMIT;
2525                 results.outcallid.buf[0] = '\0';
2526                 results.outcallid.len = 0;
2527                 if (!res) {
2528                         status = AST_OSP_FAILED;
2529                 } else {
2530                         status = AST_OSP_ERROR;
2531                 }
2532         }
2533
2534         snprintf(buffer, sizeof(buffer), "%d", results.outhandle);
2535         pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
2536         ast_debug(1, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
2537         pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.outtech);
2538         ast_debug(1, "OSPLookup: OSPOUTTECH '%s'\n", results.outtech);
2539         pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
2540         ast_debug(1, "OSPLookup: OSPDESTINATION '%s'\n", results.dest);
2541         pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
2542         ast_debug(1, "OSPLookup: OSPOUTCALLING '%s'\n", results.calling);
2543         pbx_builtin_setvar_helper(chan, "OSPOUTCALLED", results.called);
2544         ast_debug(1, "OSPLookup: OSPOUTCALLED '%s'\n", results.called);
2545         pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", results.networkid);
2546         ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", results.networkid);
2547         pbx_builtin_setvar_helper(chan, "OSPOUTNPRN", results.nprn);
2548         ast_debug(1, "OSPLookup: OSPOUTNPRN '%s'\n", results.nprn);
2549         pbx_builtin_setvar_helper(chan, "OSPOUTNPCIC", results.npcic);
2550         ast_debug(1, "OSPLookup: OSPOUTNPCIC '%s'\n", results.npcic);
2551         snprintf(buffer, sizeof(buffer), "%d", results.npdi);
2552         pbx_builtin_setvar_helper(chan, "OSPOUTNPDI", buffer);
2553         ast_debug(1, "OSPLookup: OSPOUTNPDI'%s'\n", buffer);
2554         pbx_builtin_setvar_helper(chan, "OSPOUTSPID", results.opname[OSPC_OPNAME_SPID]);
2555         ast_debug(1, "OSPLookup: OSPOUTSPID '%s'\n", results.opname[OSPC_OPNAME_SPID]);
2556         pbx_builtin_setvar_helper(chan, "OSPOUTOCN", results.opname[OSPC_OPNAME_OCN]);
2557         ast_debug(1, "OSPLookup: OSPOUTOCN '%s'\n", results.opname[OSPC_OPNAME_OCN]);
2558         pbx_builtin_setvar_helper(chan, "OSPOUTSPN", results.opname[OSPC_OPNAME_SPN]);
2559         ast_debug(1, "OSPLookup: OSPOUTSPN '%s'\n", results.opname[OSPC_OPNAME_SPN]);
2560         pbx_builtin_setvar_helper(chan, "OSPOUTALTSPN", results.opname[OSPC_OPNAME_ALTSPN]);
2561         ast_debug(1, "OSPLookup: OSPOUTALTSPN '%s'\n", results.opname[OSPC_OPNAME_ALTSPN]);
2562         pbx_builtin_setvar_helper(chan, "OSPOUTMCC", results.opname[OSPC_OPNAME_MCC]);
2563         ast_debug(1, "OSPLookup: OSPOUTMCC '%s'\n", results.opname[OSPC_OPNAME_MCC]);
2564         pbx_builtin_setvar_helper(chan, "OSPOUTMNC", results.opname[OSPC_OPNAME_MNC]);
2565         ast_debug(1, "OSPLookup: OSPOUTMNC '%s'\n", results.opname[OSPC_OPNAME_MNC]);
2566         pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", results.token);
2567         ast_debug(1, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(results.token));
2568         snprintf(buffer, sizeof(buffer), "%d", results.numdests);
2569         pbx_builtin_setvar_helper(chan, "OSPDESTREMAILS", buffer);
2570         ast_debug(1, "OSPLookup: OSPDESTREMAILS '%s'\n", buffer);
2571         snprintf(buffer, sizeof(buffer), "%d", results.outtimelimit);
2572         pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
2573         ast_debug(1, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
2574         snprintf(buffer, sizeof(buffer), "%d", callidtypes);
2575         pbx_builtin_setvar_helper(chan, "OSPOUTCALLIDTYPES", buffer);
2576         ast_debug(1, "OSPLookup: OSPOUTCALLIDTYPES '%s'\n", buffer);
2577         pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
2578         ast_debug(1, "OSPLookup: %s\n", status);
2579
2580         if (!strcasecmp(results.outtech, OSP_TECH_SIP)) {
2581                 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.outtech, results.called, results.dest);
2582                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2583                 if (!ast_strlen_zero(results.token)) {
2584                         snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
2585                         pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
2586                         ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
2587                 }
2588         } else if (!strcasecmp(results.outtech, OSP_TECH_H323)) {
2589                 if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
2590                         osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
2591                 } else {
2592                         buffer[0] = '\0';
2593                 }
2594                 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
2595                 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.outtech, results.called, results.dest);
2596                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2597         } else if (!strcasecmp(results.outtech, OSP_TECH_IAX)) {
2598                 snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.outtech, results.dest, results.called);
2599                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2600         } else if (!strcasecmp(results.outtech, OSP_TECH_SKYPE)) {
2601                 snprintf(buffer, sizeof(buffer), "%s/%s", results.outtech, results.called);
2602                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2603         }
2604
2605         if (ast_autoservice_stop(chan) < 0) {
2606                 return OSP_AST_ERROR;
2607         }
2608
2609         if(res != OSP_OK) {
2610                 res = OSP_AST_ERROR;
2611         } else {
2612                 res = OSP_AST_OK;
2613         }
2614
2615         return res;
2616 }
2617
2618 /*!
2619  * \brief OSP Application OSPNext
2620  * \param chan Channel
2621  * \param data Parameter
2622  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2623  */
2624 static int ospnext_exec(
2625         struct ast_channel* chan,
2626         const char * data)
2627 {
2628         int res;
2629         const char* provider = OSP_DEF_PROVIDER;
2630         int cause = 0;
2631         struct varshead* headp;
2632         struct ast_var_t* current;
2633         struct osp_results results;
2634         OSPE_OPERATOR_NAME type;
2635         char buffer[OSP_SIZE_TOKSTR];
2636         unsigned int callidtypes = OSP_CALLID_UNDEF;
2637         const char* status;
2638         char* tmp;
2639
2640         AST_DECLARE_APP_ARGS(args,
2641                 AST_APP_ARG(cause);
2642                 AST_APP_ARG(provider);
2643                 AST_APP_ARG(options);
2644         );
2645
2646         if (ast_strlen_zero(data)) {
2647                 ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[,provider[,options]])\n");
2648                 return OSP_AST_ERROR;
2649         }
2650
2651         tmp = ast_strdupa(data);
2652
2653         AST_STANDARD_APP_ARGS(args, tmp);
2654
2655         if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
2656                 cause = 0;
2657         }
2658         ast_debug(1, "OSPNext: cause '%d'\n", cause);
2659
2660         if (!ast_strlen_zero(args.provider)) {
2661                 provider = args.provider;
2662         }
2663         ast_debug(1, "OSPlookup: provider '%s'\n", provider);
2664
2665         results.inhandle = OSP_INVALID_HANDLE;
2666         results.outhandle = OSP_INVALID_HANDLE;
2667         results.intimelimit = OSP_DEF_TIMELIMIT;
2668         results.numdests = 0;
2669
2670         headp = ast_channel_varshead(chan);
2671         AST_LIST_TRAVERSE(headp, current, entries) {
2672                 if (!strcmp(ast_var_name(current), "OSPINHANDLE")) {
2673                         if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
2674                                 results.inhandle = OSP_INVALID_HANDLE;
2675                         }
2676                 } else if (!strcmp(ast_var_name(current), "OSPOUTHANDLE")) {
2677                         if (sscanf(ast_var_value(current), "%30d", &results.outhandle) != 1) {
2678                                 results.outhandle = OSP_INVALID_HANDLE;
2679                         }
2680                 } else if (!strcmp(ast_var_name(current), "OSPINTIMELIMIT")) {
2681                         if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
2682                                 results.intimelimit = OSP_DEF_TIMELIMIT;
2683                         }
2684                 } else if (!strcmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) {
2685                         if (sscanf(ast_var_value(current), "%30d", &callidtypes) != 1) {
2686                                 callidtypes = OSP_CALLID_UNDEF;
2687                         }
2688                 } else if (!strcmp(ast_var_name(current), "OSPDESTREMAILS")) {
2689                         if (sscanf(ast_var_value(current), "%30d", &results.numdests) != 1) {
2690                                 results.numdests = 0;
2691                         }
2692                 }
2693         }
2694         ast_debug(1, "OSPNext: OSPINHANDLE '%d'\n", results.inhandle);
2695         ast_debug(1, "OSPNext: OSPOUTHANDLE '%d'\n", results.outhandle);
2696         ast_debug(1, "OSPNext: OSPINTIMELIMIT '%d'\n", results.intimelimit);
2697         ast_debug(1, "OSPNext: OSPOUTCALLIDTYPES '%d'\n", callidtypes);
2698         ast_debug(1, "OSPNext: OSPDESTREMAILS '%d'\n", results.numdests);
2699
2700         if ((res = osp_next(provider, cause, &results)) > 0) {
2701                 status = AST_OSP_SUCCESS;
2702         } else {
2703                 results.outtech[0] = '\0';
2704                 results.dest[0] = '\0';
2705                 results.calling[0] = '\0';
2706                 results.called[0] = '\0';
2707                 results.token[0] = '\0';
2708                 results.networkid[0] = '\0';
2709                 results.nprn[0] = '\0';
2710                 results.npcic[0] = '\0';
2711                 results.npdi = 0;
2712                 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
2713                         results.opname[type][0] = '\0';
2714                 }
2715                 results.numdests = 0;
2716                 results.outtimelimit = OSP_DEF_TIMELIMIT;
2717                 results.outcallid.buf[0] = '\0';
2718                 results.outcallid.len = 0;
2719                 if (!res) {
2720                         status = AST_OSP_FAILED;
2721                 } else {
2722                         status = AST_OSP_ERROR;
2723                 }
2724         }
2725
2726         pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.outtech);
2727         ast_debug(1, "OSPNext: OSPOUTTECH '%s'\n", results.outtech);
2728         pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
2729         ast_debug(1, "OSPNext: OSPDESTINATION '%s'\n", results.dest);
2730         pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
2731         ast_debug(1, "OSPNext: OSPOUTCALLING '%s'\n", results.calling);
2732         pbx_builtin_setvar_helper(chan, "OSPOUTCALLED", results.called);
2733         ast_debug(1, "OSPNext: OSPOUTCALLED'%s'\n", results.called);
2734         pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", results.networkid);
2735         ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", results.networkid);
2736         pbx_builtin_setvar_helper(chan, "OSPOUTNPRN", results.nprn);
2737         ast_debug(1, "OSPLookup: OSPOUTNPRN '%s'\n", results.nprn);
2738         pbx_builtin_setvar_helper(chan, "OSPOUTNPCIC", results.npcic);
2739         ast_debug(1, "OSPLookup: OSPOUTNPCIC '%s'\n", results.npcic);
2740         snprintf(buffer, sizeof(buffer), "%d", results.npdi);
2741         pbx_builtin_setvar_helper(chan, "OSPOUTNPDI", buffer);
2742         ast_debug(1, "OSPLookup: OSPOUTNPDI'%s'\n", buffer);
2743         pbx_builtin_setvar_helper(chan, "OSPOUTSPID", results.opname[OSPC_OPNAME_SPID]);
2744         ast_debug(1, "OSPLookup: OSPOUTSPID '%s'\n", results.opname[OSPC_OPNAME_SPID]);
2745         pbx_builtin_setvar_helper(chan, "OSPOUTOCN", results.opname[OSPC_OPNAME_OCN]);
2746         ast_debug(1, "OSPLookup: OSPOUTOCN '%s'\n", results.opname[OSPC_OPNAME_OCN]);
2747         pbx_builtin_setvar_helper(chan, "OSPOUTSPN", results.opname[OSPC_OPNAME_SPN]);
2748         ast_debug(1, "OSPLookup: OSPOUTSPN '%s'\n", results.opname[OSPC_OPNAME_SPN]);
2749         pbx_builtin_setvar_helper(chan, "OSPOUTALTSPN", results.opname[OSPC_OPNAME_ALTSPN]);
2750         ast_debug(1, "OSPLookup: OSPOUTALTSPN '%s'\n", results.opname[OSPC_OPNAME_ALTSPN]);
2751         pbx_builtin_setvar_helper(chan, "OSPOUTMCC", results.opname[OSPC_OPNAME_MCC]);
2752         ast_debug(1, "OSPLookup: OSPOUTMCC '%s'\n", results.opname[OSPC_OPNAME_MCC]);
2753         pbx_builtin_setvar_helper(chan, "OSPOUTMNC", results.opname[OSPC_OPNAME_MNC]);
2754         ast_debug(1, "OSPLookup: OSPOUTMNC '%s'\n", results.opname[OSPC_OPNAME_MNC]);
2755         pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", results.token);
2756         ast_debug(1, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(results.token));
2757         snprintf(buffer, sizeof(buffer), "%d", results.numdests);
2758         pbx_builtin_setvar_helper(chan, "OSPDESTREMAILS", buffer);
2759         ast_debug(1, "OSPNext: OSPDESTREMAILS '%s'\n", buffer);
2760         snprintf(buffer, sizeof(buffer), "%d", results.outtimelimit);
2761         pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
2762         ast_debug(1, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
2763         pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
2764         ast_debug(1, "OSPNext: %s\n", status);
2765
2766         if (!strcasecmp(results.outtech, OSP_TECH_SIP)) {
2767                 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.outtech, results.called, results.dest);
2768                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2769                 if (!ast_strlen_zero(results.token)) {
2770                         snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
2771                         pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
2772                         ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
2773                 }
2774         } else if (!strcasecmp(results.outtech, OSP_TECH_H323)) {
2775                 if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
2776                         osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
2777                 } else {
2778                         buffer[0] = '\0';
2779                 }
2780                 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
2781                 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.outtech, results.called, results.dest);
2782                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2783         } else if (!strcasecmp(results.outtech, OSP_TECH_IAX)) {
2784                 snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.outtech, results.dest, results.called);
2785                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2786         } else if (!strcasecmp(results.outtech, OSP_TECH_SKYPE)) {
2787                 snprintf(buffer, sizeof(buffer), "%s/%s", results.outtech, results.called);
2788                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
2789         }
2790
2791         if(res != OSP_OK) {
2792                 res = OSP_AST_ERROR;
2793         } else {
2794                 res = OSP_AST_OK;
2795         }
2796
2797         return res;
2798 }
2799
2800 /*!
2801  * \brief OSP Application OSPFinish
2802  * \param chan Channel
2803  * \param data Parameter
2804  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
2805  */
2806 static int ospfinished_exec(
2807         struct ast_channel* chan,
2808         const char * data)
2809 {
2810         int res = OSP_OK;
2811         int cause = 0;
2812         struct varshead* headp;
2813         struct ast_var_t* current;
2814         int inhandle = OSP_INVALID_HANDLE;
2815         int outhandle = OSP_INVALID_HANDLE;
2816         int recorded = 0;
2817         time_t start = 0, connect = 0, end = 0;
2818         unsigned int release;
2819         char buffer[OSP_SIZE_INTSTR];
2820         char inqos[OSP_SIZE_QOSSTR] = { 0 };
2821         char outqos[OSP_SIZE_QOSSTR] = { 0 };
2822         const char* status;
2823         char* tmp;
2824
2825         AST_DECLARE_APP_ARGS(args,
2826                 AST_APP_ARG(cause);
2827                 AST_APP_ARG(options);