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