2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
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.
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.
21 * \brief Open Settlement Protocol (OSP) Applications
23 * \author Mark Spencer <markster@digium.com>
25 * \ingroup applications
29 <depend>osptk</depend>
35 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
37 #include <sys/types.h>
43 #include <osp/osputils.h>
45 #include "asterisk/lock.h"
46 #include "asterisk/config.h"
47 #include "asterisk/utils.h"
48 #include "asterisk/causes.h"
49 #include "asterisk/channel.h"
50 #include "asterisk/app.h"
51 #include "asterisk/module.h"
52 #include "asterisk/pbx.h"
53 #include "asterisk/options.h"
54 #include "asterisk/cli.h"
55 #include "asterisk/logger.h"
56 #include "asterisk/astosp.h"
58 /* OSP Buffer Sizes */
59 #define OSP_INTSTR_SIZE ((unsigned int)16) /* OSP signed/unsigned int string buffer size */
60 #define OSP_NORSTR_SIZE ((unsigned int)256) /* OSP normal string buffer size */
61 #define OSP_TOKSTR_SIZE ((unsigned int)4096) /* OSP token string buffer size */
62 #define OSP_TECHSTR_SIZE ((unsigned int)32) /* OSP signed/unsigned int string buffer size */
63 #define OSP_UUID_SIZE ((unsigned int)16) /* UUID size */
64 #define OSP_UUIDSTR_SIZE ((unsigned int)36) /* UUID string size */
66 /* OSP Authentication Policy */
68 OSP_AUTH_NO, /* Accept any call */
69 OSP_AUTH_YES, /* Accept call with valid OSP token or without OSP token */
70 OSP_AUTH_EXCLUSIVE /* Only accept call with valid OSP token */
74 #define OSP_CALLID_UNDEFINED ((unsigned int)0) /* UNDEFINED */
75 #define OSP_CALLID_H323 ((unsigned int)(1 << 0)) /* H.323 */
76 #define OSP_CALLID_SIP ((unsigned int)(1 << 1)) /* SIP */
77 #define OSP_CALLID_IAX ((unsigned int)(1 << 2)) /* IAX2 */
78 #define OSP_CALLID_MAXNUM ((unsigned int)3) /* Max number of call ID type */
80 /* OSP Supported Destination Protocols */
81 #define OSP_PROT_H323 ((char*)"H323") /* H323 Q931 protocol name*/
82 #define OSP_PROT_SIP ((char*)"SIP") /* SIP protocol name */
83 #define OSP_PROT_IAX ((char*)"IAX") /* IAX protocol name */
84 #define OSP_PROT_OTHER ((char*)"OTHER") /* Other protocol name */
86 /* OSP supported Destination Tech */
88 #define OSP_TECH_H323 ((char*)"OOH323") /* OOH323 tech name */
90 #define OSP_TECH_H323 ((char*)"H323") /* OH323 tech name */
91 #define OSP_TECH_SIP ((char*)"SIP") /* SIP tech name */
92 #define OSP_TECH_IAX ((char*)"IAX2") /* IAX2 tech name */
94 /* SIP OSP header field name */
95 #define OSP_SIP_HEADER ((char*)"P-OSP-Auth-Token: ")
98 #define OSP_INVALID_HANDLE ((int)-1) /* Invalid OSP handle, provider, transaction etc. */
99 #define OSP_CONFIG_FILE ((const char*)"osp.conf") /* OSP configuration file name */
100 #define OSP_GENERAL_CAT ((const char*)"general") /* OSP global configuration context name */
101 #define OSP_DEF_PROVIDER ((const char*)"default") /* OSP default provider context name */
102 #define OSP_MAX_CERTS ((unsigned int)10) /* OSP max number of cacerts */
103 #define OSP_MAX_SRVS ((unsigned int)10) /* OSP max number of service points */
104 #define OSP_DEF_MAXCONNECTIONS ((unsigned int)20) /* OSP default max_connections */
105 #define OSP_MIN_MAXCONNECTIONS ((unsigned int)1) /* OSP min max_connections */
106 #define OSP_MAX_MAXCONNECTIONS ((unsigned int)1000) /* OSP max max_connections */
107 #define OSP_DEF_RETRYDELAY ((unsigned int)0) /* OSP default retry delay */
108 #define OSP_MIN_RETRYDELAY ((unsigned int)0) /* OSP min retry delay */
109 #define OSP_MAX_RETRYDELAY ((unsigned int)10) /* OSP max retry delay */
110 #define OSP_DEF_RETRYLIMIT ((unsigned int)2) /* OSP default retry times */
111 #define OSP_MIN_RETRYLIMIT ((unsigned int)0) /* OSP min retry times */
112 #define OSP_MAX_RETRYLIMIT ((unsigned int)100) /* OSP max retry times */
113 #define OSP_DEF_TIMEOUT ((unsigned int)500) /* OSP default timeout in ms */
114 #define OSP_MIN_TIMEOUT ((unsigned int)200) /* OSP min timeout in ms */
115 #define OSP_MAX_TIMEOUT ((unsigned int)10000) /* OSP max timeout in ms */
116 #define OSP_DEF_AUTHPOLICY ((enum osp_authpolicy)OSP_AUTH_YES)
117 #define OSP_AUDIT_URL ((const char*)"localhost") /* OSP default Audit URL */
118 #define OSP_LOCAL_VALIDATION ((int)1) /* Validate OSP token locally */
119 #define OSP_SSL_LIFETIME ((unsigned int)300) /* SSL life time, in seconds */
120 #define OSP_HTTP_PERSISTENCE ((int)1) /* In seconds */
121 #define OSP_CUSTOMER_ID ((const char*)"") /* OSP customer ID */
122 #define OSP_DEVICE_ID ((const char*)"") /* OSP device ID */
123 #define OSP_DEF_DESTINATIONS ((unsigned int)5) /* OSP default max number of destinations */
124 #define OSP_DEF_TIMELIMIT ((unsigned int)0) /* OSP default duration limit, no limit */
125 #define OSP_DEF_PROTOCOL OSP_PROT_SIP /* OSP default destination protocol, SIP */
128 struct osp_provider {
129 char name[OSP_NORSTR_SIZE]; /* OSP provider context name */
130 char privatekey[OSP_NORSTR_SIZE]; /* OSP private key file name */
131 char localcert[OSP_NORSTR_SIZE]; /* OSP local cert file name */
132 unsigned int cacount; /* Number of cacerts */
133 char cacerts[OSP_MAX_CERTS][OSP_NORSTR_SIZE]; /* Cacert file names */
134 unsigned int spcount; /* Number of service points */
135 char srvpoints[OSP_MAX_SRVS][OSP_NORSTR_SIZE]; /* Service point URLs */
136 int maxconnections; /* Max number of connections */
137 int retrydelay; /* Retry delay */
138 int retrylimit; /* Retry limit */
139 int timeout; /* Timeout in ms */
140 char source[OSP_NORSTR_SIZE]; /* IP of self */
141 enum osp_authpolicy authpolicy; /* OSP authentication policy */
142 char* defaultprotocol; /* OSP default destination protocol */
143 OSPTPROVHANDLE handle; /* OSP provider handle */
144 struct osp_provider* next; /* Pointer to next OSP provider */
149 char buf[OSPC_CALLID_MAXSIZE]; /* Call ID string */
150 unsigned int len; /* Call ID length */
153 /* OSP Application In/Output Results */
155 int inhandle; /* Inbound transaction handle */
156 int outhandle; /* Outbound transaction handle */
157 unsigned int intimelimit; /* Inbound duration limit */
158 unsigned int outtimelimit; /* Outbound duration limit */
159 char tech[OSP_TECHSTR_SIZE]; /* Outbound Asterisk TECH string */
160 char dest[OSP_NORSTR_SIZE]; /* Outbound destination IP address */
161 char called[OSP_NORSTR_SIZE]; /* Outbound called number, may be translated */
162 char calling[OSP_NORSTR_SIZE]; /* Outbound calling number, may be translated */
163 char token[OSP_TOKSTR_SIZE]; /* Outbound OSP token */
164 char networkid[OSP_NORSTR_SIZE]; /* Outbound network ID */
165 unsigned int numresults; /* Number of remain outbound destinations */
166 struct osp_callid outcallid; /* Outbound call ID */
169 /* OSP Module Global Variables */
170 AST_MUTEX_DEFINE_STATIC(osplock); /* Lock of OSP provider list */
171 static int osp_initialized = 0; /* Init flag */
172 static int osp_hardware = 0; /* Hardware accelleration flag */
173 static struct osp_provider* ospproviders = NULL; /* OSP provider list */
174 static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED; /* Token format supported */
176 /* OSP Client Wrapper APIs */
179 * \brief Create OSP provider handle according to configuration
180 * \param cfg OSP configuration
181 * \param provider OSP provider context name
182 * \return 1 Success, 0 Failed, -1 Error
184 static int osp_create_provider(
185 struct ast_config* cfg,
186 const char* provider)
189 unsigned int t, i, j;
190 struct osp_provider* p;
191 struct ast_variable* v;
192 OSPTPRIVATEKEY privatekey;
194 const char* psrvpoints[OSP_MAX_SRVS];
195 OSPTCERT cacerts[OSP_MAX_CERTS];
196 const OSPTCERT* pcacerts[OSP_MAX_CERTS];
197 int error = OSPC_ERR_NO_ERROR;
199 if (!(p = ast_calloc(1, sizeof(*p)))) {
200 ast_log(LOG_ERROR, "Out of memory\n");
204 ast_copy_string(p->name, provider, sizeof(p->name));
205 snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, provider);
206 snprintf(p->localcert, sizeof(p->localcert), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, provider);
207 p->maxconnections = OSP_DEF_MAXCONNECTIONS;
208 p->retrydelay = OSP_DEF_RETRYDELAY;
209 p->retrylimit = OSP_DEF_RETRYLIMIT;
210 p->timeout = OSP_DEF_TIMEOUT;
211 p->authpolicy = OSP_DEF_AUTHPOLICY;
212 p->defaultprotocol = OSP_DEF_PROTOCOL;
213 p->handle = OSP_INVALID_HANDLE;
215 v = ast_variable_browse(cfg, provider);
217 if (!strcasecmp(v->name, "privatekey")) {
218 if (v->value[0] == '/') {
219 ast_copy_string(p->privatekey, v->value, sizeof(p->privatekey));
221 snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s", ast_config_AST_KEY_DIR, v->value);
224 ast_log(LOG_DEBUG, "OSP: privatekey '%s'\n", p->privatekey);
225 } else if (!strcasecmp(v->name, "localcert")) {
226 if (v->value[0] == '/') {
227 ast_copy_string(p->localcert, v->value, sizeof(p->localcert));
229 snprintf(p->localcert, sizeof(p->localcert), "%s/%s", ast_config_AST_KEY_DIR, v->value);
232 ast_log(LOG_DEBUG, "OSP: localcert '%s'\n", p->localcert);
233 } else if (!strcasecmp(v->name, "cacert")) {
234 if (p->cacount < OSP_MAX_CERTS) {
235 if (v->value[0] == '/') {
236 ast_copy_string(p->cacerts[p->cacount], v->value, sizeof(p->cacerts[0]));
238 snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s", ast_config_AST_KEY_DIR, v->value);
241 ast_log(LOG_DEBUG, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
244 ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", v->lineno);
246 } else if (!strcasecmp(v->name, "servicepoint")) {
247 if (p->spcount < OSP_MAX_SRVS) {
248 ast_copy_string(p->srvpoints[p->spcount], v->value, sizeof(p->srvpoints[0]));
250 ast_log(LOG_DEBUG, "OSP: servicepoint[%d]: '%s'\n", p->spcount, p->srvpoints[p->spcount]);
253 ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", v->lineno);
255 } else if (!strcasecmp(v->name, "maxconnections")) {
256 if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_MAXCONNECTIONS) && (t <= OSP_MAX_MAXCONNECTIONS)) {
257 p->maxconnections = t;
259 ast_log(LOG_DEBUG, "OSP: maxconnections '%d'\n", t);
261 ast_log(LOG_WARNING, "OSP: maxconnections should be an integer from %d to %d, not '%s' at line %d\n",
262 OSP_MIN_MAXCONNECTIONS, OSP_MAX_MAXCONNECTIONS, v->value, v->lineno);
264 } else if (!strcasecmp(v->name, "retrydelay")) {
265 if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_RETRYDELAY) && (t <= OSP_MAX_RETRYDELAY)) {
268 ast_log(LOG_DEBUG, "OSP: retrydelay '%d'\n", t);
270 ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n",
271 OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY, v->value, v->lineno);
273 } else if (!strcasecmp(v->name, "retrylimit")) {
274 if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_RETRYLIMIT) && (t <= OSP_MAX_RETRYLIMIT)) {
277 ast_log(LOG_DEBUG, "OSP: retrylimit '%d'\n", t);
279 ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n",
280 OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT, v->value, v->lineno);
282 } else if (!strcasecmp(v->name, "timeout")) {
283 if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_TIMEOUT) && (t <= OSP_MAX_TIMEOUT)) {
286 ast_log(LOG_DEBUG, "OSP: timeout '%d'\n", t);
288 ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n",
289 OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT, v->value, v->lineno);
291 } else if (!strcasecmp(v->name, "source")) {
292 ast_copy_string(p->source, v->value, sizeof(p->source));
294 ast_log(LOG_DEBUG, "OSP: source '%s'\n", p->source);
295 } else if (!strcasecmp(v->name, "authpolicy")) {
296 if ((sscanf(v->value, "%d", &t) == 1) && ((t == OSP_AUTH_NO) || (t == OSP_AUTH_YES) || (t == OSP_AUTH_EXCLUSIVE))) {
299 ast_log(LOG_DEBUG, "OSP: authpolicy '%d'\n", t);
301 ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n",
302 OSP_AUTH_NO, OSP_AUTH_YES, OSP_AUTH_EXCLUSIVE, v->value, v->lineno);
304 } else if (!strcasecmp(v->name, "defaultprotocol")) {
305 if (!strcasecmp(v->value, OSP_PROT_SIP)) {
306 p->defaultprotocol = OSP_PROT_SIP;
308 ast_log(LOG_DEBUG, "OSP: default protocol '%s'\n", p->defaultprotocol);
309 } else if (!strcasecmp(v->value, OSP_PROT_H323)) {
310 p->defaultprotocol = OSP_PROT_H323;
312 ast_log(LOG_DEBUG, "OSP: default protocol '%s'\n", p->defaultprotocol);
313 } else if (!strcasecmp(v->value, OSP_PROT_IAX)) {
314 p->defaultprotocol = OSP_PROT_IAX;
316 ast_log(LOG_DEBUG, "OSP: default protocol '%s'\n", p->defaultprotocol);
318 ast_log(LOG_WARNING, "OSP: default protocol should be %s, %s, %s, or %s not '%s' at line %d\n",
319 OSP_PROT_SIP, OSP_PROT_H323, OSP_PROT_IAX, OSP_PROT_OTHER, v->value, v->lineno);
325 error = OSPPUtilLoadPEMPrivateKey((unsigned char*)p->privatekey, &privatekey);
326 if (error != OSPC_ERR_NO_ERROR) {
327 ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", p->privatekey, error);
332 error = OSPPUtilLoadPEMCert((unsigned char*)p->localcert, &localcert);
333 if (error != OSPC_ERR_NO_ERROR) {
334 ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", p->localcert, error);
335 if (privatekey.PrivateKeyData) {
336 free(privatekey.PrivateKeyData);
342 if (p->cacount < 1) {
343 snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s-cacert.pem", ast_config_AST_KEY_DIR, provider);
345 ast_log(LOG_DEBUG, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
348 for (i = 0; i < p->cacount; i++) {
349 error = OSPPUtilLoadPEMCert((unsigned char*)p->cacerts[i], &cacerts[i]);
350 if (error != OSPC_ERR_NO_ERROR) {
351 ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", p->cacerts[i], error);
352 for (j = 0; j < i; j++) {
353 if (cacerts[j].CertData) {
354 free(cacerts[j].CertData);
357 if (localcert.CertData) {
358 free(localcert.CertData);
360 if (privatekey.PrivateKeyData) {
361 free(privatekey.PrivateKeyData);
366 pcacerts[i] = &cacerts[i];
369 for (i = 0; i < p->spcount; i++) {
370 psrvpoints[i] = p->srvpoints[i];
373 error = OSPPProviderNew(
382 OSP_LOCAL_VALIDATION,
385 OSP_HTTP_PERSISTENCE,
392 if (error != OSPC_ERR_NO_ERROR) {
393 ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", provider, error);
398 ast_log(LOG_DEBUG, "OSP: provider '%s'\n", provider);
399 ast_mutex_lock(&osplock);
400 p->next = ospproviders;
402 ast_mutex_unlock(&osplock);
406 for (i = 0; i < p->cacount; i++) {
407 if (cacerts[i].CertData) {
408 free(cacerts[i].CertData);
411 if (localcert.CertData) {
412 free(localcert.CertData);
414 if (privatekey.PrivateKeyData) {
415 free(privatekey.PrivateKeyData);
422 * \brief Get OSP provider by name
423 * \param name OSP provider context name
424 * \param provider OSP provider structure
425 * \return 1 Success, 0 Failed, -1 Error
427 static int osp_get_provider(
429 struct osp_provider** provider)
432 struct osp_provider* p;
434 ast_mutex_lock(&osplock);
437 if (!strcasecmp(p->name, name)) {
440 ast_log(LOG_DEBUG, "OSP: find provider '%s'\n", name);
446 ast_mutex_unlock(&osplock);
452 * \brief Create OSP transaction handle
453 * \param provider OSP provider context name
454 * \param transaction OSP transaction handle, output
455 * \param sourcesize Size of source buffer, in/output
456 * \param source Source of provider, output
457 * \return 1 Success, 0 Failed, -1 Error
459 static int osp_create_transaction(
460 const char* provider,
462 unsigned int sourcesize,
466 struct osp_provider* p;
469 ast_mutex_lock(&osplock);
472 if (!strcasecmp(p->name, provider)) {
473 error = OSPPTransactionNew(p->handle, transaction);
474 if (error == OSPC_ERR_NO_ERROR) {
476 ast_log(LOG_DEBUG, "OSP: transaction '%d'\n", *transaction);
477 ast_copy_string(source, p->source, sourcesize);
479 ast_log(LOG_DEBUG, "OSP: source '%s'\n", source);
482 *transaction = OSP_INVALID_HANDLE;
484 ast_log(LOG_DEBUG, "OSP: Unable to create transaction handle, error '%d'\n", error);
491 ast_mutex_unlock(&osplock);
497 * \brief Convert address to "[x.x.x.x]" or "host.domain" format
498 * \param src Source address string
499 * \param dst Destination address string
500 * \param buffersize Size of dst buffer
502 static void osp_convert_address(
509 if (inet_aton(src, &inp) != 0) {
510 snprintf(dst, buffersize, "[%s]", src);
512 snprintf(dst, buffersize, "%s", src);
517 * \brief Validate OSP token of inbound call
518 * \param transaction OSP transaction handle
519 * \param source Source of inbound call
520 * \param destination Destination of inbound call
521 * \param calling Calling number
522 * \param called Called number
523 * \param token OSP token, may be empty
524 * \param timelimit Call duration limit, output
525 * \return 1 Success, 0 Failed, -1 Error
527 static int osp_validate_token(
530 const char* destination,
534 unsigned int* timelimit)
538 unsigned char tokenstr[OSP_TOKSTR_SIZE];
539 char src[OSP_TOKSTR_SIZE];
540 char dst[OSP_TOKSTR_SIZE];
541 unsigned int authorised;
542 unsigned int dummy = 0;
545 tokenlen = ast_base64decode(tokenstr, token, strlen(token));
546 osp_convert_address(source, src, sizeof(src));
547 osp_convert_address(destination, dst, sizeof(dst));
548 error = OSPPTransactionValidateAuthorisation(
554 calling ? calling : "",
567 if (error != OSPC_ERR_NO_ERROR) {
569 ast_log(LOG_DEBUG, "OSP: Unable to validate inbound token\n");
571 } else if (authorised) {
573 ast_log(LOG_DEBUG, "OSP: Authorised\n");
577 ast_log(LOG_DEBUG, "OSP: Unauthorised\n");
585 * \brief Choose min duration limit
586 * \param in Inbound duration limit
587 * \param out Outbound duration limit
588 * \return min duration limit
590 static unsigned int osp_choose_timelimit(
594 if (in == OSP_DEF_TIMELIMIT) {
596 } else if (out == OSP_DEF_TIMELIMIT) {
599 return in < out ? in : out;
604 * \brief Choose min duration limit
605 * \param provider OSP provider
606 * \param called Called number
607 * \param calling Calling number
608 * \param destination Destination IP in '[x.x.x.x]' format
609 * \param tokenlen OSP token length
610 * \param token OSP token
611 * \param reason Failure reason, output
612 * \param result OSP lookup results, in/output
613 * \return 1 Success, 0 Failed, -1 Error
615 static int osp_check_destination(
616 struct osp_provider* provider,
620 unsigned int tokenlen,
622 enum OSPEFAILREASON* reason,
623 struct osp_result* result)
626 OSPE_DEST_OSP_ENABLED enabled;
627 OSPE_DEST_PROT protocol;
630 if (strlen(destination) <= 2) {
632 ast_log(LOG_DEBUG, "OSP: Wrong destination format '%s'\n", destination);
633 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
637 if ((error = OSPPTransactionIsDestOSPEnabled(result->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) {
639 ast_log(LOG_DEBUG, "OSP: Unable to get destination OSP version, error '%d'\n", error);
640 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
644 if (enabled == OSPE_OSP_FALSE) {
645 result->token[0] = '\0';
647 ast_base64encode(result->token, (const unsigned char*)token, tokenlen, sizeof(result->token) - 1);
650 if ((error = OSPPTransactionGetDestNetworkId(result->outhandle, result->networkid)) != OSPC_ERR_NO_ERROR) {
652 ast_log(LOG_DEBUG, "OSP: Unable to get destination network ID, error '%d'\n", error);
653 result->networkid[0] = '\0';
656 if ((error = OSPPTransactionGetDestProtocol(result->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
658 ast_log(LOG_DEBUG, "OSP: Unable to get destination protocol, error '%d'\n", error);
659 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
660 result->token[0] = '\0';
661 result->networkid[0] = '\0';
666 /* Strip leading and trailing brackets */
667 destination[strlen(destination) - 1] = '\0';
669 case OSPE_DEST_PROT_H323_SETUP:
671 ast_log(LOG_DEBUG, "OSP: protocol '%s'\n", OSP_PROT_H323);
672 ast_copy_string(result->tech, OSP_TECH_H323, sizeof(result->tech));
673 ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
674 ast_copy_string(result->called, called, sizeof(result->called));
675 ast_copy_string(result->calling, calling, sizeof(result->calling));
677 case OSPE_DEST_PROT_SIP:
679 ast_log(LOG_DEBUG, "OSP: protocol '%s'\n", OSP_PROT_SIP);
680 ast_copy_string(result->tech, OSP_TECH_SIP, sizeof(result->tech));
681 ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
682 ast_copy_string(result->called, called, sizeof(result->called));
683 ast_copy_string(result->calling, calling, sizeof(result->calling));
685 case OSPE_DEST_PROT_IAX:
687 ast_log(LOG_DEBUG, "OSP: protocol '%s'\n", OSP_PROT_IAX);
688 ast_copy_string(result->tech, OSP_TECH_IAX, sizeof(result->tech));
689 ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
690 ast_copy_string(result->called, called, sizeof(result->called));
691 ast_copy_string(result->calling, calling, sizeof(result->calling));
693 case OSPE_DEST_PROT_UNDEFINED:
694 case OSPE_DEST_PROT_UNKNOWN:
696 ast_log(LOG_DEBUG, "OSP: unknown/undefined protocol '%d'\n", protocol);
697 ast_log(LOG_DEBUG, "OSP: use default protocol '%s'\n", provider->defaultprotocol);
699 ast_copy_string(result->tech, provider->defaultprotocol, sizeof(result->tech));
700 ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
701 ast_copy_string(result->called, called, sizeof(result->called));
702 ast_copy_string(result->calling, calling, sizeof(result->calling));
704 case OSPE_DEST_PROT_H323_LRQ:
706 ast_log(LOG_WARNING, "OSP: unsupported protocol '%d'\n", protocol);
707 *reason = OSPC_FAIL_PROTOCOL_ERROR;
708 result->token[0] = '\0';
709 result->networkid[0] = '\0';
718 * \brief Convert Asterisk status to TC code
719 * \param cause Asterisk hangup cause
720 * \return OSP TC code
722 static enum OSPEFAILREASON asterisk2osp(
725 return (enum OSPEFAILREASON)cause;
729 * \brief OSP Authentication function
730 * \param provider OSP provider context name
731 * \param transaction OSP transaction handle, output
732 * \param source Source of inbound call
733 * \param calling Calling number
734 * \param called Called number
735 * \param token OSP token, may be empty
736 * \param timelimit Call duration limit, output
737 * \return 1 Authenricated, 0 Unauthenticated, -1 Error
740 const char* provider,
746 unsigned int* timelimit)
749 struct osp_provider* p;
750 char dest[OSP_NORSTR_SIZE];
752 *transaction = OSP_INVALID_HANDLE;
753 *timelimit = OSP_DEF_TIMELIMIT;
755 if ((res = osp_get_provider(provider, &p)) <= 0) {
757 ast_log(LOG_DEBUG, "OSP: Unabe to find OSP provider '%s'\n", provider);
761 switch (p->authpolicy) {
765 case OSP_AUTH_EXCLUSIVE:
766 if (ast_strlen_zero(token)) {
768 } else if ((res = osp_create_transaction(provider, transaction, sizeof(dest), dest)) <= 0) {
770 ast_log(LOG_DEBUG, "OSP: Unable to generate transaction handle\n");
771 *transaction = OSP_INVALID_HANDLE;
773 } else if((res = osp_validate_token(*transaction, source, dest, calling, called, token, timelimit)) <= 0) {
774 OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
779 if (ast_strlen_zero(token)) {
781 } else if ((res = osp_create_transaction(provider, transaction, sizeof(dest), dest)) <= 0) {
783 ast_log(LOG_DEBUG, "OSP: Unable to generate transaction handle\n");
784 *transaction = OSP_INVALID_HANDLE;
786 } else if((res = osp_validate_token(*transaction, source, dest, calling, called, token, timelimit)) <= 0) {
787 OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
796 * \brief Create a UUID
797 * \param uuid UUID buffer
798 * \param buffersize UUID buffer size
799 * \return 1 Created, -1 Error
801 static int osp_create_uuid(
803 unsigned int* buffersize)
808 if (*buffersize >= OSP_UUID_SIZE) {
809 tmp = (long int*)uuid;
810 for (i = 0; i < OSP_UUID_SIZE / sizeof(long int); i++) {
811 tmp[i] = ast_random();
813 *buffersize = OSP_UUID_SIZE;
823 * \brief UUID to string
825 * \param buffer String buffer
826 * \param buffersize String buffer size
827 * \return 1 Successed, -1 Error
829 static int osp_uuid2str(
832 unsigned int buffersize)
836 if (buffersize > OSP_UUIDSTR_SIZE) {
837 snprintf(buffer, buffersize, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
838 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
839 uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
849 * \brief Create a call ID according to the type
850 * \param type Call ID type
851 * \param callid Call ID buffer
852 * \return 1 Created, 0 Not create, -1 Error
854 static int osp_create_callid(
856 struct osp_callid* callid)
860 callid->len = sizeof(callid->buf);
862 case OSP_CALLID_H323:
863 res = osp_create_uuid(callid->buf, &callid->len);
873 if ((res != 1) && (callid->len != 0)) {
874 callid->buf[0] = '\0';
882 * \brief OSP Lookup function
883 * \param provider OSP provider context name
884 * \param srcdev Source device of outbound call
885 * \param calling Calling number
886 * \param called Called number
887 * \param callidtypes Call ID types
888 * \param result Lookup results
889 * \return 1 Found , 0 No route, -1 Error
891 static int osp_lookup(
892 const char* provider,
896 unsigned int callidtypes,
897 struct osp_result* result)
900 struct osp_provider* p;
901 char source[OSP_NORSTR_SIZE];
902 char callingnum[OSP_NORSTR_SIZE];
903 char callednum[OSP_NORSTR_SIZE];
904 char destination[OSP_NORSTR_SIZE];
905 unsigned int tokenlen;
906 char token[OSP_TOKSTR_SIZE];
907 char src[OSP_NORSTR_SIZE];
908 char dev[OSP_NORSTR_SIZE];
909 unsigned int i, type;
910 struct osp_callid callid;
911 unsigned int callidnum;
912 OSPTCALLID* callids[OSP_CALLID_MAXNUM];
913 unsigned int dummy = 0;
914 enum OSPEFAILREASON reason;
917 result->outhandle = OSP_INVALID_HANDLE;
918 result->tech[0] = '\0';
919 result->dest[0] = '\0';
920 result->called[0] = '\0';
921 result->calling[0] = '\0';
922 result->token[0] = '\0';
923 result->networkid[0] = '\0';
924 result->numresults = 0;
925 result->outtimelimit = OSP_DEF_TIMELIMIT;
927 if ((res = osp_get_provider(provider, &p)) <= 0) {
929 ast_log(LOG_DEBUG, "OSP: Unabe to find OSP provider '%s'\n", provider);
933 if ((res = osp_create_transaction(provider, &result->outhandle, sizeof(source), source)) <= 0) {
935 ast_log(LOG_DEBUG, "OSP: Unable to generate transaction handle\n");
936 result->outhandle = OSP_INVALID_HANDLE;
937 if (result->inhandle != OSP_INVALID_HANDLE) {
938 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
945 for (i = 0; i < OSP_CALLID_MAXNUM; i++) {
947 if (callidtypes & type) {
948 error = osp_create_callid(type, &callid);
950 callids[callidnum] = OSPPCallIdNew(callid.len, callid.buf);
956 osp_convert_address(source, src, sizeof(src));
957 osp_convert_address(srcdev, dev, sizeof(dev));
958 result->numresults = OSP_DEF_DESTINATIONS;
959 error = OSPPTransactionRequestAuthorisation(
963 calling ? calling : "",
975 for (i = 0; i < callidnum; i++) {
976 OSPPCallIdDelete(&callids[i]);
979 if (error != OSPC_ERR_NO_ERROR) {
981 ast_log(LOG_DEBUG, "OSP: Unable to request authorization\n");
982 result->numresults = 0;
983 if (result->inhandle != OSP_INVALID_HANDLE) {
984 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
989 if (!result->numresults) {
991 ast_log(LOG_DEBUG, "OSP: No more destination\n");
992 if (result->inhandle != OSP_INVALID_HANDLE) {
993 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
998 result->outcallid.len = sizeof(result->outcallid.buf);
999 tokenlen = sizeof(token);
1000 error = OSPPTransactionGetFirstDestination(
1005 &result->outtimelimit,
1006 &result->outcallid.len,
1007 result->outcallid.buf,
1012 sizeof(destination),
1018 if (error != OSPC_ERR_NO_ERROR) {
1020 ast_log(LOG_DEBUG, "OSP: Unable to get first route\n");
1021 result->numresults = 0;
1022 result->outtimelimit = OSP_DEF_TIMELIMIT;
1023 if (result->inhandle != OSP_INVALID_HANDLE) {
1024 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1029 result->numresults--;
1030 result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
1032 ast_log(LOG_DEBUG, "OSP: outtimelimit '%d'\n", result->outtimelimit);
1033 ast_log(LOG_DEBUG, "OSP: called '%s'\n", callednum);
1034 ast_log(LOG_DEBUG, "OSP: calling '%s'\n", callingnum);
1035 ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination);
1036 ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen);
1039 if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
1043 if (!result->numresults) {
1045 ast_log(LOG_DEBUG, "OSP: No more destination\n");
1046 result->outtimelimit = OSP_DEF_TIMELIMIT;
1047 OSPPTransactionRecordFailure(result->outhandle, reason);
1048 if (result->inhandle != OSP_INVALID_HANDLE) {
1049 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1054 while(result->numresults) {
1055 result->outcallid.len = sizeof(result->outcallid.buf);
1056 tokenlen = sizeof(token);
1057 error = OSPPTransactionGetNextDestination(
1063 &result->outtimelimit,
1064 &result->outcallid.len,
1065 result->outcallid.buf,
1070 sizeof(destination),
1076 if (error == OSPC_ERR_NO_ERROR) {
1077 result->numresults--;
1078 result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
1080 ast_log(LOG_DEBUG, "OSP: outtimelimit '%d'\n", result->outtimelimit);
1081 ast_log(LOG_DEBUG, "OSP: called '%s'\n", callednum);
1082 ast_log(LOG_DEBUG, "OSP: calling '%s'\n", callingnum);
1083 ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination);
1084 ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen);
1086 if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
1088 } else if (!result->numresults) {
1090 ast_log(LOG_DEBUG, "OSP: No more destination\n");
1091 OSPPTransactionRecordFailure(result->outhandle, reason);
1092 if (result->inhandle != OSP_INVALID_HANDLE) {
1093 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1100 ast_log(LOG_DEBUG, "OSP: Unable to get route, error '%d'\n", error);
1101 result->numresults = 0;
1102 result->outtimelimit = OSP_DEF_TIMELIMIT;
1103 if (result->inhandle != OSP_INVALID_HANDLE) {
1104 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1114 * \brief OSP Lookup Next function
1115 * \param cause Asterisk hangup cuase
1116 * \param result Lookup results, in/output
1117 * \return 1 Found , 0 No route, -1 Error
1119 static int osp_next(
1120 const char* provider,
1122 struct osp_result* result)
1125 struct osp_provider* p;
1126 char callingnum[OSP_NORSTR_SIZE];
1127 char callednum[OSP_NORSTR_SIZE];
1128 char destination[OSP_NORSTR_SIZE];
1129 unsigned int tokenlen;
1130 char token[OSP_TOKSTR_SIZE];
1131 enum OSPEFAILREASON reason;
1134 result->tech[0] = '\0';
1135 result->dest[0] = '\0';
1136 result->called[0] = '\0';
1137 result->calling[0] = '\0';
1138 result->token[0] = '\0';
1139 result->networkid[0] = '\0';
1140 result->outtimelimit = OSP_DEF_TIMELIMIT;
1142 if ((res = osp_get_provider(provider, &p)) <= 0) {
1144 ast_log(LOG_DEBUG, "OSP: Unabe to find OSP provider '%s'\n", provider);
1148 if (result->outhandle == OSP_INVALID_HANDLE) {
1150 ast_log(LOG_DEBUG, "OSP: Transaction handle undefined\n");
1151 result->numresults = 0;
1152 if (result->inhandle != OSP_INVALID_HANDLE) {
1153 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1158 reason = asterisk2osp(cause);
1160 if (!result->numresults) {
1162 ast_log(LOG_DEBUG, "OSP: No more destination\n");
1163 OSPPTransactionRecordFailure(result->outhandle, reason);
1164 if (result->inhandle != OSP_INVALID_HANDLE) {
1165 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1170 while(result->numresults) {
1171 result->outcallid.len = sizeof(result->outcallid.buf);
1172 tokenlen = sizeof(token);
1173 error = OSPPTransactionGetNextDestination(
1179 &result->outtimelimit,
1180 &result->outcallid.len,
1181 result->outcallid.buf,
1186 sizeof(destination),
1192 if (error == OSPC_ERR_NO_ERROR) {
1193 result->numresults--;
1194 result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
1196 ast_log(LOG_DEBUG, "OSP: outtimelimit '%d'\n", result->outtimelimit);
1197 ast_log(LOG_DEBUG, "OSP: called '%s'\n", callednum);
1198 ast_log(LOG_DEBUG, "OSP: calling '%s'\n", callingnum);
1199 ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination);
1200 ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen);
1202 if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
1205 } else if (!result->numresults) {
1207 ast_log(LOG_DEBUG, "OSP: No more destination\n");
1208 OSPPTransactionRecordFailure(result->outhandle, reason);
1209 if (result->inhandle != OSP_INVALID_HANDLE) {
1210 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1217 ast_log(LOG_DEBUG, "OSP: Unable to get route, error '%d'\n", error);
1218 result->token[0] = '\0';
1219 result->numresults = 0;
1220 result->outtimelimit = OSP_DEF_TIMELIMIT;
1221 if (result->inhandle != OSP_INVALID_HANDLE) {
1222 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1233 * \brief OSP Finish function
1234 * \param handle OSP in/outbound transaction handle
1235 * \param recorded If failure reason has been recorded
1236 * \param cause Asterisk hangup cause
1237 * \param start Call start time
1238 * \param connect Call connect time
1239 * \param end Call end time
1240 * \param release Who release first, 0 source, 1 destination
1241 * \return 1 Success, 0 Failed, -1 Error
1243 static int osp_finish(
1250 unsigned int release)
1253 enum OSPEFAILREASON reason;
1255 unsigned isPddInfoPresent = 0;
1257 unsigned int dummy = 0;
1260 if (handle == OSP_INVALID_HANDLE) {
1265 reason = asterisk2osp(cause);
1266 OSPPTransactionRecordFailure(handle, reason);
1269 error = OSPPTransactionReportUsage(
1271 difftime(end, connect),
1286 if (error == OSPC_ERR_NO_ERROR) {
1288 ast_log(LOG_DEBUG, "OSP: Usage reported\n");
1292 ast_log(LOG_DEBUG, "OSP: Unable to report usage, error '%d'\n", error);
1295 OSPPTransactionDelete(handle);
1300 /* OSP Application APIs */
1303 * \brief OSP Application OSPAuth
1304 * \param chan Channel
1305 * \param data Parameter
1306 * \return 0 Success, -1 Failed
1308 static int ospauth_exec(
1309 struct ast_channel* chan,
1313 struct ast_module_user* u;
1314 const char* provider = OSP_DEF_PROVIDER;
1315 int priority_jump = 0;
1316 struct varshead* headp;
1317 struct ast_var_t* current;
1318 const char* source = "";
1319 const char* token = "";
1321 unsigned int timelimit;
1322 char buffer[OSP_INTSTR_SIZE];
1326 AST_DECLARE_APP_ARGS(args,
1327 AST_APP_ARG(provider);
1328 AST_APP_ARG(options);
1331 u = ast_module_user_add(chan);
1333 if (!(tmp = ast_strdupa(data))) {
1334 ast_log(LOG_ERROR, "Out of memory\n");
1335 ast_module_user_remove(u);
1339 AST_STANDARD_APP_ARGS(args, tmp);
1341 if (!ast_strlen_zero(args.provider)) {
1342 provider = args.provider;
1345 ast_log(LOG_DEBUG, "OSPAuth: provider '%s'\n", provider);
1347 if ((args.options) && (strchr(args.options, 'j'))) {
1351 ast_log(LOG_DEBUG, "OSPAuth: priority jump '%d'\n", priority_jump);
1353 headp = &chan->varshead;
1354 AST_LIST_TRAVERSE(headp, current, entries) {
1355 if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
1356 source = ast_var_value(current);
1357 } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
1358 token = ast_var_value(current);
1363 ast_log(LOG_DEBUG, "OSPAuth: source '%s'\n", source);
1364 ast_log(LOG_DEBUG, "OSPAuth: token size '%zd'\n", strlen(token));
1367 if ((res = osp_auth(provider, &handle, source, chan->cid.cid_num, chan->exten, token, &timelimit)) > 0) {
1368 status = AST_OSP_SUCCESS;
1370 timelimit = OSP_DEF_TIMELIMIT;
1372 status = AST_OSP_FAILED;
1374 status = AST_OSP_ERROR;
1378 snprintf(buffer, sizeof(buffer), "%d", handle);
1379 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
1381 ast_log(LOG_DEBUG, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
1382 snprintf(buffer, sizeof(buffer), "%d", timelimit);
1383 pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
1385 ast_log(LOG_DEBUG, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
1386 pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
1388 ast_log(LOG_DEBUG, "OSPAuth: %s\n", status);
1391 if (priority_jump || ast_opt_priority_jumping) {
1392 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
1401 ast_module_user_remove(u);
1407 * \brief OSP Application OSPLookup
1408 * \param chan Channel
1409 * \param data Parameter
1410 * \return 0 Success, -1 Failed
1412 static int osplookup_exec(
1413 struct ast_channel* chan,
1417 struct ast_module_user* u;
1418 const char* provider = OSP_DEF_PROVIDER;
1419 int priority_jump = 0;
1420 struct varshead* headp;
1421 struct ast_var_t* current;
1422 const char* srcdev = "";
1423 const char* netid = "";
1424 char buffer[OSP_TOKSTR_SIZE];
1425 unsigned int callidtypes = OSP_CALLID_UNDEFINED;
1426 struct osp_result result;
1430 AST_DECLARE_APP_ARGS(args,
1432 AST_APP_ARG(provider);
1433 AST_APP_ARG(options);
1436 if (ast_strlen_zero(data)) {
1437 ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[|provider[|options]])\n");
1441 u = ast_module_user_add(chan);
1443 if (!(tmp = ast_strdupa(data))) {
1444 ast_log(LOG_ERROR, "Out of memory\n");
1445 ast_module_user_remove(u);
1449 AST_STANDARD_APP_ARGS(args, tmp);
1452 ast_log(LOG_DEBUG, "OSPLookup: exten '%s'\n", args.exten);
1454 if (!ast_strlen_zero(args.provider)) {
1455 provider = args.provider;
1458 ast_log(LOG_DEBUG, "OSPlookup: provider '%s'\n", provider);
1461 if (strchr(args.options, 'j')) {
1464 if (strchr(args.options, 'h')) {
1465 callidtypes |= OSP_CALLID_H323;
1467 if (strchr(args.options, 's')) {
1468 callidtypes |= OSP_CALLID_SIP;
1470 if (strchr(args.options, 'i')) {
1471 callidtypes |= OSP_CALLID_IAX;
1475 ast_log(LOG_DEBUG, "OSPLookup: priority jump '%d'\n", priority_jump);
1476 ast_log(LOG_DEBUG, "OSPLookup: call id types '%d'\n", callidtypes);
1479 result.inhandle = OSP_INVALID_HANDLE;
1480 result.intimelimit = OSP_DEF_TIMELIMIT;
1482 headp = &chan->varshead;
1483 AST_LIST_TRAVERSE(headp, current, entries) {
1484 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
1485 if (sscanf(ast_var_value(current), "%d", &result.inhandle) != 1) {
1486 result.inhandle = OSP_INVALID_HANDLE;
1488 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
1489 if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) {
1490 result.intimelimit = OSP_DEF_TIMELIMIT;
1492 } else if (!strcasecmp(ast_var_name(current), "OSPINNETWORKID")) {
1493 netid = ast_var_value(current);
1494 } else if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
1495 srcdev = ast_var_value(current);
1499 ast_log(LOG_DEBUG, "OSPLookup: OSPINHANDLE '%d'\n", result.inhandle);
1500 ast_log(LOG_DEBUG, "OSPLookup: OSPINTIMELIMIT '%d'\n", result.intimelimit);
1501 ast_log(LOG_DEBUG, "OSPLookup: OSPINNETWORKID '%s'\n", netid);
1502 ast_log(LOG_DEBUG, "OSPLookup: source device '%s'\n", srcdev);
1505 if ((cres = ast_autoservice_start(chan)) < 0) {
1506 ast_module_user_remove(u);
1510 if ((res = osp_lookup(provider, srcdev, chan->cid.cid_num, args.exten, callidtypes, &result)) > 0) {
1511 status = AST_OSP_SUCCESS;
1513 result.tech[0] = '\0';
1514 result.dest[0] = '\0';
1515 result.called[0] = '\0';
1516 result.calling[0] = '\0';
1517 result.token[0] = '\0';
1518 result.networkid[0] = '\0';
1519 result.numresults = 0;
1520 result.outtimelimit = OSP_DEF_TIMELIMIT;
1521 result.outcallid.buf[0] = '\0';
1522 result.outcallid.len = 0;
1524 status = AST_OSP_FAILED;
1526 status = AST_OSP_ERROR;
1530 snprintf(buffer, sizeof(buffer), "%d", result.outhandle);
1531 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
1533 ast_log(LOG_DEBUG, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
1534 pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
1536 ast_log(LOG_DEBUG, "OSPLookup: OSPTECH '%s'\n", result.tech);
1537 pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
1539 ast_log(LOG_DEBUG, "OSPLookup: OSPDEST '%s'\n", result.dest);
1540 pbx_builtin_setvar_helper(chan, "OSPCALLED", result.called);
1542 ast_log(LOG_DEBUG, "OSPLookup: OSPCALLED '%s'\n", result.called);
1543 pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
1545 ast_log(LOG_DEBUG, "OSPLookup: OSPCALLING '%s'\n", result.calling);
1546 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
1548 ast_log(LOG_DEBUG, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
1549 snprintf(buffer, sizeof(buffer), "%d", result.numresults);
1550 pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
1552 ast_log(LOG_DEBUG, "OSPLookup: OSPRESULTS '%s'\n", buffer);
1553 snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
1554 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
1556 ast_log(LOG_DEBUG, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
1557 snprintf(buffer, sizeof(buffer), "%d", callidtypes);
1558 pbx_builtin_setvar_helper(chan, "OSPOUTCALLIDTYPES", buffer);
1560 ast_log(LOG_DEBUG, "OSPLookup: OSPOUTCALLIDTYPES '%s'\n", buffer);
1561 pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
1563 ast_log(LOG_DEBUG, "OSPLookup: %s\n", status);
1565 if (!strcasecmp(result.tech, OSP_TECH_H323)) {
1566 if ((callidtypes & OSP_CALLID_H323) && (result.outcallid.len != 0)) {
1567 osp_uuid2str(result.outcallid.buf, buffer, sizeof(buffer));
1571 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
1572 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
1573 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1574 } else if (!strcasecmp(result.tech, OSP_TECH_SIP)) {
1575 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
1576 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1577 if (!ast_strlen_zero(result.token)) {
1578 snprintf(buffer, sizeof(buffer), "%s%s", OSP_SIP_HEADER, result.token);
1579 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
1581 ast_log(LOG_DEBUG, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
1583 } else if (!strcasecmp(result.tech, OSP_TECH_IAX)) {
1584 snprintf(buffer, sizeof(buffer), "%s/%s/%s", result.tech, result.dest, result.called);
1585 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1588 if ((cres = ast_autoservice_stop(chan)) < 0) {
1589 ast_module_user_remove(u);
1594 if (priority_jump || ast_opt_priority_jumping) {
1595 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
1604 ast_module_user_remove(u);
1610 * \brief OSP Application OSPNext
1611 * \param chan Channel
1612 * \param data Parameter
1613 * \return 0 Success, -1 Failed
1615 static int ospnext_exec(
1616 struct ast_channel* chan,
1620 struct ast_module_user* u;
1621 const char* provider = OSP_DEF_PROVIDER;
1622 int priority_jump = 0;
1624 struct varshead* headp;
1625 struct ast_var_t* current;
1626 struct osp_result result;
1627 char buffer[OSP_TOKSTR_SIZE];
1628 unsigned int callidtypes = OSP_CALLID_UNDEFINED;
1632 AST_DECLARE_APP_ARGS(args,
1634 AST_APP_ARG(provider);
1635 AST_APP_ARG(options);
1638 if (ast_strlen_zero(data)) {
1639 ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[|provider[|options]])\n");
1643 u = ast_module_user_add(chan);
1645 if (!(tmp = ast_strdupa(data))) {
1646 ast_log(LOG_ERROR, "Out of memory\n");
1647 ast_module_user_remove(u);
1651 AST_STANDARD_APP_ARGS(args, tmp);
1653 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%d", &cause) != 1) {
1657 ast_log(LOG_DEBUG, "OSPNext: cause '%d'\n", cause);
1659 if (!ast_strlen_zero(args.provider)) {
1660 provider = args.provider;
1663 ast_log(LOG_DEBUG, "OSPlookup: provider '%s'\n", provider);
1665 if ((args.options) && (strchr(args.options, 'j'))) {
1669 ast_log(LOG_DEBUG, "OSPNext: priority jump '%d'\n", priority_jump);
1671 result.inhandle = OSP_INVALID_HANDLE;
1672 result.outhandle = OSP_INVALID_HANDLE;
1673 result.intimelimit = OSP_DEF_TIMELIMIT;
1674 result.numresults = 0;
1676 headp = &chan->varshead;
1677 AST_LIST_TRAVERSE(headp, current, entries) {
1678 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
1679 if (sscanf(ast_var_value(current), "%d", &result.inhandle) != 1) {
1680 result.inhandle = OSP_INVALID_HANDLE;
1682 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
1683 if (sscanf(ast_var_value(current), "%d", &result.outhandle) != 1) {
1684 result.outhandle = OSP_INVALID_HANDLE;
1686 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
1687 if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) {
1688 result.intimelimit = OSP_DEF_TIMELIMIT;
1690 } else if (!strcasecmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) {
1691 if (sscanf(ast_var_value(current), "%d", &callidtypes) != 1) {
1692 callidtypes = OSP_CALLID_UNDEFINED;
1694 } else if (!strcasecmp(ast_var_name(current), "OSPRESULTS")) {
1695 if (sscanf(ast_var_value(current), "%d", &result.numresults) != 1) {
1696 result.numresults = 0;
1701 ast_log(LOG_DEBUG, "OSPNext: OSPINHANDLE '%d'\n", result.inhandle);
1702 ast_log(LOG_DEBUG, "OSPNext: OSPOUTHANDLE '%d'\n", result.outhandle);
1703 ast_log(LOG_DEBUG, "OSPNext: OSPINTIMELIMIT '%d'\n", result.intimelimit);
1704 ast_log(LOG_DEBUG, "OSPNext: OSPOUTCALLIDTYPES '%d'\n", callidtypes);
1705 ast_log(LOG_DEBUG, "OSPNext: OSPRESULTS '%d'\n", result.numresults);
1708 if ((res = osp_next(provider, cause, &result)) > 0) {
1709 status = AST_OSP_SUCCESS;
1711 result.tech[0] = '\0';
1712 result.dest[0] = '\0';
1713 result.called[0] = '\0';
1714 result.calling[0] = '\0';
1715 result.token[0] = '\0';
1716 result.networkid[0] = '\0';
1717 result.numresults = 0;
1718 result.outtimelimit = OSP_DEF_TIMELIMIT;
1719 result.outcallid.buf[0] = '\0';
1720 result.outcallid.len = 0;
1722 status = AST_OSP_FAILED;
1724 status = AST_OSP_ERROR;
1728 pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
1730 ast_log(LOG_DEBUG, "OSPNext: OSPTECH '%s'\n", result.tech);
1731 pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
1733 ast_log(LOG_DEBUG, "OSPNext: OSPDEST '%s'\n", result.dest);
1734 pbx_builtin_setvar_helper(chan, "OSPCALLED", result.called);
1736 ast_log(LOG_DEBUG, "OSPNext: OSPCALLED'%s'\n", result.called);
1737 pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
1739 ast_log(LOG_DEBUG, "OSPNext: OSPCALLING '%s'\n", result.calling);
1740 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
1742 ast_log(LOG_DEBUG, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
1743 snprintf(buffer, sizeof(buffer), "%d", result.numresults);
1744 pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
1746 ast_log(LOG_DEBUG, "OSPNext: OSPRESULTS '%s'\n", buffer);
1747 snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
1748 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
1750 ast_log(LOG_DEBUG, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
1751 pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
1753 ast_log(LOG_DEBUG, "OSPNext: %s\n", status);
1755 if (!strcasecmp(result.tech, OSP_TECH_H323)) {
1756 if ((callidtypes & OSP_CALLID_H323) && (result.outcallid.len != 0)) {
1757 osp_uuid2str(result.outcallid.buf, buffer, sizeof(buffer));
1761 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
1762 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
1763 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1764 } else if (!strcasecmp(result.tech, OSP_TECH_SIP)) {
1765 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
1766 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1767 if (!ast_strlen_zero(result.token)) {
1768 snprintf(buffer, sizeof(buffer), "%s%s", OSP_SIP_HEADER, result.token);
1769 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
1771 ast_log(LOG_DEBUG, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
1773 } else if (!strcasecmp(result.tech, OSP_TECH_IAX)) {
1774 snprintf(buffer, sizeof(buffer), "%s/%s/%s", result.tech, result.dest, result.called);
1775 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1779 if (priority_jump || ast_opt_priority_jumping) {
1780 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
1789 ast_module_user_remove(u);
1795 * \brief OSP Application OSPFinish
1796 * \param chan Channel
1797 * \param data Parameter
1798 * \return 0 Success, -1 Failed
1800 static int ospfinished_exec(
1801 struct ast_channel* chan,
1805 struct ast_module_user* u;
1806 int priority_jump = 0;
1808 struct varshead* headp;
1809 struct ast_var_t* current;
1810 int inhandle = OSP_INVALID_HANDLE;
1811 int outhandle = OSP_INVALID_HANDLE;
1813 time_t start, connect, end;
1814 unsigned int release;
1815 char buffer[OSP_INTSTR_SIZE];
1819 AST_DECLARE_APP_ARGS(args,
1821 AST_APP_ARG(options);
1824 u = ast_module_user_add(chan);
1826 if (!(tmp = ast_strdupa(data))) {
1827 ast_log(LOG_ERROR, "Out of memory\n");
1828 ast_module_user_remove(u);
1832 AST_STANDARD_APP_ARGS(args, tmp);
1834 if ((args.options) && (strchr(args.options, 'j'))) {
1838 ast_log(LOG_DEBUG, "OSPFinish: priority jump '%d'\n", priority_jump);
1840 headp = &chan->varshead;
1841 AST_LIST_TRAVERSE(headp, current, entries) {
1842 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
1843 if (sscanf(ast_var_value(current), "%d", &inhandle) != 1) {
1844 inhandle = OSP_INVALID_HANDLE;
1846 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
1847 if (sscanf(ast_var_value(current), "%d", &outhandle) != 1) {
1848 outhandle = OSP_INVALID_HANDLE;
1850 } else if (!recorded &&
1851 (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") ||
1852 !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") ||
1853 !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS")))
1855 if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) {
1861 ast_log(LOG_DEBUG, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
1862 ast_log(LOG_DEBUG, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
1863 ast_log(LOG_DEBUG, "OSPFinish: recorded '%d'\n", recorded);
1866 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%d", &cause) != 1) {
1870 ast_log(LOG_DEBUG, "OSPFinish: cause '%d'\n", cause);
1873 start = chan->cdr->start.tv_sec;
1874 connect = chan->cdr->answer.tv_sec;
1886 ast_log(LOG_DEBUG, "OSPFinish: start '%ld'\n", start);
1887 ast_log(LOG_DEBUG, "OSPFinish: connect '%ld'\n", connect);
1888 ast_log(LOG_DEBUG, "OSPFinish: end '%ld'\n", end);
1891 release = chan->_softhangup ? 0 : 1;
1893 if (osp_finish(outhandle, recorded, cause, start, connect, end, release) <= 0) {
1895 ast_log(LOG_DEBUG, "OSPFinish: Unable to report usage for outbound call\n");
1898 case AST_CAUSE_NORMAL_CLEARING:
1901 cause = AST_CAUSE_NO_ROUTE_DESTINATION;
1904 if (osp_finish(inhandle, recorded, cause, start, connect, end, release) <= 0) {
1906 ast_log(LOG_DEBUG, "OSPFinish: Unable to report usage for inbound call\n");
1908 snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
1909 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
1910 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
1913 status = AST_OSP_SUCCESS;
1915 status = AST_OSP_FAILED;
1917 status = AST_OSP_ERROR;
1919 pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
1922 if (priority_jump || ast_opt_priority_jumping) {
1923 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
1932 ast_module_user_remove(u);
1937 /* OSP Module APIs */
1939 static int osp_load(void)
1943 struct ast_config* cfg;
1944 int error = OSPC_ERR_NO_ERROR;
1946 cfg = ast_config_load(OSP_CONFIG_FILE);
1948 t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate");
1949 if (t && ast_true(t)) {
1950 if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
1951 ast_log(LOG_WARNING, "OSP: Unable to enable hardware accelleration\n");
1960 ast_log(LOG_DEBUG, "OSP: osp_hardware '%d'\n", osp_hardware);
1962 t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat");
1964 if ((sscanf(t, "%d", &v) == 1) &&
1965 ((v == TOKEN_ALGO_SIGNED) || (v == TOKEN_ALGO_UNSIGNED) || (v == TOKEN_ALGO_BOTH)))
1967 osp_tokenformat = v;
1969 ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n",
1970 TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, t);
1974 ast_log(LOG_DEBUG, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
1976 t = ast_category_browse(cfg, NULL);
1978 if (strcasecmp(t, OSP_GENERAL_CAT)) {
1979 osp_create_provider(cfg, t);
1981 t = ast_category_browse(cfg, t);
1984 osp_initialized = 1;
1986 ast_config_destroy(cfg);
1988 ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
1992 ast_log(LOG_DEBUG, "OSP: osp_initialized '%d'\n", osp_initialized);
1997 static int osp_unload(void)
1999 struct osp_provider* p;
2000 struct osp_provider* next;
2002 if (osp_initialized) {
2003 ast_mutex_lock(&osplock);
2007 OSPPProviderDelete(p->handle, 0);
2011 ospproviders = NULL;
2012 ast_mutex_unlock(&osplock);
2016 osp_tokenformat = TOKEN_ALGO_SIGNED;
2018 osp_initialized = 0;
2023 static int osp_show(
2030 struct osp_provider* p;
2031 const char* provider = NULL;
2032 const char* tokenalgo;
2034 if ((argc < 2) || (argc > 3)) {
2035 return RESULT_SHOWUSAGE;
2041 switch (osp_tokenformat) {
2042 case TOKEN_ALGO_BOTH:
2045 case TOKEN_ALGO_UNSIGNED:
2046 tokenalgo = "Unsigned";
2048 case TOKEN_ALGO_SIGNED:
2050 tokenalgo = "Signed";
2053 ast_cli(fd, "OSP: %s %s %s\n",
2054 osp_initialized ? "Initialized" : "Uninitialized", osp_hardware ? "Accelerated" : "Normal", tokenalgo);
2057 ast_mutex_lock(&osplock);
2060 if (!provider || !strcasecmp(p->name, provider)) {
2064 ast_cli(fd, " == OSP Provider '%s' == \n", p->name);
2065 ast_cli(fd, "Local Private Key: %s\n", p->privatekey);
2066 ast_cli(fd, "Local Certificate: %s\n", p->localcert);
2067 for (i = 0; i < p->cacount; i++) {
2068 ast_cli(fd, "CA Certificate %d: %s\n", i + 1, p->cacerts[i]);
2070 for (i = 0; i < p->spcount; i++) {
2071 ast_cli(fd, "Service Point %d: %s\n", i + 1, p->srvpoints[i]);
2073 ast_cli(fd, "Max Connections: %d\n", p->maxconnections);
2074 ast_cli(fd, "Retry Delay: %d seconds\n", p->retrydelay);
2075 ast_cli(fd, "Retry Limit: %d\n", p->retrylimit);
2076 ast_cli(fd, "Timeout: %d milliseconds\n", p->timeout);
2077 ast_cli(fd, "Source: %s\n", strlen(p->source) ? p->source : "<unspecified>");
2078 ast_cli(fd, "Auth Policy %d\n", p->authpolicy);
2079 ast_cli(fd, "Default protocol %s\n", p->defaultprotocol);
2080 ast_cli(fd, "OSP Handle: %d\n", p->handle);
2085 ast_mutex_unlock(&osplock);
2089 ast_cli(fd, "Unable to find OSP provider '%s'\n", provider);
2091 ast_cli(fd, "No OSP providers configured\n");
2094 return RESULT_SUCCESS;
2097 static const char* app1= "OSPAuth";
2098 static const char* synopsis1 = "OSP authentication";
2099 static const char* descrip1 =
2100 " OSPAuth([provider[|options]]): Authenticate a SIP INVITE by OSP and sets\n"
2102 " ${OSPINHANDLE}: The inbound call transaction handle\n"
2103 " ${OSPINTIMELIMIT}: The inbound call duration limit in seconds\n"
2105 "The option string may contain the following character:\n"
2106 " 'j' -- jump to n+101 priority if the authentication was NOT successful\n"
2107 "This application sets the following channel variable upon completion:\n"
2108 " OSPAUTHSTATUS The status of the OSP Auth attempt as a text string, one of\n"
2109 " SUCCESS | FAILED | ERROR\n";
2111 static const char* app2= "OSPLookup";
2112 static const char* synopsis2 = "Lookup destination by OSP";
2113 static const char* descrip2 =
2114 " OSPLookup(exten[|provider[|options]]): Looks up an extension via OSP and sets\n"
2115 "the variables, where 'n' is the number of the result beginning with 1:\n"
2116 " ${OSPOUTHANDLE}: The OSP Handle for anything remaining\n"
2117 " ${OSPTECH}: The technology to use for the call\n"
2118 " ${OSPDEST}: The destination to use for the call\n"
2119 " ${OSPCALLED}: The called number to use for the call\n"
2120 " ${OSPCALLING}: The calling number to use for the call\n"
2121 " ${OSPDIALSTR}: The dial command string\n"
2122 " ${OSPOUTTOKEN}: The actual OSP token as a string\n"
2123 " ${OSPOUTTIMELIMIT}: The outbound call duration limit in seconds\n"
2124 " ${OSPOUTCALLIDTYPES}: The outbound call id types\n"
2125 " ${OSPOUTCALLID}: The outbound call id\n"
2126 " ${OSPRESULTS}: The number of OSP results total remaining\n"
2128 "The option string may contain the following character:\n"
2129 " 'j' -- jump to n+101 priority if the lookup was NOT successful\n"
2130 " 'h' -- generate H323 call id for the outbound call\n"
2131 " 's' -- generate SIP call id for the outbound call. Have not been implemented\n"
2132 " 'i' -- generate IAX call id for the outbound call. Have not been implemented\n"
2133 "This application sets the following channel variable upon completion:\n"
2134 " OSPLOOKUPSTATUS The status of the OSP Lookup attempt as a text string, one of\n"
2135 " SUCCESS | FAILED | ERROR\n";
2137 static const char* app3 = "OSPNext";
2138 static const char* synopsis3 = "Lookup next destination by OSP";
2139 static const char* descrip3 =
2140 " OSPNext(cause[|provider[|options]]): Looks up the next OSP Destination for ${OSPOUTHANDLE}\n"
2141 "See OSPLookup for more information\n"
2143 "The option string may contain the following character:\n"
2144 " 'j' -- jump to n+101 priority if the lookup was NOT successful\n"
2145 "This application sets the following channel variable upon completion:\n"
2146 " OSPNEXTSTATUS The status of the OSP Next attempt as a text string, one of\n"
2147 " SUCCESS | FAILED | ERROR\n";
2149 static const char* app4 = "OSPFinish";
2150 static const char* synopsis4 = "Record OSP entry";
2151 static const char* descrip4 =
2152 " OSPFinish([status[|options]]): Records call state for ${OSPINHANDLE}, according to\n"
2153 "status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or CHANUNAVAIL\n"
2154 "or coincidentally, just what the Dial application stores in its ${DIALSTATUS}.\n"
2156 "The option string may contain the following character:\n"
2157 " 'j' -- jump to n+101 priority if the finish attempt was NOT successful\n"
2158 "This application sets the following channel variable upon completion:\n"
2159 " OSPFINISHSTATUS The status of the OSP Finish attempt as a text string, one of\n"
2160 " SUCCESS | FAILED | ERROR \n";
2162 static char osp_usage[] =
2164 " Displays information on Open Settlement Protocol support\n";
2166 static struct ast_cli_entry cli_osp[] = {
2167 { {"osp", "show", NULL},
2168 osp_show, "Displays OSP information",
2172 static int load_module(void)
2177 return AST_MODULE_LOAD_DECLINE;
2179 ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
2180 res = ast_register_application(app1, ospauth_exec, synopsis1, descrip1);
2181 res |= ast_register_application(app2, osplookup_exec, synopsis2, descrip2);
2182 res |= ast_register_application(app3, ospnext_exec, synopsis3, descrip3);
2183 res |= ast_register_application(app4, ospfinished_exec, synopsis4, descrip4);
2188 static int unload_module(void)
2192 res = ast_unregister_application(app4);
2193 res |= ast_unregister_application(app3);
2194 res |= ast_unregister_application(app2);
2195 res |= ast_unregister_application(app1);
2196 ast_cli_unregister_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
2199 ast_module_user_hangup_all();
2204 static int reload(void)
2212 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
2213 .load = load_module,
2214 .unload = unload_module,