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