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