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