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