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