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