Start untangling header inclusion in a way that does not affect
[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>ssl</depend>
34  ***/
35
36 #include "asterisk.h"
37
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39
40 #include <errno.h>
41 #include <osp/osp.h>
42 #include <osp/osputils.h>
43
44 #include "asterisk/lock.h"
45 #include "asterisk/config.h"
46 #include "asterisk/utils.h"
47 #include "asterisk/causes.h"
48 #include "asterisk/channel.h"
49 #include "asterisk/app.h"
50 #include "asterisk/module.h"
51 #include "asterisk/pbx.h"
52 #include "asterisk/options.h"
53 #include "asterisk/cli.h"
54 #include "asterisk/logger.h"
55 #include "asterisk/astosp.h"
56
57 /* OSP Buffer Sizes */
58 #define OSP_INTSTR_SIZE         ((unsigned int)16)              /* OSP signed/unsigned int string buffer size */
59 #define OSP_NORSTR_SIZE         ((unsigned int)256)             /* OSP normal string buffer size */
60 #define OSP_TOKSTR_SIZE         ((unsigned int)4096)    /* OSP token string buffer size */
61 #define OSP_TECHSTR_SIZE        ((unsigned int)32)              /* OSP signed/unsigned int string buffer size */
62 #define OSP_UUID_SIZE           ((unsigned int)16)              /* UUID size */
63 #define OSP_UUIDSTR_SIZE        ((unsigned int)36)              /* UUID string size */
64
65 /* OSP Authentication Policy */
66 enum osp_authpolicy {
67         OSP_AUTH_NO,            /* Accept any call */
68         OSP_AUTH_YES,           /* Accept call with valid OSP token or without OSP token */
69         OSP_AUTH_EXCLUSIVE      /* Only accept call with valid OSP token */
70 };
71
72 /* Call ID type*/
73 #define OSP_CALLID_UNDEFINED    ((unsigned int)0)                       /* UNDEFINED */
74 #define OSP_CALLID_H323                 ((unsigned int)(1 << 0))        /* H.323 */
75 #define OSP_CALLID_SIP                  ((unsigned int)(1 << 1))        /* SIP */
76 #define OSP_CALLID_IAX                  ((unsigned int)(1 << 2))        /* IAX2 */
77 #define OSP_CALLID_MAXNUM               ((unsigned int)3)                       /* Max number of call ID type */
78
79 /* OSP Supported Destination Protocols */
80 #define OSP_PROT_H323                   ((char*)"H323")                         /* H323 Q931 protocol name*/
81 #define OSP_PROT_SIP                    ((char*)"SIP")                          /* SIP protocol name */
82 #define OSP_PROT_IAX                    ((char*)"IAX")                          /* IAX protocol name */
83 #define OSP_PROT_OTHER                  ((char*)"OTHER")                        /* Other protocol name */
84
85 /* OSP supported Destination Tech */
86 #if 0
87 #define OSP_TECH_H323                   ((char*)"OOH323")                       /* OOH323 tech name */
88 #endif
89 #define OSP_TECH_H323                   ((char*)"H323")                         /* OH323 tech name */
90 #define OSP_TECH_SIP                    ((char*)"SIP")                          /* SIP tech name */
91 #define OSP_TECH_IAX                    ((char*)"IAX2")                         /* IAX2 tech name */
92
93 /* SIP OSP header field name */
94 #define OSP_SIP_HEADER                  ((char*)"P-OSP-Auth-Token: ")
95
96 /* OSP Constants */
97 #define OSP_INVALID_HANDLE              ((int)-1)                                       /* Invalid OSP handle, provider, transaction etc. */
98 #define OSP_CONFIG_FILE                 ((const char*)"osp.conf")       /* OSP configuration file name */
99 #define OSP_GENERAL_CAT                 ((const char*)"general")        /* OSP global configuration context name */
100 #define OSP_DEF_PROVIDER                ((const char*)"default")        /* OSP default provider context name */
101 #define OSP_MAX_CERTS                   ((unsigned int)10)                      /* OSP max number of cacerts */
102 #define OSP_MAX_SRVS                    ((unsigned int)10)                      /* OSP max number of service points */
103 #define OSP_DEF_MAXCONNECTIONS  ((unsigned int)20)                      /* OSP default max_connections */
104 #define OSP_MIN_MAXCONNECTIONS  ((unsigned int)1)                       /* OSP min max_connections */
105 #define OSP_MAX_MAXCONNECTIONS  ((unsigned int)1000)            /* OSP max max_connections */
106 #define OSP_DEF_RETRYDELAY              ((unsigned int)0)                       /* OSP default retry delay */
107 #define OSP_MIN_RETRYDELAY              ((unsigned int)0)                       /* OSP min retry delay */
108 #define OSP_MAX_RETRYDELAY              ((unsigned int)10)                      /* OSP max retry delay */
109 #define OSP_DEF_RETRYLIMIT              ((unsigned int)2)                       /* OSP default retry times */
110 #define OSP_MIN_RETRYLIMIT              ((unsigned int)0)                       /* OSP min retry times */
111 #define OSP_MAX_RETRYLIMIT              ((unsigned int)100)                     /* OSP max retry times */
112 #define OSP_DEF_TIMEOUT                 ((unsigned int)500)                     /* OSP default timeout in ms */
113 #define OSP_MIN_TIMEOUT                 ((unsigned int)200)                     /* OSP min timeout in ms */
114 #define OSP_MAX_TIMEOUT                 ((unsigned int)10000)           /* OSP max timeout in ms */
115 #define OSP_DEF_AUTHPOLICY              ((enum osp_authpolicy)OSP_AUTH_YES)
116 #define OSP_AUDIT_URL                   ((const char*)"localhost")      /* OSP default Audit URL */
117 #define OSP_LOCAL_VALIDATION    ((int)1)                                        /* Validate OSP token locally */
118 #define OSP_SSL_LIFETIME                ((unsigned int)300)                     /* SSL life time, in seconds */
119 #define OSP_HTTP_PERSISTENCE    ((int)1)                                        /* In seconds */
120 #define OSP_CUSTOMER_ID                 ((const char*)"")                       /* OSP customer ID */
121 #define OSP_DEVICE_ID                   ((const char*)"")                       /* OSP device ID */
122 #define OSP_DEF_DESTINATIONS    ((unsigned int)5)                       /* OSP default max number of destinations */
123 #define OSP_DEF_TIMELIMIT               ((unsigned int)0)                       /* OSP default duration limit, no limit */
124 #define OSP_DEF_PROTOCOL                OSP_PROT_SIP                            /* OSP default destination protocol, SIP */
125
126 /* OSP Provider */
127 struct osp_provider {
128         char name[OSP_NORSTR_SIZE];                                             /* OSP provider context name */
129         char privatekey[OSP_NORSTR_SIZE];                               /* OSP private key file name */
130         char localcert[OSP_NORSTR_SIZE];                                /* OSP local cert file name */
131         unsigned int cacount;                                                   /* Number of cacerts */
132         char cacerts[OSP_MAX_CERTS][OSP_NORSTR_SIZE];   /* Cacert file names */
133         unsigned int spcount;                                                   /* Number of service points */
134         char srvpoints[OSP_MAX_SRVS][OSP_NORSTR_SIZE];  /* Service point URLs */
135         int maxconnections;                                                             /* Max number of connections */
136         int retrydelay;                                                                 /* Retry delay */
137         int retrylimit;                                                                 /* Retry limit */
138         int timeout;                                                                    /* Timeout in ms */
139         char source[OSP_NORSTR_SIZE];                                   /* IP of self */
140         enum osp_authpolicy authpolicy;                                 /* OSP authentication policy */
141         char* defaultprotocol;                                                  /* OSP default destination protocol */
142         OSPTPROVHANDLE handle;                                                  /* OSP provider handle */
143         struct osp_provider* next;                                              /* Pointer to next OSP provider */
144 };
145
146 /* Call ID */
147 struct osp_callid {
148         unsigned char buf[OSPC_CALLID_MAXSIZE];         /* Call ID string */
149         unsigned int len;                                       /* Call ID length */
150 };
151
152 /* OSP Application In/Output Results */
153 struct osp_result {
154         int inhandle;                                           /* Inbound transaction handle */
155         int outhandle;                                          /* Outbound transaction handle */
156         unsigned int intimelimit;                       /* Inbound duration limit */
157         unsigned int outtimelimit;                      /* Outbound duration limit */
158         char tech[OSP_TECHSTR_SIZE];            /* Outbound Asterisk TECH string */
159         char dest[OSP_NORSTR_SIZE];                     /* Outbound destination IP address */
160         char called[OSP_NORSTR_SIZE];           /* Outbound called number, may be translated */
161         char calling[OSP_NORSTR_SIZE];          /* Outbound calling number, may be translated */
162         char token[OSP_TOKSTR_SIZE];            /* Outbound OSP token */
163         char networkid[OSP_NORSTR_SIZE];        /* Outbound network ID */
164         unsigned int numresults;                        /* Number of remain outbound destinations */
165         struct osp_callid outcallid;            /* Outbound call ID */
166 };
167
168 /* OSP Module Global Variables */
169 AST_MUTEX_DEFINE_STATIC(osplock);                                                       /* Lock of OSP provider list */
170 static int osp_initialized = 0;                                                         /* Init flag */
171 static int osp_hardware = 0;                                                            /* Hardware accelleration flag */
172 static struct osp_provider* ospproviders = NULL;                        /* OSP provider list */
173 static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED;        /* Token format supported */
174
175 /* OSP Client Wrapper APIs */
176
177 /*!
178  * \brief Create OSP provider handle according to configuration
179  * \param cfg OSP configuration
180  * \param provider OSP provider context name
181  * \return 1 Success, 0 Failed, -1 Error
182  */
183 static int osp_create_provider(
184         struct ast_config* cfg,
185         const char* provider)
186 {
187         int res;
188         unsigned int t, i, j;
189         struct osp_provider* p;
190         struct ast_variable* v;
191         OSPTPRIVATEKEY privatekey;
192         OSPTCERT localcert;
193         const char* psrvpoints[OSP_MAX_SRVS];
194         OSPTCERT cacerts[OSP_MAX_CERTS];
195         const OSPTCERT* pcacerts[OSP_MAX_CERTS];
196         int error = OSPC_ERR_NO_ERROR;
197
198         if (!(p = ast_calloc(1, sizeof(*p)))) {
199                 ast_log(LOG_ERROR, "Out of memory\n");
200                 return -1;
201         }
202
203         ast_copy_string(p->name, provider, sizeof(p->name));
204         snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, provider);
205         snprintf(p->localcert, sizeof(p->localcert), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, provider);
206         p->maxconnections = OSP_DEF_MAXCONNECTIONS;
207         p->retrydelay = OSP_DEF_RETRYDELAY;
208         p->retrylimit = OSP_DEF_RETRYLIMIT;
209         p->timeout = OSP_DEF_TIMEOUT;
210         p->authpolicy = OSP_DEF_AUTHPOLICY;
211         p->defaultprotocol = OSP_DEF_PROTOCOL;
212         p->handle = OSP_INVALID_HANDLE;
213
214         v = ast_variable_browse(cfg, provider);
215         while(v) {
216                 if (!strcasecmp(v->name, "privatekey")) {
217                         if (v->value[0] == '/') {
218                                 ast_copy_string(p->privatekey, v->value, sizeof(p->privatekey));
219                         } else {
220                                 snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s", ast_config_AST_KEY_DIR, v->value);
221                         }
222                         ast_debug(1, "OSP: privatekey '%s'\n", p->privatekey);
223                 } else if (!strcasecmp(v->name, "localcert")) {
224                         if (v->value[0] == '/') {
225                                 ast_copy_string(p->localcert, v->value, sizeof(p->localcert));
226                         } else {
227                                 snprintf(p->localcert, sizeof(p->localcert), "%s/%s", ast_config_AST_KEY_DIR, v->value);
228                         }
229                         ast_debug(1, "OSP: localcert '%s'\n", p->localcert);
230                 } else if (!strcasecmp(v->name, "cacert")) {
231                         if (p->cacount < OSP_MAX_CERTS) {
232                                 if (v->value[0] == '/') {
233                                         ast_copy_string(p->cacerts[p->cacount], v->value, sizeof(p->cacerts[0]));
234                                 } else {
235                                         snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s", ast_config_AST_KEY_DIR, v->value);
236                                 }
237                                 ast_debug(1, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
238                                 p->cacount++;
239                         } else {
240                                 ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", v->lineno);
241                         }
242                 } else if (!strcasecmp(v->name, "servicepoint")) {
243                         if (p->spcount < OSP_MAX_SRVS) {
244                                 ast_copy_string(p->srvpoints[p->spcount], v->value, sizeof(p->srvpoints[0]));
245                                 ast_debug(1, "OSP: servicepoint[%d]: '%s'\n", p->spcount, p->srvpoints[p->spcount]);
246                                 p->spcount++;
247                         } else {
248                                 ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", v->lineno);
249                         }
250                 } else if (!strcasecmp(v->name, "maxconnections")) {
251                         if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_MAXCONNECTIONS) && (t <= OSP_MAX_MAXCONNECTIONS)) {
252                                 p->maxconnections = t;
253                                 ast_debug(1, "OSP: maxconnections '%d'\n", t);
254                         } else {
255                                 ast_log(LOG_WARNING, "OSP: maxconnections should be an integer from %d to %d, not '%s' at line %d\n",
256                                         OSP_MIN_MAXCONNECTIONS, OSP_MAX_MAXCONNECTIONS, v->value, v->lineno);
257                         }
258                 } else if (!strcasecmp(v->name, "retrydelay")) {
259                         if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_RETRYDELAY) && (t <= OSP_MAX_RETRYDELAY)) {
260                                 p->retrydelay = t;
261                                 ast_debug(1, "OSP: retrydelay '%d'\n", t);
262                         } else {
263                                 ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n",
264                                         OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY, v->value, v->lineno);
265                         }
266                 } else if (!strcasecmp(v->name, "retrylimit")) {
267                         if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_RETRYLIMIT) && (t <= OSP_MAX_RETRYLIMIT)) {
268                                 p->retrylimit = t;
269                                 ast_debug(1, "OSP: retrylimit '%d'\n", t);
270                         } else {
271                                 ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n",
272                                         OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT, v->value, v->lineno);
273                         }
274                 } else if (!strcasecmp(v->name, "timeout")) {
275                         if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_TIMEOUT) && (t <= OSP_MAX_TIMEOUT)) {
276                                 p->timeout = t;
277                                 ast_debug(1, "OSP: timeout '%d'\n", t);
278                         } else {
279                                 ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n",
280                                         OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT, v->value, v->lineno);
281                         }
282                 } else if (!strcasecmp(v->name, "source")) {
283                         ast_copy_string(p->source, v->value, sizeof(p->source));
284                         ast_debug(1, "OSP: source '%s'\n", p->source);
285                 } else if (!strcasecmp(v->name, "authpolicy")) {
286                         if ((sscanf(v->value, "%d", &t) == 1) && ((t == OSP_AUTH_NO) || (t == OSP_AUTH_YES) || (t == OSP_AUTH_EXCLUSIVE))) {
287                                 p->authpolicy = t;
288                                 ast_debug(1, "OSP: authpolicy '%d'\n", t);
289                         } else {
290                                 ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n",
291                                         OSP_AUTH_NO, OSP_AUTH_YES, OSP_AUTH_EXCLUSIVE, v->value, v->lineno);
292                         }
293                 } else if (!strcasecmp(v->name, "defaultprotocol")) {
294                         if (!strcasecmp(v->value, OSP_PROT_SIP)) {
295                                 p->defaultprotocol = OSP_PROT_SIP;
296                                 ast_debug(1, "OSP: default protocol '%s'\n", p->defaultprotocol);
297                         } else if (!strcasecmp(v->value, OSP_PROT_H323)) {
298                                 p->defaultprotocol = OSP_PROT_H323;
299                                 ast_debug(1, "OSP: default protocol '%s'\n", p->defaultprotocol);
300                         } else if (!strcasecmp(v->value, OSP_PROT_IAX)) {
301                                 p->defaultprotocol = OSP_PROT_IAX;
302                                 ast_debug(1, "OSP: default protocol '%s'\n", p->defaultprotocol);
303                         } else {
304                                 ast_log(LOG_WARNING, "OSP: default protocol should be %s, %s, %s, or %s not '%s' at line %d\n",
305                                         OSP_PROT_SIP, OSP_PROT_H323, OSP_PROT_IAX, OSP_PROT_OTHER, v->value, v->lineno);
306                         }
307                 }
308                 v = v->next;
309         }
310
311         error = OSPPUtilLoadPEMPrivateKey((unsigned char*)p->privatekey, &privatekey);
312         if (error != OSPC_ERR_NO_ERROR) {
313                 ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", p->privatekey, error);
314                 ast_free(p);
315                 return 0;
316         }
317
318         error = OSPPUtilLoadPEMCert((unsigned char*)p->localcert, &localcert);
319         if (error != OSPC_ERR_NO_ERROR) {
320                 ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", p->localcert, error);
321                 if (privatekey.PrivateKeyData) {
322                         ast_free(privatekey.PrivateKeyData);
323                 }
324                 ast_free(p);
325                 return 0;
326         }
327
328         if (p->cacount < 1) {
329                 snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s-cacert.pem", ast_config_AST_KEY_DIR, provider);
330                 ast_debug(1, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
331                 p->cacount++;
332         }
333         for (i = 0; i < p->cacount; i++) {
334                 error = OSPPUtilLoadPEMCert((unsigned char*)p->cacerts[i], &cacerts[i]);
335                 if (error != OSPC_ERR_NO_ERROR) {
336                         ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", p->cacerts[i], error);
337                         for (j = 0; j < i; j++) {
338                                 if (cacerts[j].CertData) {
339                                         ast_free(cacerts[j].CertData);
340                                 }
341                         }
342                         if (localcert.CertData) {
343                                 ast_free(localcert.CertData);
344                         }
345                         if (privatekey.PrivateKeyData) {
346                                 ast_free(privatekey.PrivateKeyData);
347                         }
348                         ast_free(p);
349                         return 0;
350                 }
351                 pcacerts[i] = &cacerts[i];
352         }
353
354         for (i = 0; i < p->spcount; i++) {
355                 psrvpoints[i] = p->srvpoints[i];
356         }
357
358         error = OSPPProviderNew(
359                                 p->spcount,
360                                 psrvpoints,
361                                 NULL,
362                                 OSP_AUDIT_URL,
363                                 &privatekey,
364                                 &localcert,
365                                 p->cacount,
366                                 pcacerts,
367                                 OSP_LOCAL_VALIDATION,
368                                 OSP_SSL_LIFETIME,
369                                 p->maxconnections,
370                                 OSP_HTTP_PERSISTENCE,
371                                 p->retrydelay,
372                                 p->retrylimit,
373                                 p->timeout,
374                                 OSP_CUSTOMER_ID,
375                                 OSP_DEVICE_ID,
376                                 &p->handle);
377         if (error != OSPC_ERR_NO_ERROR) {
378                 ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", provider, error);
379                 ast_free(p);
380                 res = -1;
381         } else {
382                 ast_debug(1, "OSP: provider '%s'\n", provider);
383                 ast_mutex_lock(&osplock);
384                 p->next = ospproviders;
385                 ospproviders = p;
386                 ast_mutex_unlock(&osplock);
387                 res = 1;
388         }
389
390         for (i = 0; i < p->cacount; i++) {
391                 if (cacerts[i].CertData) {
392                         ast_free(cacerts[i].CertData);
393                 }
394         }
395         if (localcert.CertData) {
396                 ast_free(localcert.CertData);
397         }
398         if (privatekey.PrivateKeyData) {
399                 ast_free(privatekey.PrivateKeyData);
400         }
401
402         return res;
403 }
404
405 /*!
406  * \brief Get OSP provider by name
407  * \param name OSP provider context name
408  * \param provider OSP provider structure
409  * \return 1 Success, 0 Failed, -1 Error
410  */
411 static int osp_get_provider(
412         const char* name,
413         struct osp_provider** provider)
414 {
415         int res = 0;
416         struct osp_provider* p;
417
418         ast_mutex_lock(&osplock);
419         p = ospproviders;
420         while(p) {
421                 if (!strcasecmp(p->name, name)) {
422                         *provider = p;
423                         ast_debug(1, "OSP: find provider '%s'\n", name);
424                         res = 1;
425                         break;
426                 }
427                 p = p->next;
428         }
429         ast_mutex_unlock(&osplock);
430
431         return res;
432 }
433
434 /*!
435  * \brief Create OSP transaction handle
436  * \param provider OSP provider context name
437  * \param transaction OSP transaction handle, output
438  * \param sourcesize Size of source buffer, in/output
439  * \param source Source of provider, output
440  * \return 1 Success, 0 Failed, -1 Error
441  */
442 static int osp_create_transaction(
443         const char* provider,
444         int* transaction,
445         unsigned int sourcesize,
446         char* source)
447 {
448         int res = 0;
449         struct osp_provider* p;
450         int error;
451
452         ast_mutex_lock(&osplock);
453         p = ospproviders;
454         while(p) {
455                 if (!strcasecmp(p->name, provider)) {
456                         error = OSPPTransactionNew(p->handle, transaction);
457                         if (error == OSPC_ERR_NO_ERROR) {
458                                 ast_debug(1, "OSP: transaction '%d'\n", *transaction);
459                                 ast_copy_string(source, p->source, sourcesize);
460                                 ast_debug(1, "OSP: source '%s'\n", source);
461                                 res = 1;
462                         } else {
463                                 *transaction = OSP_INVALID_HANDLE;
464                                 ast_debug(1, "OSP: Unable to create transaction handle, error '%d'\n", error);
465                                 res = -1;
466                         }
467                         break;
468                 }
469                 p = p->next;
470         }
471         ast_mutex_unlock(&osplock);
472
473         return res;
474 }
475
476 /*!
477  * \brief Convert address to "[x.x.x.x]" or "host.domain" format
478  * \param src Source address string
479  * \param dst Destination address string
480  * \param buffersize Size of dst buffer
481  */
482 static void osp_convert_address(
483         const char* src,
484         char* dst,
485         int buffersize)
486 {
487         struct in_addr inp;
488
489         if (inet_aton(src, &inp) != 0) {
490                 snprintf(dst, buffersize, "[%s]", src);
491         } else {
492                 snprintf(dst, buffersize, "%s", src);
493         }
494 }
495
496 /*!
497  * \brief Validate OSP token of inbound call
498  * \param transaction OSP transaction handle
499  * \param source Source of inbound call
500  * \param destination Destination of inbound call
501  * \param calling Calling number
502  * \param called Called number
503  * \param token OSP token, may be empty
504  * \param timelimit Call duration limit, output
505  * \return 1 Success, 0 Failed, -1 Error
506  */
507 static int osp_validate_token(
508         int transaction,
509         const char* source,
510         const char* destination,
511         const char* calling,
512         const char* called,
513         const char* token,
514         unsigned int* timelimit)
515 {
516         int res;
517         int tokenlen;
518         unsigned char tokenstr[OSP_TOKSTR_SIZE];
519         char src[OSP_NORSTR_SIZE];
520         char dst[OSP_NORSTR_SIZE];
521         unsigned int authorised;
522         unsigned int dummy = 0;
523         int error;
524
525         tokenlen = ast_base64decode(tokenstr, token, strlen(token));
526         osp_convert_address(source, src, sizeof(src));
527         osp_convert_address(destination, dst, sizeof(dst));
528         error = OSPPTransactionValidateAuthorisation(
529                                 transaction,
530                                 src,
531                                 dst,
532                                 NULL,
533                                 NULL,
534                                 calling ? calling : "",
535                                 OSPC_E164,
536                                 called,
537                                 OSPC_E164,
538                                 0,
539                                 NULL,
540                                 tokenlen,
541                                 (char*)tokenstr,
542                                 &authorised,
543                                 timelimit,
544                                 &dummy,
545                                 NULL,
546                                 osp_tokenformat);
547         if (error != OSPC_ERR_NO_ERROR) {
548                 ast_debug(1, "OSP: Unable to validate inbound token\n");
549                 res = -1;
550         } else if (authorised) {
551                 ast_debug(1, "OSP: Authorised\n");
552                 res = 1;
553         } else {
554                 ast_debug(1, "OSP: Unauthorised\n");
555                 res = 0;
556         }
557
558         return res;
559 }
560
561 /*!
562  * \brief Choose min duration limit
563  * \param in Inbound duration limit
564  * \param out Outbound duration limit
565  * \return min duration limit
566  */
567 static unsigned int osp_choose_timelimit(
568         unsigned int in,
569         unsigned int out)
570 {
571         if (in == OSP_DEF_TIMELIMIT) {
572                 return out;
573         } else if (out == OSP_DEF_TIMELIMIT) {
574                 return in;
575         } else {
576                 return in < out ? in : out;
577         }
578 }
579
580 /*!
581  * \brief Choose min duration limit
582  * \param provider OSP provider
583  * \param called Called number
584  * \param calling Calling number
585  * \param destination Destination IP in '[x.x.x.x]' format
586  * \param tokenlen OSP token length
587  * \param token OSP token
588  * \param reason Failure reason, output
589  * \param result OSP lookup results, in/output
590  * \return 1 Success, 0 Failed, -1 Error
591  */
592 static int osp_check_destination(
593         struct osp_provider* provider,
594         const char* called,
595         const char* calling,
596         char* destination,
597         unsigned int tokenlen,
598         const char* token,
599         enum OSPEFAILREASON* reason,
600         struct osp_result* result)
601 {
602         int res;
603         OSPE_DEST_OSP_ENABLED enabled;
604         OSPE_DEST_PROT protocol;
605         int error;
606
607         if (strlen(destination) <= 2) {
608                 ast_debug(1, "OSP: Wrong destination format '%s'\n", destination);
609                 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
610                 return -1;
611         }
612
613         if ((error = OSPPTransactionIsDestOSPEnabled(result->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) {
614                 ast_debug(1, "OSP: Unable to get destination OSP version, error '%d'\n", error);
615                 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
616                 return -1;
617         }
618
619         if (enabled == OSPE_OSP_FALSE) {
620                 result->token[0] = '\0';
621         } else {
622                 ast_base64encode(result->token, (const unsigned char*)token, tokenlen, sizeof(result->token) - 1);
623         }
624
625         if ((error = OSPPTransactionGetDestNetworkId(result->outhandle, result->networkid)) != OSPC_ERR_NO_ERROR) {
626                 ast_debug(1, "OSP: Unable to get destination network ID, error '%d'\n", error);
627                 result->networkid[0] = '\0';
628         }
629
630         if ((error = OSPPTransactionGetDestProtocol(result->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
631                 ast_debug(1, "OSP: Unable to get destination protocol, error '%d'\n", error);
632                 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
633                 result->token[0] = '\0';
634                 result->networkid[0] = '\0';
635                 return -1;
636         }
637
638         res = 1;
639         /* Strip leading and trailing brackets */
640         destination[strlen(destination) - 1] = '\0';
641         switch(protocol) {
642                 case OSPE_DEST_PROT_H323_SETUP:
643                         ast_debug(1, "OSP: protocol '%s'\n", OSP_PROT_H323);
644                         ast_copy_string(result->tech, OSP_TECH_H323, sizeof(result->tech));
645                         ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
646                         ast_copy_string(result->called, called, sizeof(result->called));
647                         ast_copy_string(result->calling, calling, sizeof(result->calling));
648                         break;
649                 case OSPE_DEST_PROT_SIP:
650                         ast_debug(1, "OSP: protocol '%s'\n", OSP_PROT_SIP);
651                         ast_copy_string(result->tech, OSP_TECH_SIP, sizeof(result->tech));
652                         ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
653                         ast_copy_string(result->called, called, sizeof(result->called));
654                         ast_copy_string(result->calling, calling, sizeof(result->calling));
655                         break;
656                 case OSPE_DEST_PROT_IAX:
657                         ast_debug(1, "OSP: protocol '%s'\n", OSP_PROT_IAX);
658                         ast_copy_string(result->tech, OSP_TECH_IAX, sizeof(result->tech));
659                         ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
660                         ast_copy_string(result->called, called, sizeof(result->called));
661                         ast_copy_string(result->calling, calling, sizeof(result->calling));
662                         break;
663                 case OSPE_DEST_PROT_UNDEFINED:
664                 case OSPE_DEST_PROT_UNKNOWN:
665                         ast_debug(1, "OSP: unknown/undefined protocol '%d'\n", protocol);
666                         ast_debug(1, "OSP: use default protocol '%s'\n", provider->defaultprotocol);
667
668                         ast_copy_string(result->tech, provider->defaultprotocol, sizeof(result->tech));
669                         ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
670                         ast_copy_string(result->called, called, sizeof(result->called));
671                         ast_copy_string(result->calling, calling, sizeof(result->calling));
672                         break;
673                 case OSPE_DEST_PROT_H323_LRQ:
674                 default:
675                         ast_log(LOG_WARNING, "OSP: unsupported protocol '%d'\n", protocol);
676                         *reason = OSPC_FAIL_PROTOCOL_ERROR;
677                         result->token[0] = '\0';
678                         result->networkid[0] = '\0';
679                         res = 0;
680                         break;
681         }
682
683         return res;
684 }
685
686 /*!
687  * \brief Convert Asterisk status to TC code
688  * \param cause Asterisk hangup cause
689  * \return OSP TC code
690  */
691 static enum OSPEFAILREASON asterisk2osp(
692         int cause)
693 {
694         return (enum OSPEFAILREASON)cause;
695 }
696
697 /*!
698  * \brief OSP Authentication function
699  * \param provider OSP provider context name
700  * \param transaction OSP transaction handle, output
701  * \param source Source of inbound call
702  * \param calling Calling number
703  * \param called Called number
704  * \param token OSP token, may be empty
705  * \param timelimit Call duration limit, output
706  * \return 1 Authenricated, 0 Unauthenticated, -1 Error
707  */
708 static int osp_auth(
709         const char* provider,
710         int* transaction,
711         const char* source,
712         const char* calling,
713         const char* called,
714         const char* token,
715         unsigned int* timelimit)
716 {
717         int res;
718         struct osp_provider* p;
719         char dest[OSP_NORSTR_SIZE];
720
721         *transaction = OSP_INVALID_HANDLE;
722         *timelimit = OSP_DEF_TIMELIMIT;
723
724         if ((res = osp_get_provider(provider, &p)) <= 0) {
725                 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", provider);
726                 return res;
727         }
728
729         switch (p->authpolicy) {
730                 case OSP_AUTH_NO:
731                         res = 1;
732                         break;
733                 case OSP_AUTH_EXCLUSIVE:
734                         if (ast_strlen_zero(token)) {
735                                 res = 0;
736                         } else if ((res = osp_create_transaction(provider, transaction, sizeof(dest), dest)) <= 0) {
737                                 ast_debug(1, "OSP: Unable to generate transaction handle\n");
738                                 *transaction = OSP_INVALID_HANDLE;
739                                 res = 0;
740                         } else if((res = osp_validate_token(*transaction, source, dest, calling, called, token, timelimit)) <= 0) {
741                                 OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
742                         }
743                         break;
744                 case OSP_AUTH_YES:
745                 default:
746                         if (ast_strlen_zero(token)) {
747                                 res = 1;
748                         } else if ((res = osp_create_transaction(provider, transaction, sizeof(dest), dest)) <= 0) {
749                                 ast_debug(1, "OSP: Unable to generate transaction handle\n");
750                                 *transaction = OSP_INVALID_HANDLE;
751                                 res = 0;
752                         } else if((res = osp_validate_token(*transaction, source, dest, calling, called, token, timelimit)) <= 0) {
753                                 OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
754                         }
755                         break;
756         }
757
758         return res;
759 }
760
761 /*!
762  * \brief Create a UUID
763  * \param uuid UUID buffer
764  * \param buffersize UUID buffer size
765  * \return 1 Created, -1 Error
766  */
767 static int osp_create_uuid(
768         unsigned char* uuid,
769         unsigned int* buffersize)
770 {
771         int i, res;
772         long int* tmp;
773
774         if (*buffersize >= OSP_UUID_SIZE) {
775                 tmp = (long int*)uuid;
776                 for (i = 0; i < OSP_UUID_SIZE / sizeof(long int); i++) {
777                         tmp[i] = ast_random();
778                 }
779                 *buffersize = OSP_UUID_SIZE;
780                 res = 1;
781         } else {
782                 res = -1;
783         }
784
785         return res;
786 }
787
788 /*!
789  * \brief UUID to string
790  * \param uuid UUID
791  * \param buffer String buffer
792  * \param buffersize String buffer size
793  * \return 1 Successed, -1 Error
794  */
795 static int osp_uuid2str(
796         unsigned char* uuid,
797         char* buffer,
798         unsigned int buffersize)
799 {
800         int res;
801
802         if (buffersize > OSP_UUIDSTR_SIZE) {
803                 snprintf(buffer, buffersize, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
804                         uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
805                         uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
806                 res = 1;
807         } else {
808                 res = -1;
809         }
810
811         return res;
812 }
813
814 /*!
815  * \brief Create a call ID according to the type
816  * \param type Call ID type
817  * \param callid Call ID buffer
818  * \return 1 Created, 0 Not create, -1 Error
819  */
820 static int osp_create_callid(
821         unsigned int type,
822         struct osp_callid* callid)
823 {
824         int res;
825
826         callid->len = sizeof(callid->buf);
827         switch (type) {
828                 case OSP_CALLID_H323:
829                         res = osp_create_uuid(callid->buf, &callid->len);
830                         break;
831                 case OSP_CALLID_SIP:
832                 case OSP_CALLID_IAX:
833                         res = 0;
834                 default:
835                         res = -1;
836                         break;
837         }
838
839         if ((res != 1) && (callid->len != 0)) {
840                 callid->buf[0] = '\0';
841                 callid->len = 0;
842         }
843
844         return res;
845 }
846
847 /*!
848  * \brief OSP Lookup function
849  * \param provider OSP provider context name
850  * \param srcdev Source device of outbound call
851  * \param calling Calling number
852  * \param called Called number
853  * \param callidtypes Call ID types
854  * \param result Lookup results
855  * \return 1 Found , 0 No route, -1 Error
856  */
857 static int osp_lookup(
858         const char* provider,
859         const char* srcdev,
860         const char* calling,
861         const char* called,
862         unsigned int callidtypes,
863         struct osp_result* result)
864 {
865         int res;
866         struct osp_provider* p;
867         char source[OSP_NORSTR_SIZE];
868         char callingnum[OSP_NORSTR_SIZE];
869         char callednum[OSP_NORSTR_SIZE];
870         char destination[OSP_NORSTR_SIZE];
871         unsigned int tokenlen;
872         char token[OSP_TOKSTR_SIZE];
873         char src[OSP_NORSTR_SIZE];
874         char dev[OSP_NORSTR_SIZE];
875         unsigned int i, type;
876         struct osp_callid callid;
877         unsigned int callidnum;
878         OSPTCALLID* callids[OSP_CALLID_MAXNUM];
879         unsigned int dummy = 0;
880         enum OSPEFAILREASON reason;
881         int error;
882
883         result->outhandle = OSP_INVALID_HANDLE;
884         result->tech[0] = '\0';
885         result->dest[0] = '\0';
886         result->called[0] = '\0';
887         result->calling[0] = '\0';
888         result->token[0] = '\0';
889         result->networkid[0] = '\0';
890         result->numresults = 0;
891         result->outtimelimit = OSP_DEF_TIMELIMIT;
892
893         if ((res = osp_get_provider(provider, &p)) <= 0) {
894                 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", provider);
895                 return res;
896         }
897
898         if ((res = osp_create_transaction(provider, &result->outhandle, sizeof(source), source)) <= 0) {
899                 ast_debug(1, "OSP: Unable to generate transaction handle\n");
900                 result->outhandle = OSP_INVALID_HANDLE;
901                 if (result->inhandle != OSP_INVALID_HANDLE) {
902                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
903                 }
904                 return -1;
905         }
906
907         callidnum = 0;
908         callids[0] = NULL;
909         for (i = 0; i < OSP_CALLID_MAXNUM; i++) {
910                 type = 1 << i;
911                 if (callidtypes & type) {
912                         error = osp_create_callid(type, &callid);
913                         if (error == 1) {
914                                 callids[callidnum] = OSPPCallIdNew(callid.len, callid.buf);
915                                 callidnum++;
916                         }
917                 }
918         }
919
920         osp_convert_address(source, src, sizeof(src));
921         osp_convert_address(srcdev, dev, sizeof(dev));
922         result->numresults = OSP_DEF_DESTINATIONS;
923         error = OSPPTransactionRequestAuthorisation(
924                                 result->outhandle,
925                                 src,
926                                 dev,
927                                 calling ? calling : "",
928                                 OSPC_E164,
929                                 called,
930                                 OSPC_E164,
931                                 NULL,
932                                 callidnum,
933                                 callids,
934                                 NULL,
935                                 &result->numresults,
936                                 &dummy,
937                                 NULL);
938
939         for (i = 0; i < callidnum; i++) {
940                 OSPPCallIdDelete(&callids[i]);
941         }
942
943         if (error != OSPC_ERR_NO_ERROR) {
944                 ast_debug(1, "OSP: Unable to request authorization\n");
945                 result->numresults = 0;
946                 if (result->inhandle != OSP_INVALID_HANDLE) {
947                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
948                 }
949                 return -1;
950         }
951
952         if (!result->numresults) {
953                 ast_debug(1, "OSP: No more destination\n");
954                 if (result->inhandle != OSP_INVALID_HANDLE) {
955                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
956                 }
957                 return 0;
958         }
959
960         result->outcallid.len = sizeof(result->outcallid.buf);
961         tokenlen = sizeof(token);
962         error = OSPPTransactionGetFirstDestination(
963                                 result->outhandle,
964                                 0,
965                                 NULL,
966                                 NULL,
967                                 &result->outtimelimit,
968                                 &result->outcallid.len,
969                                 result->outcallid.buf,
970                                 sizeof(callednum),
971                                 callednum,
972                                 sizeof(callingnum),
973                                 callingnum,
974                                 sizeof(destination),
975                                 destination,
976                                 0,
977                                 NULL,
978                                 &tokenlen,
979                                 token);
980         if (error != OSPC_ERR_NO_ERROR) {
981                 ast_debug(1, "OSP: Unable to get first route\n");
982                 result->numresults = 0;
983                 result->outtimelimit = OSP_DEF_TIMELIMIT;
984                 if (result->inhandle != OSP_INVALID_HANDLE) {
985                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
986                 }
987                 return -1;
988         }
989
990         result->numresults--;
991         result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
992         ast_debug(1, "OSP: outtimelimit '%d'\n", result->outtimelimit);
993         ast_debug(1, "OSP: called '%s'\n", callednum);
994         ast_debug(1, "OSP: calling '%s'\n", callingnum);
995         ast_debug(1, "OSP: destination '%s'\n", destination);
996         ast_debug(1, "OSP: token size '%d'\n", tokenlen);
997
998         if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
999                 return 1;
1000         }
1001
1002         if (!result->numresults) {
1003                 ast_debug(1, "OSP: No more destination\n");
1004                 result->outtimelimit = OSP_DEF_TIMELIMIT;
1005                 OSPPTransactionRecordFailure(result->outhandle, reason);
1006                 if (result->inhandle != OSP_INVALID_HANDLE) {
1007                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1008                 }
1009                 return 0;
1010         }
1011
1012         while(result->numresults) {
1013                 result->outcallid.len = sizeof(result->outcallid.buf);
1014                 tokenlen = sizeof(token);
1015                 error = OSPPTransactionGetNextDestination(
1016                                         result->outhandle,
1017                                         reason,
1018                                         0,
1019                                         NULL,
1020                                         NULL,
1021                                         &result->outtimelimit,
1022                                         &result->outcallid.len,
1023                                         result->outcallid.buf,
1024                                         sizeof(callednum),
1025                                         callednum,
1026                                         sizeof(callingnum),
1027                                         callingnum,
1028                                         sizeof(destination),
1029                                         destination,
1030                                         0,
1031                                         NULL,
1032                                         &tokenlen,
1033                                         token);
1034                 if (error == OSPC_ERR_NO_ERROR) {
1035                         result->numresults--;
1036                         result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
1037                         ast_debug(1, "OSP: outtimelimit '%d'\n", result->outtimelimit);
1038                         ast_debug(1, "OSP: called '%s'\n", callednum);
1039                         ast_debug(1, "OSP: calling '%s'\n", callingnum);
1040                         ast_debug(1, "OSP: destination '%s'\n", destination);
1041                         ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1042
1043                         if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
1044                                 break;
1045                         } else if (!result->numresults) {
1046                                 ast_debug(1, "OSP: No more destination\n");
1047                                 OSPPTransactionRecordFailure(result->outhandle, reason);
1048                                 if (result->inhandle != OSP_INVALID_HANDLE) {
1049                                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1050                                 }
1051                                 res = 0;
1052                                 break;
1053                         }
1054                 } else {
1055                         ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
1056                         result->numresults = 0;
1057                         result->outtimelimit = OSP_DEF_TIMELIMIT;
1058                         if (result->inhandle != OSP_INVALID_HANDLE) {
1059                                 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1060                         }
1061                         res = -1;
1062                         break;
1063                 }
1064         }
1065         return res;
1066 }
1067
1068 /*!
1069  * \brief OSP Lookup Next function
1070  * \param provider OSP provider name
1071  * \param cause Asterisk hangup cuase
1072  * \param result Lookup results, in/output
1073  * \return 1 Found , 0 No route, -1 Error
1074  */
1075 static int osp_next(
1076         const char* provider,
1077         int cause,
1078         struct osp_result* result)
1079 {
1080         int res;
1081         struct osp_provider* p;
1082         char callingnum[OSP_NORSTR_SIZE];
1083         char callednum[OSP_NORSTR_SIZE];
1084         char destination[OSP_NORSTR_SIZE];
1085         unsigned int tokenlen;
1086         char token[OSP_TOKSTR_SIZE];
1087         enum OSPEFAILREASON reason;
1088         int error;
1089
1090         result->tech[0] = '\0';
1091         result->dest[0] = '\0';
1092         result->called[0] = '\0';
1093         result->calling[0] = '\0';
1094         result->token[0] = '\0';
1095         result->networkid[0] = '\0';
1096         result->outtimelimit = OSP_DEF_TIMELIMIT;
1097
1098         if ((res = osp_get_provider(provider, &p)) <= 0) {
1099                 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", provider);
1100                 return res;
1101         }
1102
1103         if (result->outhandle == OSP_INVALID_HANDLE) {
1104                 ast_debug(1, "OSP: Transaction handle undefined\n");
1105                 result->numresults = 0;
1106                 if (result->inhandle != OSP_INVALID_HANDLE) {
1107                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1108                 }
1109                 return -1;
1110         }
1111
1112         reason = asterisk2osp(cause);
1113
1114         if (!result->numresults) {
1115                 ast_debug(1, "OSP: No more destination\n");
1116                 OSPPTransactionRecordFailure(result->outhandle, reason);
1117                 if (result->inhandle != OSP_INVALID_HANDLE) {
1118                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1119                 }
1120                 return 0;
1121         }
1122
1123         while(result->numresults) {
1124                 result->outcallid.len = sizeof(result->outcallid.buf);
1125                 tokenlen = sizeof(token);
1126                 error = OSPPTransactionGetNextDestination(
1127                                         result->outhandle,
1128                                         reason,
1129                                         0,
1130                                         NULL,
1131                                         NULL,
1132                                         &result->outtimelimit,
1133                                         &result->outcallid.len,
1134                                         result->outcallid.buf,
1135                                         sizeof(callednum),
1136                                         callednum,
1137                                         sizeof(callingnum),
1138                                         callingnum,
1139                                         sizeof(destination),
1140                                         destination,
1141                                         0,
1142                                         NULL,
1143                                         &tokenlen,
1144                                         token);
1145                 if (error == OSPC_ERR_NO_ERROR) {
1146                         result->numresults--;
1147                         result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
1148                         ast_debug(1, "OSP: outtimelimit '%d'\n", result->outtimelimit);
1149                         ast_debug(1, "OSP: called '%s'\n", callednum);
1150                         ast_debug(1, "OSP: calling '%s'\n", callingnum);
1151                         ast_debug(1, "OSP: destination '%s'\n", destination);
1152                         ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1153
1154                         if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
1155                                 res = 1;
1156                                 break;
1157                         } else if (!result->numresults) {
1158                                 ast_debug(1, "OSP: No more destination\n");
1159                                 OSPPTransactionRecordFailure(result->outhandle, reason);
1160                                 if (result->inhandle != OSP_INVALID_HANDLE) {
1161                                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1162                                 }
1163                                 res = 0;
1164                                 break;
1165                         }
1166                 } else {
1167                         ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
1168                         result->token[0] = '\0';
1169                         result->numresults = 0;
1170                         result->outtimelimit = OSP_DEF_TIMELIMIT;
1171                         if (result->inhandle != OSP_INVALID_HANDLE) {
1172                                 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1173                         }
1174                         res = -1;
1175                         break;
1176                 }
1177         }
1178
1179         return res;
1180 }
1181
1182 /*!
1183  * \brief OSP Finish function
1184  * \param handle OSP in/outbound transaction handle
1185  * \param recorded If failure reason has been recorded
1186  * \param cause Asterisk hangup cause
1187  * \param start Call start time
1188  * \param connect Call connect time
1189  * \param end Call end time
1190  * \param release Who release first, 0 source, 1 destination
1191  * \return 1 Success, 0 Failed, -1 Error
1192  */
1193 static int osp_finish(
1194         int handle,
1195         int recorded,
1196         int cause,
1197         time_t start,
1198         time_t connect,
1199         time_t end,
1200         unsigned int release)
1201 {
1202         int res;
1203         enum OSPEFAILREASON reason;
1204         time_t alert = 0;
1205         unsigned isPddInfoPresent = 0;
1206         unsigned pdd = 0;
1207         unsigned int dummy = 0;
1208         int error;
1209
1210         if (handle == OSP_INVALID_HANDLE) {
1211                 return 0;
1212         }
1213
1214         if (!recorded) {
1215                 reason = asterisk2osp(cause);
1216                 OSPPTransactionRecordFailure(handle, reason);
1217         }
1218
1219         error = OSPPTransactionReportUsage(
1220                                 handle,
1221                                 difftime(end, connect),
1222                                 start,
1223                                 end,
1224                                 alert,
1225                                 connect,
1226                                 isPddInfoPresent,
1227                                 pdd,
1228                                 release,
1229                                 (unsigned char*)"",
1230                                 0,
1231                                 0,
1232                                 0,
1233                                 0,
1234                                 &dummy,
1235                                 NULL);
1236         if (error == OSPC_ERR_NO_ERROR) {
1237                 ast_debug(1, "OSP: Usage reported\n");
1238                 res = 1;
1239         } else {
1240                 ast_debug(1, "OSP: Unable to report usage, error '%d'\n", error);
1241                 res = -1;
1242         }
1243         OSPPTransactionDelete(handle);
1244
1245         return res;
1246 }
1247
1248 /* OSP Application APIs */
1249
1250 /*!
1251  * \brief OSP Application OSPAuth
1252  * \param chan Channel
1253  * \param data Parameter
1254  * \return 0 Success, -1 Failed
1255  */
1256 static int ospauth_exec(
1257         struct ast_channel* chan,
1258         void* data)
1259 {
1260         int res;
1261         const char* provider = OSP_DEF_PROVIDER;
1262         struct varshead* headp;
1263         struct ast_var_t* current;
1264         const char* source = "";
1265         const char* token = "";
1266         int handle;
1267         unsigned int timelimit;
1268         char buffer[OSP_INTSTR_SIZE];
1269         const char* status;
1270         char* tmp;
1271
1272         AST_DECLARE_APP_ARGS(args,
1273                 AST_APP_ARG(provider);
1274                 AST_APP_ARG(options);
1275         );
1276
1277         if (!(tmp = ast_strdupa(data))) {
1278                 ast_log(LOG_ERROR, "Out of memory\n");
1279                 return -1;
1280         }
1281
1282         AST_STANDARD_APP_ARGS(args, tmp);
1283
1284         if (!ast_strlen_zero(args.provider)) {
1285                 provider = args.provider;
1286         }
1287         ast_debug(1, "OSPAuth: provider '%s'\n", provider);
1288
1289         headp = &chan->varshead;
1290         AST_LIST_TRAVERSE(headp, current, entries) {
1291                 if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
1292                         source = ast_var_value(current);
1293                 } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
1294                         token = ast_var_value(current);
1295                 }
1296         }
1297
1298         ast_debug(1, "OSPAuth: source '%s'\n", source);
1299         ast_debug(1, "OSPAuth: token size '%zd'\n", strlen(token));
1300
1301         if ((res = osp_auth(provider, &handle, source, chan->cid.cid_num, chan->exten, token, &timelimit)) > 0) {
1302                 status = AST_OSP_SUCCESS;
1303         } else {
1304                 timelimit = OSP_DEF_TIMELIMIT;
1305                 if (!res) {
1306                         status = AST_OSP_FAILED;
1307                 } else {
1308                         status = AST_OSP_ERROR;
1309                 }
1310         }
1311
1312         snprintf(buffer, sizeof(buffer), "%d", handle);
1313         pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
1314         ast_debug(1, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
1315         snprintf(buffer, sizeof(buffer), "%d", timelimit);
1316         pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
1317         ast_debug(1, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
1318         pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
1319         ast_debug(1, "OSPAuth: %s\n", status);
1320
1321         if(res <= 0) {
1322                 res = -1;
1323         } else {
1324                 res = 0;
1325         }
1326
1327         return res;
1328 }
1329
1330 /*!
1331  * \brief OSP Application OSPLookup
1332  * \param chan Channel
1333  * \param data Parameter
1334  * \return 0 Success, -1 Failed
1335  */
1336 static int osplookup_exec(
1337         struct ast_channel* chan,
1338         void* data)
1339 {
1340         int res, cres;
1341         const char* provider = OSP_DEF_PROVIDER;
1342         struct varshead* headp;
1343         struct ast_var_t* current;
1344         const char* srcdev = "";
1345         const char* netid = "";
1346         char buffer[OSP_TOKSTR_SIZE];
1347         unsigned int callidtypes = OSP_CALLID_UNDEFINED;
1348         struct osp_result result;
1349         const char* status;
1350         char* tmp;
1351
1352         AST_DECLARE_APP_ARGS(args,
1353                 AST_APP_ARG(exten);
1354                 AST_APP_ARG(provider);
1355                 AST_APP_ARG(options);
1356         );
1357
1358         if (ast_strlen_zero(data)) {
1359                 ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[|provider[|options]])\n");
1360                 return -1;
1361         }
1362
1363         if (!(tmp = ast_strdupa(data))) {
1364                 ast_log(LOG_ERROR, "Out of memory\n");
1365                 return -1;
1366         }
1367
1368         AST_STANDARD_APP_ARGS(args, tmp);
1369
1370         ast_debug(1, "OSPLookup: exten '%s'\n", args.exten);
1371
1372         if (!ast_strlen_zero(args.provider)) {
1373                 provider = args.provider;
1374         }
1375         ast_debug(1, "OSPlookup: provider '%s'\n", provider);
1376
1377         if (args.options) {
1378                 if (strchr(args.options, 'h')) {
1379                         callidtypes |= OSP_CALLID_H323;
1380                 }
1381                 if (strchr(args.options, 's')) {
1382                         callidtypes |= OSP_CALLID_SIP;
1383                 }
1384                 if (strchr(args.options, 'i')) {
1385                         callidtypes |= OSP_CALLID_IAX;
1386                 }
1387         }
1388         ast_debug(1, "OSPLookup: call id types '%d'\n", callidtypes);
1389
1390         result.inhandle = OSP_INVALID_HANDLE;
1391         result.intimelimit = OSP_DEF_TIMELIMIT;
1392
1393         headp = &chan->varshead;
1394         AST_LIST_TRAVERSE(headp, current, entries) {
1395                 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
1396                         if (sscanf(ast_var_value(current), "%d", &result.inhandle) != 1) {
1397                                 result.inhandle = OSP_INVALID_HANDLE;
1398                         }
1399                 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
1400                         if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) {
1401                                 result.intimelimit = OSP_DEF_TIMELIMIT;
1402                         }
1403                 } else if (!strcasecmp(ast_var_name(current), "OSPINNETWORKID")) {
1404                         netid = ast_var_value(current);
1405                 } else if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
1406                         srcdev = ast_var_value(current);
1407                 }
1408         }
1409         ast_debug(1, "OSPLookup: OSPINHANDLE '%d'\n", result.inhandle);
1410         ast_debug(1, "OSPLookup: OSPINTIMELIMIT '%d'\n", result.intimelimit);
1411         ast_debug(1, "OSPLookup: OSPINNETWORKID '%s'\n", netid);
1412         ast_debug(1, "OSPLookup: source device '%s'\n", srcdev);
1413
1414         if ((cres = ast_autoservice_start(chan)) < 0) {
1415                 return -1;
1416         }
1417
1418         if ((res = osp_lookup(provider, srcdev, chan->cid.cid_num, args.exten, callidtypes, &result)) > 0) {
1419                 status = AST_OSP_SUCCESS;
1420         } else {
1421                 result.tech[0] = '\0';
1422                 result.dest[0] = '\0';
1423                 result.called[0] = '\0';
1424                 result.calling[0] = '\0';
1425                 result.token[0] = '\0';
1426                 result.networkid[0] = '\0';
1427                 result.numresults = 0;
1428                 result.outtimelimit = OSP_DEF_TIMELIMIT;
1429                 result.outcallid.buf[0] = '\0';
1430                 result.outcallid.len = 0;
1431                 if (!res) {
1432                         status = AST_OSP_FAILED;
1433                 } else {
1434                         status = AST_OSP_ERROR;
1435                 }
1436         }
1437
1438         snprintf(buffer, sizeof(buffer), "%d", result.outhandle);
1439         pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
1440         ast_debug(1, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
1441         pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
1442         ast_debug(1, "OSPLookup: OSPTECH '%s'\n", result.tech);
1443         pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
1444         ast_debug(1, "OSPLookup: OSPDEST '%s'\n", result.dest);
1445         pbx_builtin_setvar_helper(chan, "OSPCALLED", result.called);
1446         ast_debug(1, "OSPLookup: OSPCALLED '%s'\n", result.called);
1447         pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
1448         ast_debug(1, "OSPLookup: OSPCALLING '%s'\n", result.calling);
1449         pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
1450         ast_debug(1, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
1451         snprintf(buffer, sizeof(buffer), "%d", result.numresults);
1452         pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
1453         ast_debug(1, "OSPLookup: OSPRESULTS '%s'\n", buffer);
1454         snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
1455         pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
1456         ast_debug(1, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
1457         snprintf(buffer, sizeof(buffer), "%d", callidtypes);
1458         pbx_builtin_setvar_helper(chan, "OSPOUTCALLIDTYPES", buffer);
1459         ast_debug(1, "OSPLookup: OSPOUTCALLIDTYPES '%s'\n", buffer);
1460         pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
1461         ast_debug(1, "OSPLookup: %s\n", status);
1462
1463         if (!strcasecmp(result.tech, OSP_TECH_H323)) {
1464                 if ((callidtypes & OSP_CALLID_H323) && (result.outcallid.len != 0)) {
1465                         osp_uuid2str(result.outcallid.buf, buffer, sizeof(buffer));
1466                 } else {
1467                         buffer[0] = '\0';
1468                 }
1469                 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
1470                 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
1471                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1472         } else if (!strcasecmp(result.tech, OSP_TECH_SIP)) {
1473                 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
1474                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1475                 if (!ast_strlen_zero(result.token)) {
1476                         snprintf(buffer, sizeof(buffer), "%s%s", OSP_SIP_HEADER, result.token);
1477                         pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
1478                         ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
1479                 }
1480         } else if (!strcasecmp(result.tech, OSP_TECH_IAX)) {
1481                 snprintf(buffer, sizeof(buffer), "%s/%s/%s", result.tech, result.dest, result.called);
1482                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1483         }
1484
1485         if ((cres = ast_autoservice_stop(chan)) < 0) {
1486                 return -1;
1487         }
1488
1489         if(res <= 0) {
1490                 res = -1;
1491         } else {
1492                 res = 0;
1493         }
1494
1495         return res;
1496 }
1497
1498 /*!
1499  * \brief OSP Application OSPNext
1500  * \param chan Channel
1501  * \param data Parameter
1502  * \return 0 Success, -1 Failed
1503  */
1504 static int ospnext_exec(
1505         struct ast_channel* chan,
1506         void* data)
1507 {
1508         int res;
1509         const char* provider = OSP_DEF_PROVIDER;
1510         int cause = 0;
1511         struct varshead* headp;
1512         struct ast_var_t* current;
1513         struct osp_result result;
1514         char buffer[OSP_TOKSTR_SIZE];
1515         unsigned int callidtypes = OSP_CALLID_UNDEFINED;
1516         const char* status;
1517         char* tmp;
1518
1519         AST_DECLARE_APP_ARGS(args,
1520                 AST_APP_ARG(cause);
1521                 AST_APP_ARG(provider);
1522                 AST_APP_ARG(options);
1523         );
1524
1525         if (ast_strlen_zero(data)) {
1526                 ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[|provider[|options]])\n");
1527                 return -1;
1528         }
1529
1530         if (!(tmp = ast_strdupa(data))) {
1531                 ast_log(LOG_ERROR, "Out of memory\n");
1532                 return -1;
1533         }
1534
1535         AST_STANDARD_APP_ARGS(args, tmp);
1536
1537         if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%d", &cause) != 1) {
1538                 cause = 0;
1539         }
1540         ast_debug(1, "OSPNext: cause '%d'\n", cause);
1541
1542         if (!ast_strlen_zero(args.provider)) {
1543                 provider = args.provider;
1544         }
1545         ast_debug(1, "OSPlookup: provider '%s'\n", provider);
1546
1547         result.inhandle = OSP_INVALID_HANDLE;
1548         result.outhandle = OSP_INVALID_HANDLE;
1549         result.intimelimit = OSP_DEF_TIMELIMIT;
1550         result.numresults = 0;
1551
1552         headp = &chan->varshead;
1553         AST_LIST_TRAVERSE(headp, current, entries) {
1554                 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
1555                         if (sscanf(ast_var_value(current), "%d", &result.inhandle) != 1) {
1556                                 result.inhandle = OSP_INVALID_HANDLE;
1557                         }
1558                 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
1559                         if (sscanf(ast_var_value(current), "%d", &result.outhandle) != 1) {
1560                                 result.outhandle = OSP_INVALID_HANDLE;
1561                         }
1562                 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
1563                         if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) {
1564                                 result.intimelimit = OSP_DEF_TIMELIMIT;
1565                         }
1566                 } else if (!strcasecmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) {
1567                         if (sscanf(ast_var_value(current), "%d", &callidtypes) != 1) {
1568                                 callidtypes = OSP_CALLID_UNDEFINED;
1569                         }
1570                 } else if (!strcasecmp(ast_var_name(current), "OSPRESULTS")) {
1571                         if (sscanf(ast_var_value(current), "%d", &result.numresults) != 1) {
1572                                 result.numresults = 0;
1573                         }
1574                 }
1575         }
1576         ast_debug(1, "OSPNext: OSPINHANDLE '%d'\n", result.inhandle);
1577         ast_debug(1, "OSPNext: OSPOUTHANDLE '%d'\n", result.outhandle);
1578         ast_debug(1, "OSPNext: OSPINTIMELIMIT '%d'\n", result.intimelimit);
1579         ast_debug(1, "OSPNext: OSPOUTCALLIDTYPES '%d'\n", callidtypes);
1580         ast_debug(1, "OSPNext: OSPRESULTS '%d'\n", result.numresults);
1581
1582         if ((res = osp_next(provider, cause, &result)) > 0) {
1583                 status = AST_OSP_SUCCESS;
1584         } else {
1585                 result.tech[0] = '\0';
1586                 result.dest[0] = '\0';
1587                 result.called[0] = '\0';
1588                 result.calling[0] = '\0';
1589                 result.token[0] = '\0';
1590                 result.networkid[0] = '\0';
1591                 result.numresults = 0;
1592                 result.outtimelimit = OSP_DEF_TIMELIMIT;
1593                 result.outcallid.buf[0] = '\0';
1594                 result.outcallid.len = 0;
1595                 if (!res) {
1596                         status = AST_OSP_FAILED;
1597                 } else {
1598                         status = AST_OSP_ERROR;
1599                 }
1600         }
1601
1602         pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
1603         ast_debug(1, "OSPNext: OSPTECH '%s'\n", result.tech);
1604         pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
1605         ast_debug(1, "OSPNext: OSPDEST '%s'\n", result.dest);
1606         pbx_builtin_setvar_helper(chan, "OSPCALLED", result.called);
1607         ast_debug(1, "OSPNext: OSPCALLED'%s'\n", result.called);
1608         pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
1609         ast_debug(1, "OSPNext: OSPCALLING '%s'\n", result.calling);
1610         pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
1611         ast_debug(1, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
1612         snprintf(buffer, sizeof(buffer), "%d", result.numresults);
1613         pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
1614         ast_debug(1, "OSPNext: OSPRESULTS '%s'\n", buffer);
1615         snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
1616         pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
1617         ast_debug(1, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
1618         pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
1619         ast_debug(1, "OSPNext: %s\n", status);
1620
1621         if (!strcasecmp(result.tech, OSP_TECH_H323)) {
1622                 if ((callidtypes & OSP_CALLID_H323) && (result.outcallid.len != 0)) {
1623                         osp_uuid2str(result.outcallid.buf, buffer, sizeof(buffer));
1624                 } else {
1625                         buffer[0] = '\0';
1626                 }
1627                 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
1628                 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
1629                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1630         } else if (!strcasecmp(result.tech, OSP_TECH_SIP)) {
1631                 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
1632                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1633                 if (!ast_strlen_zero(result.token)) {
1634                         snprintf(buffer, sizeof(buffer), "%s%s", OSP_SIP_HEADER, result.token);
1635                         pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
1636                         ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
1637                 }
1638         } else if (!strcasecmp(result.tech, OSP_TECH_IAX)) {
1639                 snprintf(buffer, sizeof(buffer), "%s/%s/%s", result.tech, result.dest, result.called);
1640                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1641         }
1642
1643         if(res <= 0) {
1644                 res = -1;
1645         } else {
1646                 res = 0;
1647         }
1648
1649         return res;
1650 }
1651
1652 /*!
1653  * \brief OSP Application OSPFinish
1654  * \param chan Channel
1655  * \param data Parameter
1656  * \return 0 Success, -1 Failed
1657  */
1658 static int ospfinished_exec(
1659         struct ast_channel* chan,
1660         void* data)
1661 {
1662         int res = 1;
1663         int cause = 0;
1664         struct varshead* headp;
1665         struct ast_var_t* current;
1666         int inhandle = OSP_INVALID_HANDLE;
1667         int outhandle = OSP_INVALID_HANDLE;
1668         int recorded = 0;
1669         time_t start, connect, end;
1670         unsigned int release;
1671         char buffer[OSP_INTSTR_SIZE];
1672         const char* status;
1673         char* tmp;
1674
1675         AST_DECLARE_APP_ARGS(args,
1676                 AST_APP_ARG(cause);
1677                 AST_APP_ARG(options);
1678         );
1679
1680         if (!(tmp = ast_strdupa(data))) {
1681                 ast_log(LOG_ERROR, "Out of memory\n");
1682                 return -1;
1683         }
1684
1685         AST_STANDARD_APP_ARGS(args, tmp);
1686
1687         headp = &chan->varshead;
1688         AST_LIST_TRAVERSE(headp, current, entries) {
1689                 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
1690                         if (sscanf(ast_var_value(current), "%d", &inhandle) != 1) {
1691                                 inhandle = OSP_INVALID_HANDLE;
1692                         }
1693                 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
1694                         if (sscanf(ast_var_value(current), "%d", &outhandle) != 1) {
1695                                 outhandle = OSP_INVALID_HANDLE;
1696                         }
1697                 } else if (!recorded &&
1698                         (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") ||
1699                         !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") ||
1700                         !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS")))
1701                 {
1702                         if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) {
1703                                 recorded = 1;
1704                         }
1705                 }
1706         }
1707         ast_debug(1, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
1708         ast_debug(1, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
1709         ast_debug(1, "OSPFinish: recorded '%d'\n", recorded);
1710
1711         if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%d", &cause) != 1) {
1712                 cause = 0;
1713         }
1714         ast_debug(1, "OSPFinish: cause '%d'\n", cause);
1715
1716         if (chan->cdr) {
1717                 start = chan->cdr->start.tv_sec;
1718                 connect = chan->cdr->answer.tv_sec;
1719                 if (connect) {
1720                         end = time(NULL);
1721                 } else {
1722                         end = connect;
1723                 }
1724         } else {
1725                 start = 0;
1726                 connect = 0;
1727                 end = 0;
1728         }
1729         ast_debug(1, "OSPFinish: start '%ld'\n", start);
1730         ast_debug(1, "OSPFinish: connect '%ld'\n", connect);
1731         ast_debug(1, "OSPFinish: end '%ld'\n", end);
1732
1733         release = ast_check_hangup(chan) ? 0 : 1;
1734
1735         if (osp_finish(outhandle, recorded, cause, start, connect, end, release) <= 0) {
1736                 ast_debug(1, "OSPFinish: Unable to report usage for outbound call\n");
1737         }
1738         switch (cause) {
1739                 case AST_CAUSE_NORMAL_CLEARING:
1740                         break;
1741                 default:
1742                         cause = AST_CAUSE_NO_ROUTE_DESTINATION;
1743                         break;
1744         }
1745         if (osp_finish(inhandle, recorded, cause, start, connect, end, release) <= 0) {
1746                 ast_debug(1, "OSPFinish: Unable to report usage for inbound call\n");
1747         }
1748         snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
1749         pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
1750         pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
1751
1752         if (res > 0) {
1753                 status = AST_OSP_SUCCESS;
1754         } else if (!res) {
1755                 status = AST_OSP_FAILED;
1756         } else {
1757                 status = AST_OSP_ERROR;
1758         }
1759         pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
1760
1761         if(!res) {
1762                 res = -1;
1763         } else {
1764                 res = 0;
1765         }
1766
1767         return res;
1768 }
1769
1770 /* OSP Module APIs */
1771
1772 static int osp_unload(void);
1773 static int osp_load(int reload)
1774 {
1775         const char* t;
1776         unsigned int v;
1777         struct ast_config* cfg;
1778         struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1779         int error = OSPC_ERR_NO_ERROR;
1780
1781         if ((cfg = ast_config_load(OSP_CONFIG_FILE, config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
1782                 return 0;
1783
1784         if (cfg) {
1785                 if (reload)
1786                         osp_unload();
1787
1788                 t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate");
1789                 if (t && ast_true(t)) {
1790                         if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
1791                                 ast_log(LOG_WARNING, "OSP: Unable to enable hardware accelleration\n");
1792                                 OSPPInit(0);
1793                         } else {
1794                                 osp_hardware = 1;
1795                         }
1796                 } else {
1797                         OSPPInit(0);
1798                 }
1799                 ast_debug(1, "OSP: osp_hardware '%d'\n", osp_hardware);
1800
1801                 t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat");
1802                 if (t) {
1803                         if ((sscanf(t, "%d", &v) == 1) &&
1804                                 ((v == TOKEN_ALGO_SIGNED) || (v == TOKEN_ALGO_UNSIGNED) || (v == TOKEN_ALGO_BOTH)))
1805                         {
1806                                 osp_tokenformat = v;
1807                         } else {
1808                                 ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n",
1809                                         TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, t);
1810                         }
1811                 }
1812                 ast_debug(1, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
1813
1814                 t = ast_category_browse(cfg, NULL);
1815                 while(t) {
1816                         if (strcasecmp(t, OSP_GENERAL_CAT)) {
1817                                 osp_create_provider(cfg, t);
1818                         }
1819                         t = ast_category_browse(cfg, t);
1820                 }
1821
1822                 osp_initialized = 1;
1823
1824                 ast_config_destroy(cfg);
1825         } else {
1826                 ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
1827                 return 0;
1828         }
1829         ast_debug(1, "OSP: osp_initialized '%d'\n", osp_initialized);
1830
1831         return 1;
1832 }
1833
1834 static int osp_unload(void)
1835 {
1836         struct osp_provider* p;
1837         struct osp_provider* next;
1838
1839         if (osp_initialized) {
1840                 ast_mutex_lock(&osplock);
1841                 p = ospproviders;
1842                 while(p) {
1843                         next = p->next;
1844                         OSPPProviderDelete(p->handle, 0);
1845                         ast_free(p);
1846                         p = next;
1847                 }
1848                 ospproviders = NULL;
1849                 ast_mutex_unlock(&osplock);
1850
1851                 OSPPCleanup();
1852
1853                 osp_tokenformat = TOKEN_ALGO_SIGNED;
1854                 osp_hardware = 0;
1855                 osp_initialized = 0;
1856         }
1857         return 0;
1858 }
1859
1860 static char *handle_cli_osp_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1861 {
1862         int i;
1863         int found = 0;
1864         struct osp_provider* p;
1865         const char* provider = NULL;
1866         const char* tokenalgo;
1867
1868         switch (cmd) {
1869         case CLI_INIT:
1870                 e->command = "osp show";
1871                 e->usage =
1872                         "Usage: osp show\n"
1873                         "       Displays information on Open Settlement Protocol support\n";
1874                 return NULL;
1875         case CLI_GENERATE:
1876                 return NULL;
1877         }
1878
1879         if ((a->argc < 2) || (a->argc > 3))
1880                 return CLI_SHOWUSAGE;
1881         if (a->argc > 2) 
1882                 provider = a->argv[2];
1883         if (!provider) {
1884                 switch (osp_tokenformat) {
1885                         case TOKEN_ALGO_BOTH:
1886                                 tokenalgo = "Both";
1887                                 break;
1888                         case TOKEN_ALGO_UNSIGNED:
1889                                 tokenalgo = "Unsigned";
1890                                 break;
1891                         case TOKEN_ALGO_SIGNED:
1892                         default:
1893                                 tokenalgo = "Signed";
1894                                 break;
1895                 }
1896                 ast_cli(a->fd, "OSP: %s %s %s\n",
1897                         osp_initialized ? "Initialized" : "Uninitialized", osp_hardware ? "Accelerated" : "Normal", tokenalgo);
1898         }
1899
1900         ast_mutex_lock(&osplock);
1901         p = ospproviders;
1902         while(p) {
1903                 if (!provider || !strcasecmp(p->name, provider)) {
1904                         if (found) {
1905                                 ast_cli(a->fd, "\n");
1906                         }
1907                         ast_cli(a->fd, " == OSP Provider '%s' == \n", p->name);
1908                         ast_cli(a->fd, "Local Private Key: %s\n", p->privatekey);
1909                         ast_cli(a->fd, "Local Certificate: %s\n", p->localcert);
1910                         for (i = 0; i < p->cacount; i++) {
1911                                 ast_cli(a->fd, "CA Certificate %d:  %s\n", i + 1, p->cacerts[i]);
1912                         }
1913                         for (i = 0; i < p->spcount; i++) {
1914                                 ast_cli(a->fd, "Service Point %d:   %s\n", i + 1, p->srvpoints[i]);
1915                         }
1916                         ast_cli(a->fd, "Max Connections:   %d\n", p->maxconnections);
1917                         ast_cli(a->fd, "Retry Delay:       %d seconds\n", p->retrydelay);
1918                         ast_cli(a->fd, "Retry Limit:       %d\n", p->retrylimit);
1919                         ast_cli(a->fd, "Timeout:           %d milliseconds\n", p->timeout);
1920                         ast_cli(a->fd, "Source:            %s\n", strlen(p->source) ? p->source : "<unspecified>");
1921                         ast_cli(a->fd, "Auth Policy        %d\n", p->authpolicy);
1922                         ast_cli(a->fd, "Default protocol   %s\n", p->defaultprotocol);
1923                         ast_cli(a->fd, "OSP Handle:        %d\n", p->handle);
1924                         found++;
1925                 }
1926                 p = p->next;
1927         }
1928         ast_mutex_unlock(&osplock);
1929
1930         if (!found) {
1931                 if (provider) {
1932                         ast_cli(a->fd, "Unable to find OSP provider '%s'\n", provider);
1933                 } else {
1934                         ast_cli(a->fd, "No OSP providers configured\n");
1935                 }       
1936         }
1937         return CLI_SUCCESS;
1938 }
1939
1940 static const char* app1= "OSPAuth";
1941 static const char* synopsis1 = "OSP authentication";
1942 static const char* descrip1 =
1943 "  OSPAuth([provider[|options]]):  Authenticate a SIP INVITE by OSP and sets\n"
1944 "the variables:\n"
1945 " ${OSPINHANDLE}:  The inbound call transaction handle\n"
1946 " ${OSPINTIMELIMIT}:  The inbound call duration limit in seconds\n"
1947 "\n"
1948 "This application sets the following channel variable upon completion:\n"
1949 "       OSPAUTHSTATUS   The status of the OSP Auth attempt as a text string, one of\n"
1950 "               SUCCESS | FAILED | ERROR\n";
1951
1952 static const char* app2= "OSPLookup";
1953 static const char* synopsis2 = "Lookup destination by OSP";
1954 static const char* descrip2 =
1955 "  OSPLookup(exten[|provider[|options]]):  Looks up an extension via OSP and sets\n"
1956 "the variables, where 'n' is the number of the result beginning with 1:\n"
1957 " ${OSPOUTHANDLE}:  The OSP Handle for anything remaining\n"
1958 " ${OSPTECH}:  The technology to use for the call\n"
1959 " ${OSPDEST}:  The destination to use for the call\n"
1960 " ${OSPCALLED}:  The called number to use for the call\n"
1961 " ${OSPCALLING}:  The calling number to use for the call\n"
1962 " ${OSPDIALSTR}:  The dial command string\n"
1963 " ${OSPOUTTOKEN}:  The actual OSP token as a string\n"
1964 " ${OSPOUTTIMELIMIT}:  The outbound call duration limit in seconds\n"
1965 " ${OSPOUTCALLIDTYPES}:  The outbound call id types\n"
1966 " ${OSPOUTCALLID}:  The outbound call id\n"
1967 " ${OSPRESULTS}:  The number of OSP results total remaining\n"
1968 "\n"
1969 "The option string may contain the following character:\n"
1970 "       'h' -- generate H323 call id for the outbound call\n"
1971 "       's' -- generate SIP call id for the outbound call. Have not been implemented\n"
1972 "       'i' -- generate IAX call id for the outbound call. Have not been implemented\n"
1973 "This application sets the following channel variable upon completion:\n"
1974 "       OSPLOOKUPSTATUS The status of the OSP Lookup attempt as a text string, one of\n"
1975 "               SUCCESS | FAILED | ERROR\n";
1976
1977 static const char* app3 = "OSPNext";
1978 static const char* synopsis3 = "Lookup next destination by OSP";
1979 static const char* descrip3 =
1980 "  OSPNext(cause[|provider[|options]]):  Looks up the next OSP Destination for ${OSPOUTHANDLE}\n"
1981 "See OSPLookup for more information\n"
1982 "\n"
1983 "This application sets the following channel variable upon completion:\n"
1984 "       OSPNEXTSTATUS The status of the OSP Next attempt as a text string, one of\n"
1985 "               SUCCESS | FAILED | ERROR\n";
1986
1987 static const char* app4 = "OSPFinish";
1988 static const char* synopsis4 = "Record OSP entry";
1989 static const char* descrip4 =
1990 "  OSPFinish([status[|options]]):  Records call state for ${OSPINHANDLE}, according to\n"
1991 "status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or CHANUNAVAIL\n"
1992 "or coincidentally, just what the Dial application stores in its ${DIALSTATUS}.\n"
1993 "\n"
1994 "This application sets the following channel variable upon completion:\n"
1995 "       OSPFINISHSTATUS The status of the OSP Finish attempt as a text string, one of\n"
1996 "               SUCCESS | FAILED | ERROR \n";
1997
1998 static struct ast_cli_entry cli_osp[] = {
1999         AST_CLI_DEFINE(handle_cli_osp_show, "Displays OSF information")
2000 };
2001
2002 static int load_module(void)
2003 {
2004         int res;
2005
2006         if (!osp_load(0))
2007                 return AST_MODULE_LOAD_DECLINE;
2008
2009         ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
2010         res = ast_register_application(app1, ospauth_exec, synopsis1, descrip1);
2011         res |= ast_register_application(app2, osplookup_exec, synopsis2, descrip2);
2012         res |= ast_register_application(app3, ospnext_exec, synopsis3, descrip3);
2013         res |= ast_register_application(app4, ospfinished_exec, synopsis4, descrip4);
2014
2015         return res;
2016 }
2017
2018 static int unload_module(void)
2019 {
2020         int res;
2021
2022         res = ast_unregister_application(app4);
2023         res |= ast_unregister_application(app3);
2024         res |= ast_unregister_application(app2);
2025         res |= ast_unregister_application(app1);
2026         ast_cli_unregister_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
2027         osp_unload();
2028
2029         return res;
2030 }
2031
2032 static int reload(void)
2033 {
2034         osp_load(1);
2035
2036         return 0;
2037 }
2038
2039 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
2040         .load = load_module,
2041         .unload = unload_module,
2042         .reload = reload,
2043         );