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