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