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