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 * \extref The OSP Toolkit: http://www.transnexus.com
26 * \extref OpenSSL http://www.openssl.org
28 * \ingroup applications
32 <depend>osptk</depend>
38 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
41 #include <osp/osputils.h>
43 #include "asterisk/paths.h"
44 #include "asterisk/lock.h"
45 #include "asterisk/config.h"
46 #include "asterisk/utils.h"
47 #include "asterisk/causes.h"
48 #include "asterisk/channel.h"
49 #include "asterisk/app.h"
50 #include "asterisk/module.h"
51 #include "asterisk/pbx.h"
52 #include "asterisk/cli.h"
53 #include "asterisk/astosp.h"
55 /* OSP Buffer Sizes */
56 #define OSP_INTSTR_SIZE ((unsigned int)16) /* OSP signed/unsigned int string buffer size */
57 #define OSP_NORSTR_SIZE ((unsigned int)256) /* OSP normal string buffer size */
58 #define OSP_TOKSTR_SIZE ((unsigned int)4096) /* OSP token string buffer size */
59 #define OSP_TECHSTR_SIZE ((unsigned int)32) /* OSP signed/unsigned int string buffer size */
60 #define OSP_UUID_SIZE ((unsigned int)16) /* UUID size */
61 #define OSP_UUIDSTR_SIZE ((unsigned int)36) /* UUID string size */
63 /* OSP Authentication Policy */
65 OSP_AUTH_NO
, /* Accept any call */
66 OSP_AUTH_YES
, /* Accept call with valid OSP token or without OSP token */
67 OSP_AUTH_EXCLUSIVE
/* Only accept call with valid OSP token */
71 #define OSP_CALLID_UNDEFINED ((unsigned int)0) /* UNDEFINED */
72 #define OSP_CALLID_H323 ((unsigned int)(1 << 0)) /* H.323 */
73 #define OSP_CALLID_SIP ((unsigned int)(1 << 1)) /* SIP */
74 #define OSP_CALLID_IAX ((unsigned int)(1 << 2)) /* IAX2 */
75 #define OSP_CALLID_MAXNUM ((unsigned int)3) /* Max number of call ID type */
77 /* OSP Supported Destination Protocols */
78 #define OSP_PROT_H323 ((char*)"H323") /* H323 Q931 protocol name*/
79 #define OSP_PROT_SIP ((char*)"SIP") /* SIP protocol name */
80 #define OSP_PROT_IAX ((char*)"IAX") /* IAX protocol name */
81 #define OSP_PROT_OTHER ((char*)"OTHER") /* Other protocol name */
83 /* OSP supported Destination Tech */
85 #define OSP_TECH_H323 ((char*)"OOH323") /* OOH323 tech name */
87 #define OSP_TECH_H323 ((char*)"H323") /* OH323 tech name */
88 #define OSP_TECH_SIP ((char*)"SIP") /* SIP tech name */
89 #define OSP_TECH_IAX ((char*)"IAX2") /* IAX2 tech name */
91 /* SIP OSP header field name */
92 #define OSP_SIP_HEADER ((char*)"P-OSP-Auth-Token: ")
95 #define OSP_INVALID_HANDLE ((int)-1) /* Invalid OSP handle, provider, transaction etc. */
96 #define OSP_CONFIG_FILE ((const char*)"osp.conf") /* OSP configuration file name */
97 #define OSP_GENERAL_CAT ((const char*)"general") /* OSP global configuration context name */
98 #define OSP_DEF_PROVIDER ((const char*)"default") /* OSP default provider context name */
99 #define OSP_MAX_CERTS ((unsigned int)10) /* OSP max number of cacerts */
100 #define OSP_MAX_SRVS ((unsigned int)10) /* OSP max number of service points */
101 #define OSP_DEF_MAXCONNECTIONS ((unsigned int)20) /* OSP default max_connections */
102 #define OSP_MIN_MAXCONNECTIONS ((unsigned int)1) /* OSP min max_connections */
103 #define OSP_MAX_MAXCONNECTIONS ((unsigned int)1000) /* OSP max max_connections */
104 #define OSP_DEF_RETRYDELAY ((unsigned int)0) /* OSP default retry delay */
105 #define OSP_MIN_RETRYDELAY ((unsigned int)0) /* OSP min retry delay */
106 #define OSP_MAX_RETRYDELAY ((unsigned int)10) /* OSP max retry delay */
107 #define OSP_DEF_RETRYLIMIT ((unsigned int)2) /* OSP default retry times */
108 #define OSP_MIN_RETRYLIMIT ((unsigned int)0) /* OSP min retry times */
109 #define OSP_MAX_RETRYLIMIT ((unsigned int)100) /* OSP max retry times */
110 #define OSP_DEF_TIMEOUT ((unsigned int)500) /* OSP default timeout in ms */
111 #define OSP_MIN_TIMEOUT ((unsigned int)200) /* OSP min timeout in ms */
112 #define OSP_MAX_TIMEOUT ((unsigned int)10000) /* OSP max timeout in ms */
113 #define OSP_DEF_AUTHPOLICY ((enum osp_authpolicy)OSP_AUTH_YES)
114 #define OSP_AUDIT_URL ((const char*)"localhost") /* OSP default Audit URL */
115 #define OSP_LOCAL_VALIDATION ((int)1) /* Validate OSP token locally */
116 #define OSP_SSL_LIFETIME ((unsigned int)300) /* SSL life time, in seconds */
117 #define OSP_HTTP_PERSISTENCE ((int)1) /* In seconds */
118 #define OSP_CUSTOMER_ID ((const char*)"") /* OSP customer ID */
119 #define OSP_DEVICE_ID ((const char*)"") /* OSP device ID */
120 #define OSP_DEF_DESTINATIONS ((unsigned int)5) /* OSP default max number of destinations */
121 #define OSP_DEF_TIMELIMIT ((unsigned int)0) /* OSP default duration limit, no limit */
122 #define OSP_DEF_PROTOCOL OSP_PROT_SIP /* OSP default destination protocol, SIP */
125 struct osp_provider
{
126 char name
[OSP_NORSTR_SIZE
]; /* OSP provider context name */
127 char privatekey
[OSP_NORSTR_SIZE
]; /* OSP private key file name */
128 char localcert
[OSP_NORSTR_SIZE
]; /* OSP local cert file name */
129 unsigned int cacount
; /* Number of cacerts */
130 char cacerts
[OSP_MAX_CERTS
][OSP_NORSTR_SIZE
]; /* Cacert file names */
131 unsigned int spcount
; /* Number of service points */
132 char srvpoints
[OSP_MAX_SRVS
][OSP_NORSTR_SIZE
]; /* Service point URLs */
133 int maxconnections
; /* Max number of connections */
134 int retrydelay
; /* Retry delay */
135 int retrylimit
; /* Retry limit */
136 int timeout
; /* Timeout in ms */
137 char source
[OSP_NORSTR_SIZE
]; /* IP of self */
138 enum osp_authpolicy authpolicy
; /* OSP authentication policy */
139 char* defaultprotocol
; /* OSP default destination protocol */
140 OSPTPROVHANDLE handle
; /* OSP provider handle */
141 struct osp_provider
* next
; /* Pointer to next OSP provider */
146 unsigned char buf
[OSPC_CALLID_MAXSIZE
]; /* Call ID string */
147 unsigned int len
; /* Call ID length */
150 /* OSP Application In/Output Results */
152 int inhandle
; /* Inbound transaction handle */
153 int outhandle
; /* Outbound transaction handle */
154 unsigned int intimelimit
; /* Inbound duration limit */
155 unsigned int outtimelimit
; /* Outbound duration limit */
156 char tech
[OSP_TECHSTR_SIZE
]; /* Outbound Asterisk TECH string */
157 char dest
[OSP_NORSTR_SIZE
]; /* Outbound destination IP address */
158 char called
[OSP_NORSTR_SIZE
]; /* Outbound called number, may be translated */
159 char calling
[OSP_NORSTR_SIZE
]; /* Outbound calling number, may be translated */
160 char token
[OSP_TOKSTR_SIZE
]; /* Outbound OSP token */
161 char networkid
[OSP_NORSTR_SIZE
]; /* Outbound network ID */
162 unsigned int numresults
; /* Number of remain outbound destinations */
163 struct osp_callid outcallid
; /* Outbound call ID */
166 /* OSP Module Global Variables */
167 AST_MUTEX_DEFINE_STATIC(osplock
); /* Lock of OSP provider list */
168 static int osp_initialized
= 0; /* Init flag */
169 static int osp_hardware
= 0; /* Hardware accelleration flag */
170 static struct osp_provider
* ospproviders
= NULL
; /* OSP provider list */
171 static unsigned int osp_tokenformat
= TOKEN_ALGO_SIGNED
; /* Token format supported */
173 /* OSP Client Wrapper APIs */
176 * \brief Create OSP provider handle according to configuration
177 * \param cfg OSP configuration
178 * \param provider OSP provider context name
179 * \return 1 Success, 0 Failed, -1 Error
181 static int osp_create_provider(
182 struct ast_config
* cfg
,
183 const char* provider
)
186 unsigned int t
, i
, j
;
187 struct osp_provider
* p
;
188 struct ast_variable
* v
;
189 OSPTPRIVATEKEY privatekey
;
191 const char* psrvpoints
[OSP_MAX_SRVS
];
192 OSPTCERT cacerts
[OSP_MAX_CERTS
];
193 const OSPTCERT
* pcacerts
[OSP_MAX_CERTS
];
194 int error
= OSPC_ERR_NO_ERROR
;
196 if (!(p
= ast_calloc(1, sizeof(*p
)))) {
197 ast_log(LOG_ERROR
, "Out of memory\n");
201 ast_copy_string(p
->name
, provider
, sizeof(p
->name
));
202 snprintf(p
->privatekey
, sizeof(p
->privatekey
), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR
, provider
);
203 snprintf(p
->localcert
, sizeof(p
->localcert
), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR
, provider
);
204 p
->maxconnections
= OSP_DEF_MAXCONNECTIONS
;
205 p
->retrydelay
= OSP_DEF_RETRYDELAY
;
206 p
->retrylimit
= OSP_DEF_RETRYLIMIT
;
207 p
->timeout
= OSP_DEF_TIMEOUT
;
208 p
->authpolicy
= OSP_DEF_AUTHPOLICY
;
209 p
->defaultprotocol
= OSP_DEF_PROTOCOL
;
210 p
->handle
= OSP_INVALID_HANDLE
;
212 v
= ast_variable_browse(cfg
, provider
);
214 if (!strcasecmp(v
->name
, "privatekey")) {
215 if (v
->value
[0] == '/') {
216 ast_copy_string(p
->privatekey
, v
->value
, sizeof(p
->privatekey
));
218 snprintf(p
->privatekey
, sizeof(p
->privatekey
), "%s/%s", ast_config_AST_KEY_DIR
, v
->value
);
220 ast_debug(1, "OSP: privatekey '%s'\n", p
->privatekey
);
221 } else if (!strcasecmp(v
->name
, "localcert")) {
222 if (v
->value
[0] == '/') {
223 ast_copy_string(p
->localcert
, v
->value
, sizeof(p
->localcert
));
225 snprintf(p
->localcert
, sizeof(p
->localcert
), "%s/%s", ast_config_AST_KEY_DIR
, v
->value
);
227 ast_debug(1, "OSP: localcert '%s'\n", p
->localcert
);
228 } else if (!strcasecmp(v
->name
, "cacert")) {
229 if (p
->cacount
< OSP_MAX_CERTS
) {
230 if (v
->value
[0] == '/') {
231 ast_copy_string(p
->cacerts
[p
->cacount
], v
->value
, sizeof(p
->cacerts
[0]));
233 snprintf(p
->cacerts
[p
->cacount
], sizeof(p
->cacerts
[0]), "%s/%s", ast_config_AST_KEY_DIR
, v
->value
);
235 ast_debug(1, "OSP: cacert[%d]: '%s'\n", p
->cacount
, p
->cacerts
[p
->cacount
]);
238 ast_log(LOG_WARNING
, "OSP: Too many CA Certificates at line %d\n", v
->lineno
);
240 } else if (!strcasecmp(v
->name
, "servicepoint")) {
241 if (p
->spcount
< OSP_MAX_SRVS
) {
242 ast_copy_string(p
->srvpoints
[p
->spcount
], v
->value
, sizeof(p
->srvpoints
[0]));
243 ast_debug(1, "OSP: servicepoint[%d]: '%s'\n", p
->spcount
, p
->srvpoints
[p
->spcount
]);
246 ast_log(LOG_WARNING
, "OSP: Too many Service Points at line %d\n", v
->lineno
);
248 } else if (!strcasecmp(v
->name
, "maxconnections")) {
249 if ((sscanf(v
->value
, "%d", &t
) == 1) && (t
>= OSP_MIN_MAXCONNECTIONS
) && (t
<= OSP_MAX_MAXCONNECTIONS
)) {
250 p
->maxconnections
= t
;
251 ast_debug(1, "OSP: maxconnections '%d'\n", t
);
253 ast_log(LOG_WARNING
, "OSP: maxconnections should be an integer from %d to %d, not '%s' at line %d\n",
254 OSP_MIN_MAXCONNECTIONS
, OSP_MAX_MAXCONNECTIONS
, v
->value
, v
->lineno
);
256 } else if (!strcasecmp(v
->name
, "retrydelay")) {
257 if ((sscanf(v
->value
, "%d", &t
) == 1) && (t
>= OSP_MIN_RETRYDELAY
) && (t
<= OSP_MAX_RETRYDELAY
)) {
259 ast_debug(1, "OSP: retrydelay '%d'\n", t
);
261 ast_log(LOG_WARNING
, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n",
262 OSP_MIN_RETRYDELAY
, OSP_MAX_RETRYDELAY
, v
->value
, v
->lineno
);
264 } else if (!strcasecmp(v
->name
, "retrylimit")) {
265 if ((sscanf(v
->value
, "%d", &t
) == 1) && (t
>= OSP_MIN_RETRYLIMIT
) && (t
<= OSP_MAX_RETRYLIMIT
)) {
267 ast_debug(1, "OSP: retrylimit '%d'\n", t
);
269 ast_log(LOG_WARNING
, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n",
270 OSP_MIN_RETRYLIMIT
, OSP_MAX_RETRYLIMIT
, v
->value
, v
->lineno
);
272 } else if (!strcasecmp(v
->name
, "timeout")) {
273 if ((sscanf(v
->value
, "%d", &t
) == 1) && (t
>= OSP_MIN_TIMEOUT
) && (t
<= OSP_MAX_TIMEOUT
)) {
275 ast_debug(1, "OSP: timeout '%d'\n", t
);
277 ast_log(LOG_WARNING
, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n",
278 OSP_MIN_TIMEOUT
, OSP_MAX_TIMEOUT
, v
->value
, v
->lineno
);
280 } else if (!strcasecmp(v
->name
, "source")) {
281 ast_copy_string(p
->source
, v
->value
, sizeof(p
->source
));
282 ast_debug(1, "OSP: source '%s'\n", p
->source
);
283 } else if (!strcasecmp(v
->name
, "authpolicy")) {
284 if ((sscanf(v
->value
, "%d", &t
) == 1) && ((t
== OSP_AUTH_NO
) || (t
== OSP_AUTH_YES
) || (t
== OSP_AUTH_EXCLUSIVE
))) {
286 ast_debug(1, "OSP: authpolicy '%d'\n", t
);
288 ast_log(LOG_WARNING
, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n",
289 OSP_AUTH_NO
, OSP_AUTH_YES
, OSP_AUTH_EXCLUSIVE
, v
->value
, v
->lineno
);
291 } else if (!strcasecmp(v
->name
, "defaultprotocol")) {
292 if (!strcasecmp(v
->value
, OSP_PROT_SIP
)) {
293 p
->defaultprotocol
= OSP_PROT_SIP
;
294 ast_debug(1, "OSP: default protocol '%s'\n", p
->defaultprotocol
);
295 } else if (!strcasecmp(v
->value
, OSP_PROT_H323
)) {
296 p
->defaultprotocol
= OSP_PROT_H323
;
297 ast_debug(1, "OSP: default protocol '%s'\n", p
->defaultprotocol
);
298 } else if (!strcasecmp(v
->value
, OSP_PROT_IAX
)) {
299 p
->defaultprotocol
= OSP_PROT_IAX
;
300 ast_debug(1, "OSP: default protocol '%s'\n", p
->defaultprotocol
);
302 ast_log(LOG_WARNING
, "OSP: default protocol should be %s, %s, %s, or %s not '%s' at line %d\n",
303 OSP_PROT_SIP
, OSP_PROT_H323
, OSP_PROT_IAX
, OSP_PROT_OTHER
, v
->value
, v
->lineno
);
309 error
= OSPPUtilLoadPEMPrivateKey((unsigned char*)p
->privatekey
, &privatekey
);
310 if (error
!= OSPC_ERR_NO_ERROR
) {
311 ast_log(LOG_WARNING
, "OSP: Unable to load privatekey '%s', error '%d'\n", p
->privatekey
, error
);
316 error
= OSPPUtilLoadPEMCert((unsigned char*)p
->localcert
, &localcert
);
317 if (error
!= OSPC_ERR_NO_ERROR
) {
318 ast_log(LOG_WARNING
, "OSP: Unable to load localcert '%s', error '%d'\n", p
->localcert
, error
);
319 if (privatekey
.PrivateKeyData
) {
320 ast_free(privatekey
.PrivateKeyData
);
326 if (p
->cacount
< 1) {
327 snprintf(p
->cacerts
[p
->cacount
], sizeof(p
->cacerts
[0]), "%s/%s-cacert.pem", ast_config_AST_KEY_DIR
, provider
);
328 ast_debug(1, "OSP: cacert[%d]: '%s'\n", p
->cacount
, p
->cacerts
[p
->cacount
]);
331 for (i
= 0; i
< p
->cacount
; i
++) {
332 error
= OSPPUtilLoadPEMCert((unsigned char*)p
->cacerts
[i
], &cacerts
[i
]);
333 if (error
!= OSPC_ERR_NO_ERROR
) {
334 ast_log(LOG_WARNING
, "OSP: Unable to load cacert '%s', error '%d'\n", p
->cacerts
[i
], error
);
335 for (j
= 0; j
< i
; j
++) {
336 if (cacerts
[j
].CertData
) {
337 ast_free(cacerts
[j
].CertData
);
340 if (localcert
.CertData
) {
341 ast_free(localcert
.CertData
);
343 if (privatekey
.PrivateKeyData
) {
344 ast_free(privatekey
.PrivateKeyData
);
349 pcacerts
[i
] = &cacerts
[i
];
352 for (i
= 0; i
< p
->spcount
; i
++) {
353 psrvpoints
[i
] = p
->srvpoints
[i
];
356 error
= OSPPProviderNew(
365 OSP_LOCAL_VALIDATION
,
368 OSP_HTTP_PERSISTENCE
,
375 if (error
!= OSPC_ERR_NO_ERROR
) {
376 ast_log(LOG_WARNING
, "OSP: Unable to create provider '%s', error '%d'\n", provider
, error
);
380 ast_debug(1, "OSP: provider '%s'\n", provider
);
381 ast_mutex_lock(&osplock
);
382 p
->next
= ospproviders
;
384 ast_mutex_unlock(&osplock
);
388 for (i
= 0; i
< p
->cacount
; i
++) {
389 if (cacerts
[i
].CertData
) {
390 ast_free(cacerts
[i
].CertData
);
393 if (localcert
.CertData
) {
394 ast_free(localcert
.CertData
);
396 if (privatekey
.PrivateKeyData
) {
397 ast_free(privatekey
.PrivateKeyData
);
404 * \brief Get OSP provider by name
405 * \param name OSP provider context name
406 * \param provider OSP provider structure
407 * \return 1 Success, 0 Failed, -1 Error
409 static int osp_get_provider(
411 struct osp_provider
** provider
)
414 struct osp_provider
* p
;
416 ast_mutex_lock(&osplock
);
419 if (!strcasecmp(p
->name
, name
)) {
421 ast_debug(1, "OSP: find provider '%s'\n", name
);
427 ast_mutex_unlock(&osplock
);
433 * \brief Create OSP transaction handle
434 * \param provider OSP provider context name
435 * \param transaction OSP transaction handle, output
436 * \param sourcesize Size of source buffer, in/output
437 * \param source Source of provider, output
438 * \return 1 Success, 0 Failed, -1 Error
440 static int osp_create_transaction(
441 const char* provider
,
443 unsigned int sourcesize
,
447 struct osp_provider
* p
;
450 ast_mutex_lock(&osplock
);
453 if (!strcasecmp(p
->name
, provider
)) {
454 error
= OSPPTransactionNew(p
->handle
, transaction
);
455 if (error
== OSPC_ERR_NO_ERROR
) {
456 ast_debug(1, "OSP: transaction '%d'\n", *transaction
);
457 ast_copy_string(source
, p
->source
, sourcesize
);
458 ast_debug(1, "OSP: source '%s'\n", source
);
461 *transaction
= OSP_INVALID_HANDLE
;
462 ast_debug(1, "OSP: Unable to create transaction handle, error '%d'\n", error
);
469 ast_mutex_unlock(&osplock
);
475 * \brief Convert address to "[x.x.x.x]" or "host.domain" format
476 * \param src Source address string
477 * \param dst Destination address string
478 * \param buffersize Size of dst buffer
480 static void osp_convert_address(
487 if (inet_aton(src
, &inp
) != 0) {
488 snprintf(dst
, buffersize
, "[%s]", src
);
490 snprintf(dst
, buffersize
, "%s", src
);
495 * \brief Validate OSP token of inbound call
496 * \param transaction OSP transaction handle
497 * \param source Source of inbound call
498 * \param destination Destination of inbound call
499 * \param calling Calling number
500 * \param called Called number
501 * \param token OSP token, may be empty
502 * \param timelimit Call duration limit, output
503 * \return 1 Success, 0 Failed, -1 Error
505 static int osp_validate_token(
508 const char* destination
,
512 unsigned int* timelimit
)
516 unsigned char tokenstr
[OSP_TOKSTR_SIZE
];
517 char src
[OSP_NORSTR_SIZE
];
518 char dst
[OSP_NORSTR_SIZE
];
519 unsigned int authorised
;
520 unsigned int dummy
= 0;
523 tokenlen
= ast_base64decode(tokenstr
, token
, strlen(token
));
524 osp_convert_address(source
, src
, sizeof(src
));
525 osp_convert_address(destination
, dst
, sizeof(dst
));
526 error
= OSPPTransactionValidateAuthorisation(
532 calling
? calling
: "",
545 if (error
!= OSPC_ERR_NO_ERROR
) {
546 ast_debug(1, "OSP: Unable to validate inbound token\n");
548 } else if (authorised
) {
549 ast_debug(1, "OSP: Authorised\n");
552 ast_debug(1, "OSP: Unauthorised\n");
560 * \brief Choose min duration limit
561 * \param in Inbound duration limit
562 * \param out Outbound duration limit
563 * \return min duration limit
565 static unsigned int osp_choose_timelimit(
569 if (in
== OSP_DEF_TIMELIMIT
) {
571 } else if (out
== OSP_DEF_TIMELIMIT
) {
574 return in
< out
? in
: out
;
579 * \brief Choose min duration limit
580 * \param provider OSP provider
581 * \param called Called number
582 * \param calling Calling number
583 * \param destination Destination IP in '[x.x.x.x]' format
584 * \param tokenlen OSP token length
585 * \param token OSP token
586 * \param reason Failure reason, output
587 * \param result OSP lookup results, in/output
588 * \return 1 Success, 0 Failed, -1 Error
590 static int osp_check_destination(
591 struct osp_provider
* provider
,
595 unsigned int tokenlen
,
597 enum OSPEFAILREASON
* reason
,
598 struct osp_result
* result
)
601 OSPE_DEST_OSP_ENABLED enabled
;
602 OSPE_DEST_PROT protocol
;
605 if (strlen(destination
) <= 2) {
606 ast_debug(1, "OSP: Wrong destination format '%s'\n", destination
);
607 *reason
= OSPC_FAIL_NORMAL_UNSPECIFIED
;
611 if ((error
= OSPPTransactionIsDestOSPEnabled(result
->outhandle
, &enabled
)) != OSPC_ERR_NO_ERROR
) {
612 ast_debug(1, "OSP: Unable to get destination OSP version, error '%d'\n", error
);
613 *reason
= OSPC_FAIL_NORMAL_UNSPECIFIED
;
617 if (enabled
== OSPE_OSP_FALSE
) {
618 result
->token
[0] = '\0';
620 ast_base64encode(result
->token
, (const unsigned char*)token
, tokenlen
, sizeof(result
->token
) - 1);
623 if ((error
= OSPPTransactionGetDestNetworkId(result
->outhandle
, result
->networkid
)) != OSPC_ERR_NO_ERROR
) {
624 ast_debug(1, "OSP: Unable to get destination network ID, error '%d'\n", error
);
625 result
->networkid
[0] = '\0';
628 if ((error
= OSPPTransactionGetDestProtocol(result
->outhandle
, &protocol
)) != OSPC_ERR_NO_ERROR
) {
629 ast_debug(1, "OSP: Unable to get destination protocol, error '%d'\n", error
);
630 *reason
= OSPC_FAIL_NORMAL_UNSPECIFIED
;
631 result
->token
[0] = '\0';
632 result
->networkid
[0] = '\0';
637 /* Strip leading and trailing brackets */
638 destination
[strlen(destination
) - 1] = '\0';
640 case OSPE_DEST_PROT_H323_SETUP
:
641 ast_debug(1, "OSP: protocol '%s'\n", OSP_PROT_H323
);
642 ast_copy_string(result
->tech
, OSP_TECH_H323
, sizeof(result
->tech
));
643 ast_copy_string(result
->dest
, destination
+ 1, sizeof(result
->dest
));
644 ast_copy_string(result
->called
, called
, sizeof(result
->called
));
645 ast_copy_string(result
->calling
, calling
, sizeof(result
->calling
));
647 case OSPE_DEST_PROT_SIP
:
648 ast_debug(1, "OSP: protocol '%s'\n", OSP_PROT_SIP
);
649 ast_copy_string(result
->tech
, OSP_TECH_SIP
, sizeof(result
->tech
));
650 ast_copy_string(result
->dest
, destination
+ 1, sizeof(result
->dest
));
651 ast_copy_string(result
->called
, called
, sizeof(result
->called
));
652 ast_copy_string(result
->calling
, calling
, sizeof(result
->calling
));
654 case OSPE_DEST_PROT_IAX
:
655 ast_debug(1, "OSP: protocol '%s'\n", OSP_PROT_IAX
);
656 ast_copy_string(result
->tech
, OSP_TECH_IAX
, sizeof(result
->tech
));
657 ast_copy_string(result
->dest
, destination
+ 1, sizeof(result
->dest
));
658 ast_copy_string(result
->called
, called
, sizeof(result
->called
));
659 ast_copy_string(result
->calling
, calling
, sizeof(result
->calling
));
661 case OSPE_DEST_PROT_UNDEFINED
:
662 case OSPE_DEST_PROT_UNKNOWN
:
663 ast_debug(1, "OSP: unknown/undefined protocol '%d'\n", protocol
);
664 ast_debug(1, "OSP: use default protocol '%s'\n", provider
->defaultprotocol
);
666 ast_copy_string(result
->tech
, provider
->defaultprotocol
, sizeof(result
->tech
));
667 ast_copy_string(result
->dest
, destination
+ 1, sizeof(result
->dest
));
668 ast_copy_string(result
->called
, called
, sizeof(result
->called
));
669 ast_copy_string(result
->calling
, calling
, sizeof(result
->calling
));
671 case OSPE_DEST_PROT_H323_LRQ
:
673 ast_log(LOG_WARNING
, "OSP: unsupported protocol '%d'\n", protocol
);
674 *reason
= OSPC_FAIL_PROTOCOL_ERROR
;
675 result
->token
[0] = '\0';
676 result
->networkid
[0] = '\0';
685 * \brief Convert Asterisk status to TC code
686 * \param cause Asterisk hangup cause
687 * \return OSP TC code
689 static enum OSPEFAILREASON
asterisk2osp(
692 return (enum OSPEFAILREASON
)cause
;
696 * \brief OSP Authentication function
697 * \param provider OSP provider context name
698 * \param transaction OSP transaction handle, output
699 * \param source Source of inbound call
700 * \param calling Calling number
701 * \param called Called number
702 * \param token OSP token, may be empty
703 * \param timelimit Call duration limit, output
704 * \return 1 Authenricated, 0 Unauthenticated, -1 Error
707 const char* provider
,
713 unsigned int* timelimit
)
716 struct osp_provider
* p
;
717 char dest
[OSP_NORSTR_SIZE
];
719 *transaction
= OSP_INVALID_HANDLE
;
720 *timelimit
= OSP_DEF_TIMELIMIT
;
722 if ((res
= osp_get_provider(provider
, &p
)) <= 0) {
723 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", provider
);
727 switch (p
->authpolicy
) {
731 case OSP_AUTH_EXCLUSIVE
:
732 if (ast_strlen_zero(token
)) {
734 } else if ((res
= osp_create_transaction(provider
, transaction
, sizeof(dest
), dest
)) <= 0) {
735 ast_debug(1, "OSP: Unable to generate transaction handle\n");
736 *transaction
= OSP_INVALID_HANDLE
;
738 } else if((res
= osp_validate_token(*transaction
, source
, dest
, calling
, called
, token
, timelimit
)) <= 0) {
739 OSPPTransactionRecordFailure(*transaction
, OSPC_FAIL_CALL_REJECTED
);
744 if (ast_strlen_zero(token
)) {
746 } else if ((res
= osp_create_transaction(provider
, transaction
, sizeof(dest
), dest
)) <= 0) {
747 ast_debug(1, "OSP: Unable to generate transaction handle\n");
748 *transaction
= OSP_INVALID_HANDLE
;
750 } else if((res
= osp_validate_token(*transaction
, source
, dest
, calling
, called
, token
, timelimit
)) <= 0) {
751 OSPPTransactionRecordFailure(*transaction
, OSPC_FAIL_CALL_REJECTED
);
760 * \brief Create a UUID
761 * \param uuid UUID buffer
762 * \param buffersize UUID buffer size
763 * \return 1 Created, -1 Error
765 static int osp_create_uuid(
767 unsigned int* buffersize
)
772 if (*buffersize
>= OSP_UUID_SIZE
) {
773 tmp
= (long int*)uuid
;
774 for (i
= 0; i
< OSP_UUID_SIZE
/ sizeof(long int); i
++) {
775 tmp
[i
] = ast_random();
777 *buffersize
= OSP_UUID_SIZE
;
787 * \brief UUID to string
789 * \param buffer String buffer
790 * \param buffersize String buffer size
791 * \return 1 Successed, -1 Error
793 static int osp_uuid2str(
796 unsigned int buffersize
)
800 if (buffersize
> OSP_UUIDSTR_SIZE
) {
801 snprintf(buffer
, buffersize
, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
802 uuid
[0], uuid
[1], uuid
[2], uuid
[3], uuid
[4], uuid
[5], uuid
[6], uuid
[7],
803 uuid
[8], uuid
[9], uuid
[10], uuid
[11], uuid
[12], uuid
[13], uuid
[14], uuid
[15]);
813 * \brief Create a call ID according to the type
814 * \param type Call ID type
815 * \param callid Call ID buffer
816 * \return 1 Created, 0 Not create, -1 Error
818 static int osp_create_callid(
820 struct osp_callid
* callid
)
824 callid
->len
= sizeof(callid
->buf
);
826 case OSP_CALLID_H323
:
827 res
= osp_create_uuid(callid
->buf
, &callid
->len
);
837 if ((res
!= 1) && (callid
->len
!= 0)) {
838 callid
->buf
[0] = '\0';
846 * \brief OSP Lookup function
847 * \param provider OSP provider context name
848 * \param srcdev Source device of outbound call
849 * \param calling Calling number
850 * \param called Called number
851 * \param callidtypes Call ID types
852 * \param result Lookup results
853 * \return 1 Found , 0 No route, -1 Error
855 static int osp_lookup(
856 const char* provider
,
860 unsigned int callidtypes
,
861 struct osp_result
* result
)
864 struct osp_provider
* p
;
865 char source
[OSP_NORSTR_SIZE
];
866 char callingnum
[OSP_NORSTR_SIZE
];
867 char callednum
[OSP_NORSTR_SIZE
];
868 char destination
[OSP_NORSTR_SIZE
];
869 unsigned int tokenlen
;
870 char token
[OSP_TOKSTR_SIZE
];
871 char src
[OSP_NORSTR_SIZE
];
872 char dev
[OSP_NORSTR_SIZE
];
873 unsigned int i
, type
;
874 struct osp_callid callid
;
875 unsigned int callidnum
;
876 OSPTCALLID
* callids
[OSP_CALLID_MAXNUM
];
877 unsigned int dummy
= 0;
878 enum OSPEFAILREASON reason
;
881 result
->outhandle
= OSP_INVALID_HANDLE
;
882 result
->tech
[0] = '\0';
883 result
->dest
[0] = '\0';
884 result
->called
[0] = '\0';
885 result
->calling
[0] = '\0';
886 result
->token
[0] = '\0';
887 result
->networkid
[0] = '\0';
888 result
->numresults
= 0;
889 result
->outtimelimit
= OSP_DEF_TIMELIMIT
;
891 if ((res
= osp_get_provider(provider
, &p
)) <= 0) {
892 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", provider
);
896 if ((res
= osp_create_transaction(provider
, &result
->outhandle
, sizeof(source
), source
)) <= 0) {
897 ast_debug(1, "OSP: Unable to generate transaction handle\n");
898 result
->outhandle
= OSP_INVALID_HANDLE
;
899 if (result
->inhandle
!= OSP_INVALID_HANDLE
) {
900 OSPPTransactionRecordFailure(result
->inhandle
, OSPC_FAIL_NORMAL_UNSPECIFIED
);
907 for (i
= 0; i
< OSP_CALLID_MAXNUM
; i
++) {
909 if (callidtypes
& type
) {
910 error
= osp_create_callid(type
, &callid
);
912 callids
[callidnum
] = OSPPCallIdNew(callid
.len
, callid
.buf
);
918 osp_convert_address(source
, src
, sizeof(src
));
919 osp_convert_address(srcdev
, dev
, sizeof(dev
));
920 result
->numresults
= OSP_DEF_DESTINATIONS
;
921 error
= OSPPTransactionRequestAuthorisation(
925 calling
? calling
: "",
937 for (i
= 0; i
< callidnum
; i
++) {
938 OSPPCallIdDelete(&callids
[i
]);
941 if (error
!= OSPC_ERR_NO_ERROR
) {
942 ast_debug(1, "OSP: Unable to request authorization\n");
943 result
->numresults
= 0;
944 if (result
->inhandle
!= OSP_INVALID_HANDLE
) {
945 OSPPTransactionRecordFailure(result
->inhandle
, OSPC_FAIL_NORMAL_UNSPECIFIED
);
950 if (!result
->numresults
) {
951 ast_debug(1, "OSP: No more destination\n");
952 if (result
->inhandle
!= OSP_INVALID_HANDLE
) {
953 OSPPTransactionRecordFailure(result
->inhandle
, OSPC_FAIL_NO_ROUTE_TO_DEST
);
958 result
->outcallid
.len
= sizeof(result
->outcallid
.buf
);
959 tokenlen
= sizeof(token
);
960 error
= OSPPTransactionGetFirstDestination(
965 &result
->outtimelimit
,
966 &result
->outcallid
.len
,
967 result
->outcallid
.buf
,
978 if (error
!= OSPC_ERR_NO_ERROR
) {
979 ast_debug(1, "OSP: Unable to get first route\n");
980 result
->numresults
= 0;
981 result
->outtimelimit
= OSP_DEF_TIMELIMIT
;
982 if (result
->inhandle
!= OSP_INVALID_HANDLE
) {
983 OSPPTransactionRecordFailure(result
->inhandle
, OSPC_FAIL_NO_ROUTE_TO_DEST
);
988 result
->numresults
--;
989 result
->outtimelimit
= osp_choose_timelimit(result
->intimelimit
, result
->outtimelimit
);
990 ast_debug(1, "OSP: outtimelimit '%d'\n", result
->outtimelimit
);
991 ast_debug(1, "OSP: called '%s'\n", callednum
);
992 ast_debug(1, "OSP: calling '%s'\n", callingnum
);
993 ast_debug(1, "OSP: destination '%s'\n", destination
);
994 ast_debug(1, "OSP: token size '%d'\n", tokenlen
);
996 if ((res
= osp_check_destination(p
, callednum
, callingnum
, destination
, tokenlen
, token
, &reason
, result
)) > 0) {
1000 if (!result
->numresults
) {
1001 ast_debug(1, "OSP: No more destination\n");
1002 result
->outtimelimit
= OSP_DEF_TIMELIMIT
;
1003 OSPPTransactionRecordFailure(result
->outhandle
, reason
);
1004 if (result
->inhandle
!= OSP_INVALID_HANDLE
) {
1005 OSPPTransactionRecordFailure(result
->inhandle
, OSPC_FAIL_NO_ROUTE_TO_DEST
);
1010 while(result
->numresults
) {
1011 result
->outcallid
.len
= sizeof(result
->outcallid
.buf
);
1012 tokenlen
= sizeof(token
);
1013 error
= OSPPTransactionGetNextDestination(
1019 &result
->outtimelimit
,
1020 &result
->outcallid
.len
,
1021 result
->outcallid
.buf
,
1026 sizeof(destination
),
1032 if (error
== OSPC_ERR_NO_ERROR
) {
1033 result
->numresults
--;
1034 result
->outtimelimit
= osp_choose_timelimit(result
->intimelimit
, result
->outtimelimit
);
1035 ast_debug(1, "OSP: outtimelimit '%d'\n", result
->outtimelimit
);
1036 ast_debug(1, "OSP: called '%s'\n", callednum
);
1037 ast_debug(1, "OSP: calling '%s'\n", callingnum
);
1038 ast_debug(1, "OSP: destination '%s'\n", destination
);
1039 ast_debug(1, "OSP: token size '%d'\n", tokenlen
);
1041 if ((res
= osp_check_destination(p
, callednum
, callingnum
, destination
, tokenlen
, token
, &reason
, result
)) > 0) {
1043 } else if (!result
->numresults
) {
1044 ast_debug(1, "OSP: No more destination\n");
1045 OSPPTransactionRecordFailure(result
->outhandle
, reason
);
1046 if (result
->inhandle
!= OSP_INVALID_HANDLE
) {
1047 OSPPTransactionRecordFailure(result
->inhandle
, OSPC_FAIL_NO_ROUTE_TO_DEST
);
1053 ast_debug(1, "OSP: Unable to get route, error '%d'\n", error
);
1054 result
->numresults
= 0;
1055 result
->outtimelimit
= OSP_DEF_TIMELIMIT
;
1056 if (result
->inhandle
!= OSP_INVALID_HANDLE
) {
1057 OSPPTransactionRecordFailure(result
->inhandle
, OSPC_FAIL_NORMAL_UNSPECIFIED
);
1067 * \brief OSP Lookup Next function
1068 * \param provider OSP provider name
1069 * \param cause Asterisk hangup cuase
1070 * \param result Lookup results, in/output
1071 * \return 1 Found , 0 No route, -1 Error
1073 static int osp_next(
1074 const char* provider
,
1076 struct osp_result
* result
)
1079 struct osp_provider
* p
;
1080 char callingnum
[OSP_NORSTR_SIZE
];
1081 char callednum
[OSP_NORSTR_SIZE
];
1082 char destination
[OSP_NORSTR_SIZE
];
1083 unsigned int tokenlen
;
1084 char token
[OSP_TOKSTR_SIZE
];
1085 enum OSPEFAILREASON reason
;
1088 result
->tech
[0] = '\0';
1089 result
->dest
[0] = '\0';
1090 result
->called
[0] = '\0';
1091 result
->calling
[0] = '\0';
1092 result
->token
[0] = '\0';
1093 result
->networkid
[0] = '\0';
1094 result
->outtimelimit
= OSP_DEF_TIMELIMIT
;
1096 if ((res
= osp_get_provider(provider
, &p
)) <= 0) {
1097 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", provider
);
1101 if (result
->outhandle
== OSP_INVALID_HANDLE
) {
1102 ast_debug(1, "OSP: Transaction handle undefined\n");
1103 result
->numresults
= 0;
1104 if (result
->inhandle
!= OSP_INVALID_HANDLE
) {
1105 OSPPTransactionRecordFailure(result
->inhandle
, OSPC_FAIL_NORMAL_UNSPECIFIED
);
1110 reason
= asterisk2osp(cause
);
1112 if (!result
->numresults
) {
1113 ast_debug(1, "OSP: No more destination\n");
1114 OSPPTransactionRecordFailure(result
->outhandle
, reason
);
1115 if (result
->inhandle
!= OSP_INVALID_HANDLE
) {
1116 OSPPTransactionRecordFailure(result
->inhandle
, OSPC_FAIL_NO_ROUTE_TO_DEST
);
1121 while(result
->numresults
) {
1122 result
->outcallid
.len
= sizeof(result
->outcallid
.buf
);
1123 tokenlen
= sizeof(token
);
1124 error
= OSPPTransactionGetNextDestination(
1130 &result
->outtimelimit
,
1131 &result
->outcallid
.len
,
1132 result
->outcallid
.buf
,
1137 sizeof(destination
),
1143 if (error
== OSPC_ERR_NO_ERROR
) {
1144 result
->numresults
--;
1145 result
->outtimelimit
= osp_choose_timelimit(result
->intimelimit
, result
->outtimelimit
);
1146 ast_debug(1, "OSP: outtimelimit '%d'\n", result
->outtimelimit
);
1147 ast_debug(1, "OSP: called '%s'\n", callednum
);
1148 ast_debug(1, "OSP: calling '%s'\n", callingnum
);
1149 ast_debug(1, "OSP: destination '%s'\n", destination
);
1150 ast_debug(1, "OSP: token size '%d'\n", tokenlen
);
1152 if ((res
= osp_check_destination(p
, callednum
, callingnum
, destination
, tokenlen
, token
, &reason
, result
)) > 0) {
1155 } else if (!result
->numresults
) {
1156 ast_debug(1, "OSP: No more destination\n");
1157 OSPPTransactionRecordFailure(result
->outhandle
, reason
);
1158 if (result
->inhandle
!= OSP_INVALID_HANDLE
) {
1159 OSPPTransactionRecordFailure(result
->inhandle
, OSPC_FAIL_NO_ROUTE_TO_DEST
);
1165 ast_debug(1, "OSP: Unable to get route, error '%d'\n", error
);
1166 result
->token
[0] = '\0';
1167 result
->numresults
= 0;
1168 result
->outtimelimit
= OSP_DEF_TIMELIMIT
;
1169 if (result
->inhandle
!= OSP_INVALID_HANDLE
) {
1170 OSPPTransactionRecordFailure(result
->inhandle
, OSPC_FAIL_NORMAL_UNSPECIFIED
);
1181 * \brief OSP Finish function
1182 * \param handle OSP in/outbound transaction handle
1183 * \param recorded If failure reason has been recorded
1184 * \param cause Asterisk hangup cause
1185 * \param start Call start time
1186 * \param connect Call connect time
1187 * \param end Call end time
1188 * \param release Who release first, 0 source, 1 destination
1189 * \return 1 Success, 0 Failed, -1 Error
1191 static int osp_finish(
1198 unsigned int release
)
1201 enum OSPEFAILREASON reason
;
1203 unsigned isPddInfoPresent
= 0;
1205 unsigned int dummy
= 0;
1208 if (handle
== OSP_INVALID_HANDLE
) {
1213 reason
= asterisk2osp(cause
);
1214 OSPPTransactionRecordFailure(handle
, reason
);
1217 error
= OSPPTransactionReportUsage(
1219 difftime(end
, connect
),
1234 if (error
== OSPC_ERR_NO_ERROR
) {
1235 ast_debug(1, "OSP: Usage reported\n");
1238 ast_debug(1, "OSP: Unable to report usage, error '%d'\n", error
);
1241 OSPPTransactionDelete(handle
);
1246 /* OSP Application APIs */
1249 * \brief OSP Application OSPAuth
1250 * \param chan Channel
1251 * \param data Parameter
1252 * \return 0 Success, -1 Failed
1254 static int ospauth_exec(
1255 struct ast_channel
* chan
,
1259 const char* provider
= OSP_DEF_PROVIDER
;
1260 struct varshead
* headp
;
1261 struct ast_var_t
* current
;
1262 const char* source
= "";
1263 const char* token
= "";
1265 unsigned int timelimit
;
1266 char buffer
[OSP_INTSTR_SIZE
];
1270 AST_DECLARE_APP_ARGS(args
,
1271 AST_APP_ARG(provider
);
1272 AST_APP_ARG(options
);
1275 if (!(tmp
= ast_strdupa(data
))) {
1276 ast_log(LOG_ERROR
, "Out of memory\n");
1280 AST_STANDARD_APP_ARGS(args
, tmp
);
1282 if (!ast_strlen_zero(args
.provider
)) {
1283 provider
= args
.provider
;
1285 ast_debug(1, "OSPAuth: provider '%s'\n", provider
);
1287 headp
= &chan
->varshead
;
1288 AST_LIST_TRAVERSE(headp
, current
, entries
) {
1289 if (!strcasecmp(ast_var_name(current
), "OSPPEERIP")) {
1290 source
= ast_var_value(current
);
1291 } else if (!strcasecmp(ast_var_name(current
), "OSPINTOKEN")) {
1292 token
= ast_var_value(current
);
1296 ast_debug(1, "OSPAuth: source '%s'\n", source
);
1297 ast_debug(1, "OSPAuth: token size '%zd'\n", strlen(token
));
1299 if ((res
= osp_auth(provider
, &handle
, source
, chan
->cid
.cid_num
, chan
->exten
, token
, &timelimit
)) > 0) {
1300 status
= AST_OSP_SUCCESS
;
1302 timelimit
= OSP_DEF_TIMELIMIT
;
1304 status
= AST_OSP_FAILED
;
1306 status
= AST_OSP_ERROR
;
1310 snprintf(buffer
, sizeof(buffer
), "%d", handle
);
1311 pbx_builtin_setvar_helper(chan
, "OSPINHANDLE", buffer
);
1312 ast_debug(1, "OSPAuth: OSPINHANDLE '%s'\n", buffer
);
1313 snprintf(buffer
, sizeof(buffer
), "%d", timelimit
);
1314 pbx_builtin_setvar_helper(chan
, "OSPINTIMELIMIT", buffer
);
1315 ast_debug(1, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer
);
1316 pbx_builtin_setvar_helper(chan
, "OSPAUTHSTATUS", status
);
1317 ast_debug(1, "OSPAuth: %s\n", status
);
1329 * \brief OSP Application OSPLookup
1330 * \param chan Channel
1331 * \param data Parameter
1332 * \return 0 Success, -1 Failed
1334 static int osplookup_exec(
1335 struct ast_channel
* chan
,
1339 const char* provider
= OSP_DEF_PROVIDER
;
1340 struct varshead
* headp
;
1341 struct ast_var_t
* current
;
1342 const char* srcdev
= "";
1343 const char* netid
= "";
1344 char buffer
[OSP_TOKSTR_SIZE
];
1345 unsigned int callidtypes
= OSP_CALLID_UNDEFINED
;
1346 struct osp_result result
;
1350 AST_DECLARE_APP_ARGS(args
,
1352 AST_APP_ARG(provider
);
1353 AST_APP_ARG(options
);
1356 if (ast_strlen_zero(data
)) {
1357 ast_log(LOG_WARNING
, "OSPLookup: Arg required, OSPLookup(exten[|provider[|options]])\n");
1361 if (!(tmp
= ast_strdupa(data
))) {
1362 ast_log(LOG_ERROR
, "Out of memory\n");
1366 AST_STANDARD_APP_ARGS(args
, tmp
);
1368 ast_debug(1, "OSPLookup: exten '%s'\n", args
.exten
);
1370 if (!ast_strlen_zero(args
.provider
)) {
1371 provider
= args
.provider
;
1373 ast_debug(1, "OSPlookup: provider '%s'\n", provider
);
1376 if (strchr(args
.options
, 'h')) {
1377 callidtypes
|= OSP_CALLID_H323
;
1379 if (strchr(args
.options
, 's')) {
1380 callidtypes
|= OSP_CALLID_SIP
;
1382 if (strchr(args
.options
, 'i')) {
1383 callidtypes
|= OSP_CALLID_IAX
;
1386 ast_debug(1, "OSPLookup: call id types '%d'\n", callidtypes
);
1388 result
.inhandle
= OSP_INVALID_HANDLE
;
1389 result
.intimelimit
= OSP_DEF_TIMELIMIT
;
1391 headp
= &chan
->varshead
;
1392 AST_LIST_TRAVERSE(headp
, current
, entries
) {
1393 if (!strcasecmp(ast_var_name(current
), "OSPINHANDLE")) {
1394 if (sscanf(ast_var_value(current
), "%d", &result
.inhandle
) != 1) {
1395 result
.inhandle
= OSP_INVALID_HANDLE
;
1397 } else if (!strcasecmp(ast_var_name(current
), "OSPINTIMELIMIT")) {
1398 if (sscanf(ast_var_value(current
), "%d", &result
.intimelimit
) != 1) {
1399 result
.intimelimit
= OSP_DEF_TIMELIMIT
;
1401 } else if (!strcasecmp(ast_var_name(current
), "OSPINNETWORKID")) {
1402 netid
= ast_var_value(current
);
1403 } else if (!strcasecmp(ast_var_name(current
), "OSPPEERIP")) {
1404 srcdev
= ast_var_value(current
);
1407 ast_debug(1, "OSPLookup: OSPINHANDLE '%d'\n", result
.inhandle
);
1408 ast_debug(1, "OSPLookup: OSPINTIMELIMIT '%d'\n", result
.intimelimit
);
1409 ast_debug(1, "OSPLookup: OSPINNETWORKID '%s'\n", netid
);
1410 ast_debug(1, "OSPLookup: source device '%s'\n", srcdev
);
1412 if ((cres
= ast_autoservice_start(chan
)) < 0) {
1416 if ((res
= osp_lookup(provider
, srcdev
, chan
->cid
.cid_num
, args
.exten
, callidtypes
, &result
)) > 0) {
1417 status
= AST_OSP_SUCCESS
;
1419 result
.tech
[0] = '\0';
1420 result
.dest
[0] = '\0';
1421 result
.called
[0] = '\0';
1422 result
.calling
[0] = '\0';
1423 result
.token
[0] = '\0';
1424 result
.networkid
[0] = '\0';
1425 result
.numresults
= 0;
1426 result
.outtimelimit
= OSP_DEF_TIMELIMIT
;
1427 result
.outcallid
.buf
[0] = '\0';
1428 result
.outcallid
.len
= 0;
1430 status
= AST_OSP_FAILED
;
1432 status
= AST_OSP_ERROR
;
1436 snprintf(buffer
, sizeof(buffer
), "%d", result
.outhandle
);
1437 pbx_builtin_setvar_helper(chan
, "OSPOUTHANDLE", buffer
);
1438 ast_debug(1, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer
);
1439 pbx_builtin_setvar_helper(chan
, "OSPTECH", result
.tech
);
1440 ast_debug(1, "OSPLookup: OSPTECH '%s'\n", result
.tech
);
1441 pbx_builtin_setvar_helper(chan
, "OSPDEST", result
.dest
);
1442 ast_debug(1, "OSPLookup: OSPDEST '%s'\n", result
.dest
);
1443 pbx_builtin_setvar_helper(chan
, "OSPCALLED", result
.called
);
1444 ast_debug(1, "OSPLookup: OSPCALLED '%s'\n", result
.called
);
1445 pbx_builtin_setvar_helper(chan
, "OSPCALLING", result
.calling
);
1446 ast_debug(1, "OSPLookup: OSPCALLING '%s'\n", result
.calling
);
1447 pbx_builtin_setvar_helper(chan
, "OSPOUTTOKEN", result
.token
);
1448 ast_debug(1, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(result
.token
));
1449 snprintf(buffer
, sizeof(buffer
), "%d", result
.numresults
);
1450 pbx_builtin_setvar_helper(chan
, "OSPRESULTS", buffer
);
1451 ast_debug(1, "OSPLookup: OSPRESULTS '%s'\n", buffer
);
1452 snprintf(buffer
, sizeof(buffer
), "%d", result
.outtimelimit
);
1453 pbx_builtin_setvar_helper(chan
, "OSPOUTTIMELIMIT", buffer
);
1454 ast_debug(1, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer
);
1455 snprintf(buffer
, sizeof(buffer
), "%d", callidtypes
);
1456 pbx_builtin_setvar_helper(chan
, "OSPOUTCALLIDTYPES", buffer
);
1457 ast_debug(1, "OSPLookup: OSPOUTCALLIDTYPES '%s'\n", buffer
);
1458 pbx_builtin_setvar_helper(chan
, "OSPLOOKUPSTATUS", status
);
1459 ast_debug(1, "OSPLookup: %s\n", status
);
1461 if (!strcasecmp(result
.tech
, OSP_TECH_H323
)) {
1462 if ((callidtypes
& OSP_CALLID_H323
) && (result
.outcallid
.len
!= 0)) {
1463 osp_uuid2str(result
.outcallid
.buf
, buffer
, sizeof(buffer
));
1467 pbx_builtin_setvar_helper(chan
, "OSPOUTCALLID", buffer
);
1468 snprintf(buffer
, sizeof(buffer
), "%s/%s@%s", result
.tech
, result
.called
, result
.dest
);
1469 pbx_builtin_setvar_helper(chan
, "OSPDIALSTR", buffer
);
1470 } else if (!strcasecmp(result
.tech
, OSP_TECH_SIP
)) {
1471 snprintf(buffer
, sizeof(buffer
), "%s/%s@%s", result
.tech
, result
.called
, result
.dest
);
1472 pbx_builtin_setvar_helper(chan
, "OSPDIALSTR", buffer
);
1473 if (!ast_strlen_zero(result
.token
)) {
1474 snprintf(buffer
, sizeof(buffer
), "%s%s", OSP_SIP_HEADER
, result
.token
);
1475 pbx_builtin_setvar_helper(chan
, "_SIPADDHEADER", buffer
);
1476 ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer
));
1478 } else if (!strcasecmp(result
.tech
, OSP_TECH_IAX
)) {
1479 snprintf(buffer
, sizeof(buffer
), "%s/%s/%s", result
.tech
, result
.dest
, result
.called
);
1480 pbx_builtin_setvar_helper(chan
, "OSPDIALSTR", buffer
);
1483 if ((cres
= ast_autoservice_stop(chan
)) < 0) {
1497 * \brief OSP Application OSPNext
1498 * \param chan Channel
1499 * \param data Parameter
1500 * \return 0 Success, -1 Failed
1502 static int ospnext_exec(
1503 struct ast_channel
* chan
,
1507 const char* provider
= OSP_DEF_PROVIDER
;
1509 struct varshead
* headp
;
1510 struct ast_var_t
* current
;
1511 struct osp_result result
;
1512 char buffer
[OSP_TOKSTR_SIZE
];
1513 unsigned int callidtypes
= OSP_CALLID_UNDEFINED
;
1517 AST_DECLARE_APP_ARGS(args
,
1519 AST_APP_ARG(provider
);
1520 AST_APP_ARG(options
);
1523 if (ast_strlen_zero(data
)) {
1524 ast_log(LOG_WARNING
, "OSPNext: Arg required, OSPNext(cause[|provider[|options]])\n");
1528 if (!(tmp
= ast_strdupa(data
))) {
1529 ast_log(LOG_ERROR
, "Out of memory\n");
1533 AST_STANDARD_APP_ARGS(args
, tmp
);
1535 if (!ast_strlen_zero(args
.cause
) && sscanf(args
.cause
, "%d", &cause
) != 1) {
1538 ast_debug(1, "OSPNext: cause '%d'\n", cause
);
1540 if (!ast_strlen_zero(args
.provider
)) {
1541 provider
= args
.provider
;
1543 ast_debug(1, "OSPlookup: provider '%s'\n", provider
);
1545 result
.inhandle
= OSP_INVALID_HANDLE
;
1546 result
.outhandle
= OSP_INVALID_HANDLE
;
1547 result
.intimelimit
= OSP_DEF_TIMELIMIT
;
1548 result
.numresults
= 0;
1550 headp
= &chan
->varshead
;
1551 AST_LIST_TRAVERSE(headp
, current
, entries
) {
1552 if (!strcasecmp(ast_var_name(current
), "OSPINHANDLE")) {
1553 if (sscanf(ast_var_value(current
), "%d", &result
.inhandle
) != 1) {
1554 result
.inhandle
= OSP_INVALID_HANDLE
;
1556 } else if (!strcasecmp(ast_var_name(current
), "OSPOUTHANDLE")) {
1557 if (sscanf(ast_var_value(current
), "%d", &result
.outhandle
) != 1) {
1558 result
.outhandle
= OSP_INVALID_HANDLE
;
1560 } else if (!strcasecmp(ast_var_name(current
), "OSPINTIMELIMIT")) {
1561 if (sscanf(ast_var_value(current
), "%d", &result
.intimelimit
) != 1) {
1562 result
.intimelimit
= OSP_DEF_TIMELIMIT
;
1564 } else if (!strcasecmp(ast_var_name(current
), "OSPOUTCALLIDTYPES")) {
1565 if (sscanf(ast_var_value(current
), "%d", &callidtypes
) != 1) {
1566 callidtypes
= OSP_CALLID_UNDEFINED
;
1568 } else if (!strcasecmp(ast_var_name(current
), "OSPRESULTS")) {
1569 if (sscanf(ast_var_value(current
), "%d", &result
.numresults
) != 1) {
1570 result
.numresults
= 0;
1574 ast_debug(1, "OSPNext: OSPINHANDLE '%d'\n", result
.inhandle
);
1575 ast_debug(1, "OSPNext: OSPOUTHANDLE '%d'\n", result
.outhandle
);
1576 ast_debug(1, "OSPNext: OSPINTIMELIMIT '%d'\n", result
.intimelimit
);
1577 ast_debug(1, "OSPNext: OSPOUTCALLIDTYPES '%d'\n", callidtypes
);
1578 ast_debug(1, "OSPNext: OSPRESULTS '%d'\n", result
.numresults
);
1580 if ((res
= osp_next(provider
, cause
, &result
)) > 0) {
1581 status
= AST_OSP_SUCCESS
;
1583 result
.tech
[0] = '\0';
1584 result
.dest
[0] = '\0';
1585 result
.called
[0] = '\0';
1586 result
.calling
[0] = '\0';
1587 result
.token
[0] = '\0';
1588 result
.networkid
[0] = '\0';
1589 result
.numresults
= 0;
1590 result
.outtimelimit
= OSP_DEF_TIMELIMIT
;
1591 result
.outcallid
.buf
[0] = '\0';
1592 result
.outcallid
.len
= 0;
1594 status
= AST_OSP_FAILED
;
1596 status
= AST_OSP_ERROR
;
1600 pbx_builtin_setvar_helper(chan
, "OSPTECH", result
.tech
);
1601 ast_debug(1, "OSPNext: OSPTECH '%s'\n", result
.tech
);
1602 pbx_builtin_setvar_helper(chan
, "OSPDEST", result
.dest
);
1603 ast_debug(1, "OSPNext: OSPDEST '%s'\n", result
.dest
);
1604 pbx_builtin_setvar_helper(chan
, "OSPCALLED", result
.called
);
1605 ast_debug(1, "OSPNext: OSPCALLED'%s'\n", result
.called
);
1606 pbx_builtin_setvar_helper(chan
, "OSPCALLING", result
.calling
);
1607 ast_debug(1, "OSPNext: OSPCALLING '%s'\n", result
.calling
);
1608 pbx_builtin_setvar_helper(chan
, "OSPOUTTOKEN", result
.token
);
1609 ast_debug(1, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(result
.token
));
1610 snprintf(buffer
, sizeof(buffer
), "%d", result
.numresults
);
1611 pbx_builtin_setvar_helper(chan
, "OSPRESULTS", buffer
);
1612 ast_debug(1, "OSPNext: OSPRESULTS '%s'\n", buffer
);
1613 snprintf(buffer
, sizeof(buffer
), "%d", result
.outtimelimit
);
1614 pbx_builtin_setvar_helper(chan
, "OSPOUTTIMELIMIT", buffer
);
1615 ast_debug(1, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer
);
1616 pbx_builtin_setvar_helper(chan
, "OSPNEXTSTATUS", status
);
1617 ast_debug(1, "OSPNext: %s\n", status
);
1619 if (!strcasecmp(result
.tech
, OSP_TECH_H323
)) {
1620 if ((callidtypes
& OSP_CALLID_H323
) && (result
.outcallid
.len
!= 0)) {
1621 osp_uuid2str(result
.outcallid
.buf
, buffer
, sizeof(buffer
));
1625 pbx_builtin_setvar_helper(chan
, "OSPOUTCALLID", buffer
);
1626 snprintf(buffer
, sizeof(buffer
), "%s/%s@%s", result
.tech
, result
.called
, result
.dest
);
1627 pbx_builtin_setvar_helper(chan
, "OSPDIALSTR", buffer
);
1628 } else if (!strcasecmp(result
.tech
, OSP_TECH_SIP
)) {
1629 snprintf(buffer
, sizeof(buffer
), "%s/%s@%s", result
.tech
, result
.called
, result
.dest
);
1630 pbx_builtin_setvar_helper(chan
, "OSPDIALSTR", buffer
);
1631 if (!ast_strlen_zero(result
.token
)) {
1632 snprintf(buffer
, sizeof(buffer
), "%s%s", OSP_SIP_HEADER
, result
.token
);
1633 pbx_builtin_setvar_helper(chan
, "_SIPADDHEADER", buffer
);
1634 ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer
));
1636 } else if (!strcasecmp(result
.tech
, OSP_TECH_IAX
)) {
1637 snprintf(buffer
, sizeof(buffer
), "%s/%s/%s", result
.tech
, result
.dest
, result
.called
);
1638 pbx_builtin_setvar_helper(chan
, "OSPDIALSTR", buffer
);
1651 * \brief OSP Application OSPFinish
1652 * \param chan Channel
1653 * \param data Parameter
1654 * \return 0 Success, -1 Failed
1656 static int ospfinished_exec(
1657 struct ast_channel
* chan
,
1662 struct varshead
* headp
;
1663 struct ast_var_t
* current
;
1664 int inhandle
= OSP_INVALID_HANDLE
;
1665 int outhandle
= OSP_INVALID_HANDLE
;
1667 time_t start
, connect
, end
;
1668 unsigned int release
;
1669 char buffer
[OSP_INTSTR_SIZE
];
1673 AST_DECLARE_APP_ARGS(args
,
1675 AST_APP_ARG(options
);
1678 if (!(tmp
= ast_strdupa(data
))) {
1679 ast_log(LOG_ERROR
, "Out of memory\n");
1683 AST_STANDARD_APP_ARGS(args
, tmp
);
1685 headp
= &chan
->varshead
;
1686 AST_LIST_TRAVERSE(headp
, current
, entries
) {
1687 if (!strcasecmp(ast_var_name(current
), "OSPINHANDLE")) {
1688 if (sscanf(ast_var_value(current
), "%d", &inhandle
) != 1) {
1689 inhandle
= OSP_INVALID_HANDLE
;
1691 } else if (!strcasecmp(ast_var_name(current
), "OSPOUTHANDLE")) {
1692 if (sscanf(ast_var_value(current
), "%d", &outhandle
) != 1) {
1693 outhandle
= OSP_INVALID_HANDLE
;
1695 } else if (!recorded
&&
1696 (!strcasecmp(ast_var_name(current
), "OSPAUTHSTATUS") ||
1697 !strcasecmp(ast_var_name(current
), "OSPLOOKUPSTATUS") ||
1698 !strcasecmp(ast_var_name(current
), "OSPNEXTSTATUS")))
1700 if (strcasecmp(ast_var_value(current
), AST_OSP_SUCCESS
)) {
1705 ast_debug(1, "OSPFinish: OSPINHANDLE '%d'\n", inhandle
);
1706 ast_debug(1, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle
);
1707 ast_debug(1, "OSPFinish: recorded '%d'\n", recorded
);
1709 if (!ast_strlen_zero(args
.cause
) && sscanf(args
.cause
, "%d", &cause
) != 1) {
1712 ast_debug(1, "OSPFinish: cause '%d'\n", cause
);
1715 start
= chan
->cdr
->start
.tv_sec
;
1716 connect
= chan
->cdr
->answer
.tv_sec
;
1727 ast_debug(1, "OSPFinish: start '%ld'\n", start
);
1728 ast_debug(1, "OSPFinish: connect '%ld'\n", connect
);
1729 ast_debug(1, "OSPFinish: end '%ld'\n", end
);
1731 release
= ast_check_hangup(chan
) ? 0 : 1;
1733 if (osp_finish(outhandle
, recorded
, cause
, start
, connect
, end
, release
) <= 0) {
1734 ast_debug(1, "OSPFinish: Unable to report usage for outbound call\n");
1737 case AST_CAUSE_NORMAL_CLEARING
:
1740 cause
= AST_CAUSE_NO_ROUTE_DESTINATION
;
1743 if (osp_finish(inhandle
, recorded
, cause
, start
, connect
, end
, release
) <= 0) {
1744 ast_debug(1, "OSPFinish: Unable to report usage for inbound call\n");
1746 snprintf(buffer
, sizeof(buffer
), "%d", OSP_INVALID_HANDLE
);
1747 pbx_builtin_setvar_helper(chan
, "OSPOUTHANDLE", buffer
);
1748 pbx_builtin_setvar_helper(chan
, "OSPINHANDLE", buffer
);
1751 status
= AST_OSP_SUCCESS
;
1753 status
= AST_OSP_FAILED
;
1755 status
= AST_OSP_ERROR
;
1757 pbx_builtin_setvar_helper(chan
, "OSPFINISHSTATUS", status
);
1768 /* OSP Module APIs */
1770 static int osp_unload(void);
1771 static int osp_load(int reload
)
1775 struct ast_config
* cfg
;
1776 struct ast_flags config_flags
= { reload
? CONFIG_FLAG_FILEUNCHANGED
: 0 };
1777 int error
= OSPC_ERR_NO_ERROR
;
1779 if ((cfg
= ast_config_load(OSP_CONFIG_FILE
, config_flags
)) == CONFIG_STATUS_FILEUNCHANGED
)
1786 t
= ast_variable_retrieve(cfg
, OSP_GENERAL_CAT
, "accelerate");
1787 if (t
&& ast_true(t
)) {
1788 if ((error
= OSPPInit(1)) != OSPC_ERR_NO_ERROR
) {
1789 ast_log(LOG_WARNING
, "OSP: Unable to enable hardware accelleration\n");
1797 ast_debug(1, "OSP: osp_hardware '%d'\n", osp_hardware
);
1799 t
= ast_variable_retrieve(cfg
, OSP_GENERAL_CAT
, "tokenformat");
1801 if ((sscanf(t
, "%d", &v
) == 1) &&
1802 ((v
== TOKEN_ALGO_SIGNED
) || (v
== TOKEN_ALGO_UNSIGNED
) || (v
== TOKEN_ALGO_BOTH
)))
1804 osp_tokenformat
= v
;
1806 ast_log(LOG_WARNING
, "tokenformat should be an integer from %d, %d or %d, not '%s'\n",
1807 TOKEN_ALGO_SIGNED
, TOKEN_ALGO_UNSIGNED
, TOKEN_ALGO_BOTH
, t
);
1810 ast_debug(1, "OSP: osp_tokenformat '%d'\n", osp_tokenformat
);
1812 t
= ast_category_browse(cfg
, NULL
);
1814 if (strcasecmp(t
, OSP_GENERAL_CAT
)) {
1815 osp_create_provider(cfg
, t
);
1817 t
= ast_category_browse(cfg
, t
);
1820 osp_initialized
= 1;
1822 ast_config_destroy(cfg
);
1824 ast_log(LOG_WARNING
, "OSP: Unable to find configuration. OSP support disabled\n");
1827 ast_debug(1, "OSP: osp_initialized '%d'\n", osp_initialized
);
1832 static int osp_unload(void)
1834 struct osp_provider
* p
;
1835 struct osp_provider
* next
;
1837 if (osp_initialized
) {
1838 ast_mutex_lock(&osplock
);
1842 OSPPProviderDelete(p
->handle
, 0);
1846 ospproviders
= NULL
;
1847 ast_mutex_unlock(&osplock
);
1851 osp_tokenformat
= TOKEN_ALGO_SIGNED
;
1853 osp_initialized
= 0;
1858 static char *handle_cli_osp_show(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
1862 struct osp_provider
* p
;
1863 const char* provider
= NULL
;
1864 const char* tokenalgo
;
1868 e
->command
= "osp show";
1871 " Displays information on Open Settlement Protocol support\n";
1877 if ((a
->argc
< 2) || (a
->argc
> 3))
1878 return CLI_SHOWUSAGE
;
1880 provider
= a
->argv
[2];
1882 switch (osp_tokenformat
) {
1883 case TOKEN_ALGO_BOTH
:
1886 case TOKEN_ALGO_UNSIGNED
:
1887 tokenalgo
= "Unsigned";
1889 case TOKEN_ALGO_SIGNED
:
1891 tokenalgo
= "Signed";
1894 ast_cli(a
->fd
, "OSP: %s %s %s\n",
1895 osp_initialized
? "Initialized" : "Uninitialized", osp_hardware
? "Accelerated" : "Normal", tokenalgo
);
1898 ast_mutex_lock(&osplock
);
1901 if (!provider
|| !strcasecmp(p
->name
, provider
)) {
1903 ast_cli(a
->fd
, "\n");
1905 ast_cli(a
->fd
, " == OSP Provider '%s' == \n", p
->name
);
1906 ast_cli(a
->fd
, "Local Private Key: %s\n", p
->privatekey
);
1907 ast_cli(a
->fd
, "Local Certificate: %s\n", p
->localcert
);
1908 for (i
= 0; i
< p
->cacount
; i
++) {
1909 ast_cli(a
->fd
, "CA Certificate %d: %s\n", i
+ 1, p
->cacerts
[i
]);
1911 for (i
= 0; i
< p
->spcount
; i
++) {
1912 ast_cli(a
->fd
, "Service Point %d: %s\n", i
+ 1, p
->srvpoints
[i
]);
1914 ast_cli(a
->fd
, "Max Connections: %d\n", p
->maxconnections
);
1915 ast_cli(a
->fd
, "Retry Delay: %d seconds\n", p
->retrydelay
);
1916 ast_cli(a
->fd
, "Retry Limit: %d\n", p
->retrylimit
);
1917 ast_cli(a
->fd
, "Timeout: %d milliseconds\n", p
->timeout
);
1918 ast_cli(a
->fd
, "Source: %s\n", strlen(p
->source
) ? p
->source
: "<unspecified>");
1919 ast_cli(a
->fd
, "Auth Policy %d\n", p
->authpolicy
);
1920 ast_cli(a
->fd
, "Default protocol %s\n", p
->defaultprotocol
);
1921 ast_cli(a
->fd
, "OSP Handle: %d\n", p
->handle
);
1926 ast_mutex_unlock(&osplock
);
1930 ast_cli(a
->fd
, "Unable to find OSP provider '%s'\n", provider
);
1932 ast_cli(a
->fd
, "No OSP providers configured\n");
1938 static const char* app1
= "OSPAuth";
1939 static const char* synopsis1
= "OSP authentication";
1940 static const char* descrip1
=
1941 " OSPAuth([provider[,options]]): Authenticate a SIP INVITE by OSP and sets\n"
1943 " ${OSPINHANDLE}: The inbound call transaction handle\n"
1944 " ${OSPINTIMELIMIT}: The inbound call duration limit in seconds\n"
1946 "This application sets the following channel variable upon completion:\n"
1947 " OSPAUTHSTATUS The status of the OSP Auth attempt as a text string, one of\n"
1948 " SUCCESS | FAILED | ERROR\n";
1950 static const char* app2
= "OSPLookup";
1951 static const char* synopsis2
= "Lookup destination by OSP";
1952 static const char* descrip2
=
1953 " OSPLookup(exten[,provider[,options]]): Looks up an extension via OSP and sets\n"
1954 "the variables, where 'n' is the number of the result beginning with 1:\n"
1955 " ${OSPOUTHANDLE}: The OSP Handle for anything remaining\n"
1956 " ${OSPTECH}: The technology to use for the call\n"
1957 " ${OSPDEST}: The destination to use for the call\n"
1958 " ${OSPCALLED}: The called number to use for the call\n"
1959 " ${OSPCALLING}: The calling number to use for the call\n"
1960 " ${OSPDIALSTR}: The dial command string\n"
1961 " ${OSPOUTTOKEN}: The actual OSP token as a string\n"
1962 " ${OSPOUTTIMELIMIT}: The outbound call duration limit in seconds\n"
1963 " ${OSPOUTCALLIDTYPES}: The outbound call id types\n"
1964 " ${OSPOUTCALLID}: The outbound call id\n"
1965 " ${OSPRESULTS}: The number of OSP results total remaining\n"
1967 "The option string may contain the following character:\n"
1968 " 'h' -- generate H323 call id for the outbound call\n"
1969 " 's' -- generate SIP call id for the outbound call. Have not been implemented\n"
1970 " 'i' -- generate IAX call id for the outbound call. Have not been implemented\n"
1971 "This application sets the following channel variable upon completion:\n"
1972 " OSPLOOKUPSTATUS The status of the OSP Lookup attempt as a text string, one of\n"
1973 " SUCCESS | FAILED | ERROR\n";
1975 static const char* app3
= "OSPNext";
1976 static const char* synopsis3
= "Lookup next destination by OSP";
1977 static const char* descrip3
=
1978 " OSPNext(cause[,provider[,options]]): Looks up the next OSP Destination for ${OSPOUTHANDLE}\n"
1979 "See OSPLookup for more information\n"
1981 "This application sets the following channel variable upon completion:\n"
1982 " OSPNEXTSTATUS The status of the OSP Next attempt as a text string, one of\n"
1983 " SUCCESS | FAILED | ERROR\n";
1985 static const char* app4
= "OSPFinish";
1986 static const char* synopsis4
= "Record OSP entry";
1987 static const char* descrip4
=
1988 " OSPFinish([status[,options]]): Records call state for ${OSPINHANDLE}, according to\n"
1989 "status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or CHANUNAVAIL\n"
1990 "or coincidentally, just what the Dial application stores in its ${DIALSTATUS}.\n"
1992 "This application sets the following channel variable upon completion:\n"
1993 " OSPFINISHSTATUS The status of the OSP Finish attempt as a text string, one of\n"
1994 " SUCCESS | FAILED | ERROR \n";
1996 static struct ast_cli_entry cli_osp
[] = {
1997 AST_CLI_DEFINE(handle_cli_osp_show
, "Displays OSF information")
2000 static int load_module(void)
2005 return AST_MODULE_LOAD_DECLINE
;
2007 ast_cli_register_multiple(cli_osp
, sizeof(cli_osp
) / sizeof(struct ast_cli_entry
));
2008 res
= ast_register_application(app1
, ospauth_exec
, synopsis1
, descrip1
);
2009 res
|= ast_register_application(app2
, osplookup_exec
, synopsis2
, descrip2
);
2010 res
|= ast_register_application(app3
, ospnext_exec
, synopsis3
, descrip3
);
2011 res
|= ast_register_application(app4
, ospfinished_exec
, synopsis4
, descrip4
);
2016 static int unload_module(void)
2020 res
= ast_unregister_application(app4
);
2021 res
|= ast_unregister_application(app3
);
2022 res
|= ast_unregister_application(app2
);
2023 res
|= ast_unregister_application(app1
);
2024 ast_cli_unregister_multiple(cli_osp
, sizeof(cli_osp
) / sizeof(struct ast_cli_entry
));
2030 static int reload(void)
2037 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, "Open Settlement Protocol Applications",
2038 .load
= load_module
,
2039 .unload
= unload_module
,