00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "asterisk.h"
00037
00038 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 174440 $")
00039
00040 #include <osp/osp.h>
00041 #include <osp/osputils.h>
00042
00043 #include "asterisk/paths.h"
00044 #include "asterisk/lock.h"
00045 #include "asterisk/config.h"
00046 #include "asterisk/utils.h"
00047 #include "asterisk/causes.h"
00048 #include "asterisk/channel.h"
00049 #include "asterisk/app.h"
00050 #include "asterisk/module.h"
00051 #include "asterisk/pbx.h"
00052 #include "asterisk/cli.h"
00053 #include "asterisk/astosp.h"
00054
00055
00056 #define OSP_INTSTR_SIZE ((unsigned int)16)
00057 #define OSP_NORSTR_SIZE ((unsigned int)256)
00058 #define OSP_TOKSTR_SIZE ((unsigned int)4096)
00059 #define OSP_TECHSTR_SIZE ((unsigned int)32)
00060 #define OSP_UUID_SIZE ((unsigned int)16)
00061 #define OSP_UUIDSTR_SIZE ((unsigned int)36)
00062
00063
00064 enum osp_authpolicy {
00065 OSP_AUTH_NO,
00066 OSP_AUTH_YES,
00067 OSP_AUTH_EXCLUSIVE
00068 };
00069
00070
00071 #define OSP_CALLID_UNDEFINED ((unsigned int)0)
00072 #define OSP_CALLID_H323 ((unsigned int)(1 << 0))
00073 #define OSP_CALLID_SIP ((unsigned int)(1 << 1))
00074 #define OSP_CALLID_IAX ((unsigned int)(1 << 2))
00075 #define OSP_CALLID_MAXNUM ((unsigned int)3)
00076
00077
00078 #define OSP_PROT_H323 ((char*)"H323")
00079 #define OSP_PROT_SIP ((char*)"SIP")
00080 #define OSP_PROT_IAX ((char*)"IAX")
00081 #define OSP_PROT_OTHER ((char*)"OTHER")
00082
00083
00084 #if 0
00085 #define OSP_TECH_H323 ((char*)"OOH323")
00086 #endif
00087 #define OSP_TECH_H323 ((char*)"H323")
00088 #define OSP_TECH_SIP ((char*)"SIP")
00089 #define OSP_TECH_IAX ((char*)"IAX2")
00090
00091
00092 #define OSP_SIP_HEADER ((char*)"P-OSP-Auth-Token: ")
00093
00094
00095 #define OSP_INVALID_HANDLE ((int)-1)
00096 #define OSP_CONFIG_FILE ((const char*)"osp.conf")
00097 #define OSP_GENERAL_CAT ((const char*)"general")
00098 #define OSP_DEF_PROVIDER ((const char*)"default")
00099 #define OSP_MAX_CERTS ((unsigned int)10)
00100 #define OSP_MAX_SRVS ((unsigned int)10)
00101 #define OSP_DEF_MAXCONNECTIONS ((unsigned int)20)
00102 #define OSP_MIN_MAXCONNECTIONS ((unsigned int)1)
00103 #define OSP_MAX_MAXCONNECTIONS ((unsigned int)1000)
00104 #define OSP_DEF_RETRYDELAY ((unsigned int)0)
00105 #define OSP_MIN_RETRYDELAY ((unsigned int)0)
00106 #define OSP_MAX_RETRYDELAY ((unsigned int)10)
00107 #define OSP_DEF_RETRYLIMIT ((unsigned int)2)
00108 #define OSP_MIN_RETRYLIMIT ((unsigned int)0)
00109 #define OSP_MAX_RETRYLIMIT ((unsigned int)100)
00110 #define OSP_DEF_TIMEOUT ((unsigned int)500)
00111 #define OSP_MIN_TIMEOUT ((unsigned int)200)
00112 #define OSP_MAX_TIMEOUT ((unsigned int)10000)
00113 #define OSP_DEF_AUTHPOLICY ((enum osp_authpolicy)OSP_AUTH_YES)
00114 #define OSP_AUDIT_URL ((const char*)"localhost")
00115 #define OSP_LOCAL_VALIDATION ((int)1)
00116 #define OSP_SSL_LIFETIME ((unsigned int)300)
00117 #define OSP_HTTP_PERSISTENCE ((int)1)
00118 #define OSP_CUSTOMER_ID ((const char*)"")
00119 #define OSP_DEVICE_ID ((const char*)"")
00120 #define OSP_DEF_DESTINATIONS ((unsigned int)5)
00121 #define OSP_DEF_TIMELIMIT ((unsigned int)0)
00122 #define OSP_DEF_PROTOCOL OSP_PROT_SIP
00123
00124
00125 struct osp_provider {
00126 char name[OSP_NORSTR_SIZE];
00127 char privatekey[OSP_NORSTR_SIZE];
00128 char localcert[OSP_NORSTR_SIZE];
00129 unsigned int cacount;
00130 char cacerts[OSP_MAX_CERTS][OSP_NORSTR_SIZE];
00131 unsigned int spcount;
00132 char srvpoints[OSP_MAX_SRVS][OSP_NORSTR_SIZE];
00133 int maxconnections;
00134 int retrydelay;
00135 int retrylimit;
00136 int timeout;
00137 char source[OSP_NORSTR_SIZE];
00138 enum osp_authpolicy authpolicy;
00139 char* defaultprotocol;
00140 OSPTPROVHANDLE handle;
00141 struct osp_provider* next;
00142 };
00143
00144
00145 struct osp_callid {
00146 unsigned char buf[OSPC_CALLID_MAXSIZE];
00147 unsigned int len;
00148 };
00149
00150
00151 struct osp_result {
00152 int inhandle;
00153 int outhandle;
00154 unsigned int intimelimit;
00155 unsigned int outtimelimit;
00156 char tech[OSP_TECHSTR_SIZE];
00157 char dest[OSP_NORSTR_SIZE];
00158 char called[OSP_NORSTR_SIZE];
00159 char calling[OSP_NORSTR_SIZE];
00160 char token[OSP_TOKSTR_SIZE];
00161 char networkid[OSP_NORSTR_SIZE];
00162 unsigned int numresults;
00163 struct osp_callid outcallid;
00164 };
00165
00166
00167 AST_MUTEX_DEFINE_STATIC(osplock);
00168 static int osp_initialized = 0;
00169 static int osp_hardware = 0;
00170 static struct osp_provider* ospproviders = NULL;
00171 static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED;
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 static int osp_create_provider(
00182 struct ast_config* cfg,
00183 const char* provider)
00184 {
00185 int res;
00186 unsigned int t, i, j;
00187 struct osp_provider* p;
00188 struct ast_variable* v;
00189 OSPTPRIVATEKEY privatekey;
00190 OSPTCERT localcert;
00191 const char* psrvpoints[OSP_MAX_SRVS];
00192 OSPTCERT cacerts[OSP_MAX_CERTS];
00193 const OSPTCERT* pcacerts[OSP_MAX_CERTS];
00194 int error = OSPC_ERR_NO_ERROR;
00195
00196 if (!(p = ast_calloc(1, sizeof(*p)))) {
00197 ast_log(LOG_ERROR, "Out of memory\n");
00198 return -1;
00199 }
00200
00201 ast_copy_string(p->name, provider, sizeof(p->name));
00202 snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, provider);
00203 snprintf(p->localcert, sizeof(p->localcert), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, provider);
00204 p->maxconnections = OSP_DEF_MAXCONNECTIONS;
00205 p->retrydelay = OSP_DEF_RETRYDELAY;
00206 p->retrylimit = OSP_DEF_RETRYLIMIT;
00207 p->timeout = OSP_DEF_TIMEOUT;
00208 p->authpolicy = OSP_DEF_AUTHPOLICY;
00209 p->defaultprotocol = OSP_DEF_PROTOCOL;
00210 p->handle = OSP_INVALID_HANDLE;
00211
00212 v = ast_variable_browse(cfg, provider);
00213 while(v) {
00214 if (!strcasecmp(v->name, "privatekey")) {
00215 if (v->value[0] == '/') {
00216 ast_copy_string(p->privatekey, v->value, sizeof(p->privatekey));
00217 } else {
00218 snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s", ast_config_AST_KEY_DIR, v->value);
00219 }
00220 ast_debug(1, "OSP: privatekey '%s'\n", p->privatekey);
00221 } else if (!strcasecmp(v->name, "localcert")) {
00222 if (v->value[0] == '/') {
00223 ast_copy_string(p->localcert, v->value, sizeof(p->localcert));
00224 } else {
00225 snprintf(p->localcert, sizeof(p->localcert), "%s/%s", ast_config_AST_KEY_DIR, v->value);
00226 }
00227 ast_debug(1, "OSP: localcert '%s'\n", p->localcert);
00228 } else if (!strcasecmp(v->name, "cacert")) {
00229 if (p->cacount < OSP_MAX_CERTS) {
00230 if (v->value[0] == '/') {
00231 ast_copy_string(p->cacerts[p->cacount], v->value, sizeof(p->cacerts[0]));
00232 } else {
00233 snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s", ast_config_AST_KEY_DIR, v->value);
00234 }
00235 ast_debug(1, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
00236 p->cacount++;
00237 } else {
00238 ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", v->lineno);
00239 }
00240 } else if (!strcasecmp(v->name, "servicepoint")) {
00241 if (p->spcount < OSP_MAX_SRVS) {
00242 ast_copy_string(p->srvpoints[p->spcount], v->value, sizeof(p->srvpoints[0]));
00243 ast_debug(1, "OSP: servicepoint[%d]: '%s'\n", p->spcount, p->srvpoints[p->spcount]);
00244 p->spcount++;
00245 } else {
00246 ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", v->lineno);
00247 }
00248 } else if (!strcasecmp(v->name, "maxconnections")) {
00249 if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_MAXCONNECTIONS) && (t <= OSP_MAX_MAXCONNECTIONS)) {
00250 p->maxconnections = t;
00251 ast_debug(1, "OSP: maxconnections '%d'\n", t);
00252 } else {
00253 ast_log(LOG_WARNING, "OSP: maxconnections should be an integer from %d to %d, not '%s' at line %d\n",
00254 OSP_MIN_MAXCONNECTIONS, OSP_MAX_MAXCONNECTIONS, v->value, v->lineno);
00255 }
00256 } else if (!strcasecmp(v->name, "retrydelay")) {
00257 if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_RETRYDELAY) && (t <= OSP_MAX_RETRYDELAY)) {
00258 p->retrydelay = t;
00259 ast_debug(1, "OSP: retrydelay '%d'\n", t);
00260 } else {
00261 ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n",
00262 OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY, v->value, v->lineno);
00263 }
00264 } else if (!strcasecmp(v->name, "retrylimit")) {
00265 if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_RETRYLIMIT) && (t <= OSP_MAX_RETRYLIMIT)) {
00266 p->retrylimit = t;
00267 ast_debug(1, "OSP: retrylimit '%d'\n", t);
00268 } else {
00269 ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n",
00270 OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT, v->value, v->lineno);
00271 }
00272 } else if (!strcasecmp(v->name, "timeout")) {
00273 if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_TIMEOUT) && (t <= OSP_MAX_TIMEOUT)) {
00274 p->timeout = t;
00275 ast_debug(1, "OSP: timeout '%d'\n", t);
00276 } else {
00277 ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n",
00278 OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT, v->value, v->lineno);
00279 }
00280 } else if (!strcasecmp(v->name, "source")) {
00281 ast_copy_string(p->source, v->value, sizeof(p->source));
00282 ast_debug(1, "OSP: source '%s'\n", p->source);
00283 } else if (!strcasecmp(v->name, "authpolicy")) {
00284 if ((sscanf(v->value, "%d", &t) == 1) && ((t == OSP_AUTH_NO) || (t == OSP_AUTH_YES) || (t == OSP_AUTH_EXCLUSIVE))) {
00285 p->authpolicy = t;
00286 ast_debug(1, "OSP: authpolicy '%d'\n", t);
00287 } else {
00288 ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n",
00289 OSP_AUTH_NO, OSP_AUTH_YES, OSP_AUTH_EXCLUSIVE, v->value, v->lineno);
00290 }
00291 } else if (!strcasecmp(v->name, "defaultprotocol")) {
00292 if (!strcasecmp(v->value, OSP_PROT_SIP)) {
00293 p->defaultprotocol = OSP_PROT_SIP;
00294 ast_debug(1, "OSP: default protocol '%s'\n", p->defaultprotocol);
00295 } else if (!strcasecmp(v->value, OSP_PROT_H323)) {
00296 p->defaultprotocol = OSP_PROT_H323;
00297 ast_debug(1, "OSP: default protocol '%s'\n", p->defaultprotocol);
00298 } else if (!strcasecmp(v->value, OSP_PROT_IAX)) {
00299 p->defaultprotocol = OSP_PROT_IAX;
00300 ast_debug(1, "OSP: default protocol '%s'\n", p->defaultprotocol);
00301 } else {
00302 ast_log(LOG_WARNING, "OSP: default protocol should be %s, %s, %s, or %s not '%s' at line %d\n",
00303 OSP_PROT_SIP, OSP_PROT_H323, OSP_PROT_IAX, OSP_PROT_OTHER, v->value, v->lineno);
00304 }
00305 }
00306 v = v->next;
00307 }
00308
00309 error = OSPPUtilLoadPEMPrivateKey((unsigned char*)p->privatekey, &privatekey);
00310 if (error != OSPC_ERR_NO_ERROR) {
00311 ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", p->privatekey, error);
00312 ast_free(p);
00313 return 0;
00314 }
00315
00316 error = OSPPUtilLoadPEMCert((unsigned char*)p->localcert, &localcert);
00317 if (error != OSPC_ERR_NO_ERROR) {
00318 ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", p->localcert, error);
00319 if (privatekey.PrivateKeyData) {
00320 ast_free(privatekey.PrivateKeyData);
00321 }
00322 ast_free(p);
00323 return 0;
00324 }
00325
00326 if (p->cacount < 1) {
00327 snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s-cacert.pem", ast_config_AST_KEY_DIR, provider);
00328 ast_debug(1, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
00329 p->cacount++;
00330 }
00331 for (i = 0; i < p->cacount; i++) {
00332 error = OSPPUtilLoadPEMCert((unsigned char*)p->cacerts[i], &cacerts[i]);
00333 if (error != OSPC_ERR_NO_ERROR) {
00334 ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", p->cacerts[i], error);
00335 for (j = 0; j < i; j++) {
00336 if (cacerts[j].CertData) {
00337 ast_free(cacerts[j].CertData);
00338 }
00339 }
00340 if (localcert.CertData) {
00341 ast_free(localcert.CertData);
00342 }
00343 if (privatekey.PrivateKeyData) {
00344 ast_free(privatekey.PrivateKeyData);
00345 }
00346 ast_free(p);
00347 return 0;
00348 }
00349 pcacerts[i] = &cacerts[i];
00350 }
00351
00352 for (i = 0; i < p->spcount; i++) {
00353 psrvpoints[i] = p->srvpoints[i];
00354 }
00355
00356 error = OSPPProviderNew(
00357 p->spcount,
00358 psrvpoints,
00359 NULL,
00360 OSP_AUDIT_URL,
00361 &privatekey,
00362 &localcert,
00363 p->cacount,
00364 pcacerts,
00365 OSP_LOCAL_VALIDATION,
00366 OSP_SSL_LIFETIME,
00367 p->maxconnections,
00368 OSP_HTTP_PERSISTENCE,
00369 p->retrydelay,
00370 p->retrylimit,
00371 p->timeout,
00372 OSP_CUSTOMER_ID,
00373 OSP_DEVICE_ID,
00374 &p->handle);
00375 if (error != OSPC_ERR_NO_ERROR) {
00376 ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", provider, error);
00377 ast_free(p);
00378 res = -1;
00379 } else {
00380 ast_debug(1, "OSP: provider '%s'\n", provider);
00381 ast_mutex_lock(&osplock);
00382 p->next = ospproviders;
00383 ospproviders = p;
00384 ast_mutex_unlock(&osplock);
00385 res = 1;
00386 }
00387
00388 for (i = 0; i < p->cacount; i++) {
00389 if (cacerts[i].CertData) {
00390 ast_free(cacerts[i].CertData);
00391 }
00392 }
00393 if (localcert.CertData) {
00394 ast_free(localcert.CertData);
00395 }
00396 if (privatekey.PrivateKeyData) {
00397 ast_free(privatekey.PrivateKeyData);
00398 }
00399
00400 return res;
00401 }
00402
00403
00404
00405
00406
00407
00408
00409 static int osp_get_provider(
00410 const char* name,
00411 struct osp_provider** provider)
00412 {
00413 int res = 0;
00414 struct osp_provider* p;
00415
00416 ast_mutex_lock(&osplock);
00417 p = ospproviders;
00418 while(p) {
00419 if (!strcasecmp(p->name, name)) {
00420 *provider = p;
00421 ast_debug(1, "OSP: find provider '%s'\n", name);
00422 res = 1;
00423 break;
00424 }
00425 p = p->next;
00426 }
00427 ast_mutex_unlock(&osplock);
00428
00429 return res;
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 static int osp_create_transaction(
00441 const char* provider,
00442 int* transaction,
00443 unsigned int sourcesize,
00444 char* source)
00445 {
00446 int res = 0;
00447 struct osp_provider* p;
00448 int error;
00449
00450 ast_mutex_lock(&osplock);
00451 p = ospproviders;
00452 while(p) {
00453 if (!strcasecmp(p->name, provider)) {
00454 error = OSPPTransactionNew(p->handle, transaction);
00455 if (error == OSPC_ERR_NO_ERROR) {
00456 ast_debug(1, "OSP: transaction '%d'\n", *transaction);
00457 ast_copy_string(source, p->source, sourcesize);
00458 ast_debug(1, "OSP: source '%s'\n", source);
00459 res = 1;
00460 } else {
00461 *transaction = OSP_INVALID_HANDLE;
00462 ast_debug(1, "OSP: Unable to create transaction handle, error '%d'\n", error);
00463 res = -1;
00464 }
00465 break;
00466 }
00467 p = p->next;
00468 }
00469 ast_mutex_unlock(&osplock);
00470
00471 return res;
00472 }
00473
00474
00475
00476
00477
00478
00479
00480 static void osp_convert_address(
00481 const char* src,
00482 char* dst,
00483 int buffersize)
00484 {
00485 struct in_addr inp;
00486
00487 if (inet_aton(src, &inp) != 0) {
00488 snprintf(dst, buffersize, "[%s]", src);
00489 } else {
00490 snprintf(dst, buffersize, "%s", src);
00491 }
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 static int osp_validate_token(
00506 int transaction,
00507 const char* source,
00508 const char* destination,
00509 const char* calling,
00510 const char* called,
00511 const char* token,
00512 unsigned int* timelimit)
00513 {
00514 int res;
00515 int tokenlen;
00516 unsigned char tokenstr[OSP_TOKSTR_SIZE];
00517 char src[OSP_NORSTR_SIZE];
00518 char dst[OSP_NORSTR_SIZE];
00519 unsigned int authorised;
00520 unsigned int dummy = 0;
00521 int error;
00522
00523 tokenlen = ast_base64decode(tokenstr, token, strlen(token));
00524 osp_convert_address(source, src, sizeof(src));
00525 osp_convert_address(destination, dst, sizeof(dst));
00526 error = OSPPTransactionValidateAuthorisation(
00527 transaction,
00528 src,
00529 dst,
00530 NULL,
00531 NULL,
00532 calling ? calling : "",
00533 OSPC_E164,
00534 called,
00535 OSPC_E164,
00536 0,
00537 NULL,
00538 tokenlen,
00539 (char*)tokenstr,
00540 &authorised,
00541 timelimit,
00542 &dummy,
00543 NULL,
00544 osp_tokenformat);
00545 if (error != OSPC_ERR_NO_ERROR) {
00546 ast_debug(1, "OSP: Unable to validate inbound token\n");
00547 res = -1;
00548 } else if (authorised) {
00549 ast_debug(1, "OSP: Authorised\n");
00550 res = 1;
00551 } else {
00552 ast_debug(1, "OSP: Unauthorised\n");
00553 res = 0;
00554 }
00555
00556 return res;
00557 }
00558
00559
00560
00561
00562
00563
00564
00565 static unsigned int osp_choose_timelimit(
00566 unsigned int in,
00567 unsigned int out)
00568 {
00569 if (in == OSP_DEF_TIMELIMIT) {
00570 return out;
00571 } else if (out == OSP_DEF_TIMELIMIT) {
00572 return in;
00573 } else {
00574 return in < out ? in : out;
00575 }
00576 }
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 static int osp_check_destination(
00591 struct osp_provider* provider,
00592 const char* called,
00593 const char* calling,
00594 char* destination,
00595 unsigned int tokenlen,
00596 const char* token,
00597 enum OSPEFAILREASON* reason,
00598 struct osp_result* result)
00599 {
00600 int res;
00601 OSPE_DEST_OSP_ENABLED enabled;
00602 OSPE_DEST_PROT protocol;
00603 int error;
00604
00605 if (strlen(destination) <= 2) {
00606 ast_debug(1, "OSP: Wrong destination format '%s'\n", destination);
00607 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
00608 return -1;
00609 }
00610
00611 if ((error = OSPPTransactionIsDestOSPEnabled(result->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) {
00612 ast_debug(1, "OSP: Unable to get destination OSP version, error '%d'\n", error);
00613 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
00614 return -1;
00615 }
00616
00617 if (enabled == OSPE_OSP_FALSE) {
00618 result->token[0] = '\0';
00619 } else {
00620 ast_base64encode(result->token, (const unsigned char*)token, tokenlen, sizeof(result->token) - 1);
00621 }
00622
00623 if ((error = OSPPTransactionGetDestNetworkId(result->outhandle, result->networkid)) != OSPC_ERR_NO_ERROR) {
00624 ast_debug(1, "OSP: Unable to get destination network ID, error '%d'\n", error);
00625 result->networkid[0] = '\0';
00626 }
00627
00628 if ((error = OSPPTransactionGetDestProtocol(result->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
00629 ast_debug(1, "OSP: Unable to get destination protocol, error '%d'\n", error);
00630 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
00631 result->token[0] = '\0';
00632 result->networkid[0] = '\0';
00633 return -1;
00634 }
00635
00636 res = 1;
00637
00638 destination[strlen(destination) - 1] = '\0';
00639 switch(protocol) {
00640 case OSPE_DEST_PROT_H323_SETUP:
00641 ast_debug(1, "OSP: protocol '%s'\n", OSP_PROT_H323);
00642 ast_copy_string(result->tech, OSP_TECH_H323, sizeof(result->tech));
00643 ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
00644 ast_copy_string(result->called, called, sizeof(result->called));
00645 ast_copy_string(result->calling, calling, sizeof(result->calling));
00646 break;
00647 case OSPE_DEST_PROT_SIP:
00648 ast_debug(1, "OSP: protocol '%s'\n", OSP_PROT_SIP);
00649 ast_copy_string(result->tech, OSP_TECH_SIP, sizeof(result->tech));
00650 ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
00651 ast_copy_string(result->called, called, sizeof(result->called));
00652 ast_copy_string(result->calling, calling, sizeof(result->calling));
00653 break;
00654 case OSPE_DEST_PROT_IAX:
00655 ast_debug(1, "OSP: protocol '%s'\n", OSP_PROT_IAX);
00656 ast_copy_string(result->tech, OSP_TECH_IAX, sizeof(result->tech));
00657 ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
00658 ast_copy_string(result->called, called, sizeof(result->called));
00659 ast_copy_string(result->calling, calling, sizeof(result->calling));
00660 break;
00661 case OSPE_DEST_PROT_UNDEFINED:
00662 case OSPE_DEST_PROT_UNKNOWN:
00663 ast_debug(1, "OSP: unknown/undefined protocol '%d'\n", protocol);
00664 ast_debug(1, "OSP: use default protocol '%s'\n", provider->defaultprotocol);
00665
00666 ast_copy_string(result->tech, provider->defaultprotocol, sizeof(result->tech));
00667 ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
00668 ast_copy_string(result->called, called, sizeof(result->called));
00669 ast_copy_string(result->calling, calling, sizeof(result->calling));
00670 break;
00671 case OSPE_DEST_PROT_H323_LRQ:
00672 default:
00673 ast_log(LOG_WARNING, "OSP: unsupported protocol '%d'\n", protocol);
00674 *reason = OSPC_FAIL_PROTOCOL_ERROR;
00675 result->token[0] = '\0';
00676 result->networkid[0] = '\0';
00677 res = 0;
00678 break;
00679 }
00680
00681 return res;
00682 }
00683
00684
00685
00686
00687
00688
00689 static enum OSPEFAILREASON asterisk2osp(
00690 int cause)
00691 {
00692 return (enum OSPEFAILREASON)cause;
00693 }
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 static int osp_auth(
00707 const char* provider,
00708 int* transaction,
00709 const char* source,
00710 const char* calling,
00711 const char* called,
00712 const char* token,
00713 unsigned int* timelimit)
00714 {
00715 int res;
00716 struct osp_provider* p = NULL;
00717 char dest[OSP_NORSTR_SIZE];
00718
00719 *transaction = OSP_INVALID_HANDLE;
00720 *timelimit = OSP_DEF_TIMELIMIT;
00721
00722 if ((res = osp_get_provider(provider, &p)) <= 0) {
00723 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", provider);
00724 return res;
00725 }
00726
00727 switch (p->authpolicy) {
00728 case OSP_AUTH_NO:
00729 res = 1;
00730 break;
00731 case OSP_AUTH_EXCLUSIVE:
00732 if (ast_strlen_zero(token)) {
00733 res = 0;
00734 } else if ((res = osp_create_transaction(provider, transaction, sizeof(dest), dest)) <= 0) {
00735 ast_debug(1, "OSP: Unable to generate transaction handle\n");
00736 *transaction = OSP_INVALID_HANDLE;
00737 res = 0;
00738 } else if((res = osp_validate_token(*transaction, source, dest, calling, called, token, timelimit)) <= 0) {
00739 OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
00740 }
00741 break;
00742 case OSP_AUTH_YES:
00743 default:
00744 if (ast_strlen_zero(token)) {
00745 res = 1;
00746 } else if ((res = osp_create_transaction(provider, transaction, sizeof(dest), dest)) <= 0) {
00747 ast_debug(1, "OSP: Unable to generate transaction handle\n");
00748 *transaction = OSP_INVALID_HANDLE;
00749 res = 0;
00750 } else if((res = osp_validate_token(*transaction, source, dest, calling, called, token, timelimit)) <= 0) {
00751 OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
00752 }
00753 break;
00754 }
00755
00756 return res;
00757 }
00758
00759
00760
00761
00762
00763
00764
00765 static int osp_create_uuid(
00766 unsigned char* uuid,
00767 unsigned int* buffersize)
00768 {
00769 int i, res;
00770 long int* tmp;
00771
00772 if (*buffersize >= OSP_UUID_SIZE) {
00773 tmp = (long int*)uuid;
00774 for (i = 0; i < OSP_UUID_SIZE / sizeof(long int); i++) {
00775 tmp[i] = ast_random();
00776 }
00777 *buffersize = OSP_UUID_SIZE;
00778 res = 1;
00779 } else {
00780 res = -1;
00781 }
00782
00783 return res;
00784 }
00785
00786
00787
00788
00789
00790
00791
00792
00793 static int osp_uuid2str(
00794 unsigned char* uuid,
00795 char* buffer,
00796 unsigned int buffersize)
00797 {
00798 int res;
00799
00800 if (buffersize > OSP_UUIDSTR_SIZE) {
00801 snprintf(buffer, buffersize, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
00802 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
00803 uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
00804 res = 1;
00805 } else {
00806 res = -1;
00807 }
00808
00809 return res;
00810 }
00811
00812
00813
00814
00815
00816
00817
00818 static int osp_create_callid(
00819 unsigned int type,
00820 struct osp_callid* callid)
00821 {
00822 int res;
00823
00824 callid->len = sizeof(callid->buf);
00825 switch (type) {
00826 case OSP_CALLID_H323:
00827 res = osp_create_uuid(callid->buf, &callid->len);
00828 break;
00829 case OSP_CALLID_SIP:
00830 case OSP_CALLID_IAX:
00831 res = 0;
00832 default:
00833 res = -1;
00834 break;
00835 }
00836
00837 if ((res != 1) && (callid->len != 0)) {
00838 callid->buf[0] = '\0';
00839 callid->len = 0;
00840 }
00841
00842 return res;
00843 }
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855 static int osp_lookup(
00856 const char* provider,
00857 const char* srcdev,
00858 const char* calling,
00859 const char* called,
00860 unsigned int callidtypes,
00861 struct osp_result* result)
00862 {
00863 int res;
00864 struct osp_provider* p = NULL;
00865 char source[OSP_NORSTR_SIZE];
00866 char callingnum[OSP_NORSTR_SIZE];
00867 char callednum[OSP_NORSTR_SIZE];
00868 char destination[OSP_NORSTR_SIZE];
00869 unsigned int tokenlen;
00870 char token[OSP_TOKSTR_SIZE];
00871 char src[OSP_NORSTR_SIZE];
00872 char dev[OSP_NORSTR_SIZE];
00873 unsigned int i, type;
00874 struct osp_callid callid;
00875 unsigned int callidnum;
00876 OSPTCALLID* callids[OSP_CALLID_MAXNUM];
00877 unsigned int dummy = 0;
00878 enum OSPEFAILREASON reason;
00879 int error;
00880
00881 result->outhandle = OSP_INVALID_HANDLE;
00882 result->tech[0] = '\0';
00883 result->dest[0] = '\0';
00884 result->called[0] = '\0';
00885 result->calling[0] = '\0';
00886 result->token[0] = '\0';
00887 result->networkid[0] = '\0';
00888 result->numresults = 0;
00889 result->outtimelimit = OSP_DEF_TIMELIMIT;
00890
00891 if ((res = osp_get_provider(provider, &p)) <= 0) {
00892 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", provider);
00893 return res;
00894 }
00895
00896 if ((res = osp_create_transaction(provider, &result->outhandle, sizeof(source), source)) <= 0) {
00897 ast_debug(1, "OSP: Unable to generate transaction handle\n");
00898 result->outhandle = OSP_INVALID_HANDLE;
00899 if (result->inhandle != OSP_INVALID_HANDLE) {
00900 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00901 }
00902 return -1;
00903 }
00904
00905 callidnum = 0;
00906 callids[0] = NULL;
00907 for (i = 0; i < OSP_CALLID_MAXNUM; i++) {
00908 type = 1 << i;
00909 if (callidtypes & type) {
00910 error = osp_create_callid(type, &callid);
00911 if (error == 1) {
00912 callids[callidnum] = OSPPCallIdNew(callid.len, callid.buf);
00913 callidnum++;
00914 }
00915 }
00916 }
00917
00918 osp_convert_address(source, src, sizeof(src));
00919 osp_convert_address(srcdev, dev, sizeof(dev));
00920 result->numresults = OSP_DEF_DESTINATIONS;
00921 error = OSPPTransactionRequestAuthorisation(
00922 result->outhandle,
00923 src,
00924 dev,
00925 calling ? calling : "",
00926 OSPC_E164,
00927 called,
00928 OSPC_E164,
00929 NULL,
00930 callidnum,
00931 callids,
00932 NULL,
00933 &result->numresults,
00934 &dummy,
00935 NULL);
00936
00937 for (i = 0; i < callidnum; i++) {
00938 OSPPCallIdDelete(&callids[i]);
00939 }
00940
00941 if (error != OSPC_ERR_NO_ERROR) {
00942 ast_debug(1, "OSP: Unable to request authorization\n");
00943 result->numresults = 0;
00944 if (result->inhandle != OSP_INVALID_HANDLE) {
00945 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00946 }
00947 return -1;
00948 }
00949
00950 if (!result->numresults) {
00951 ast_debug(1, "OSP: No more destination\n");
00952 if (result->inhandle != OSP_INVALID_HANDLE) {
00953 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00954 }
00955 return 0;
00956 }
00957
00958 result->outcallid.len = sizeof(result->outcallid.buf);
00959 tokenlen = sizeof(token);
00960 error = OSPPTransactionGetFirstDestination(
00961 result->outhandle,
00962 0,
00963 NULL,
00964 NULL,
00965 &result->outtimelimit,
00966 &result->outcallid.len,
00967 result->outcallid.buf,
00968 sizeof(callednum),
00969 callednum,
00970 sizeof(callingnum),
00971 callingnum,
00972 sizeof(destination),
00973 destination,
00974 0,
00975 NULL,
00976 &tokenlen,
00977 token);
00978 if (error != OSPC_ERR_NO_ERROR) {
00979 ast_debug(1, "OSP: Unable to get first route\n");
00980 result->numresults = 0;
00981 result->outtimelimit = OSP_DEF_TIMELIMIT;
00982 if (result->inhandle != OSP_INVALID_HANDLE) {
00983 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00984 }
00985 return -1;
00986 }
00987
00988 result->numresults--;
00989 result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
00990 ast_debug(1, "OSP: outtimelimit '%d'\n", result->outtimelimit);
00991 ast_debug(1, "OSP: called '%s'\n", callednum);
00992 ast_debug(1, "OSP: calling '%s'\n", callingnum);
00993 ast_debug(1, "OSP: destination '%s'\n", destination);
00994 ast_debug(1, "OSP: token size '%d'\n", tokenlen);
00995
00996 if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
00997 return 1;
00998 }
00999
01000 if (!result->numresults) {
01001 ast_debug(1, "OSP: No more destination\n");
01002 result->outtimelimit = OSP_DEF_TIMELIMIT;
01003 OSPPTransactionRecordFailure(result->outhandle, reason);
01004 if (result->inhandle != OSP_INVALID_HANDLE) {
01005 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01006 }
01007 return 0;
01008 }
01009
01010 while(result->numresults) {
01011 result->outcallid.len = sizeof(result->outcallid.buf);
01012 tokenlen = sizeof(token);
01013 error = OSPPTransactionGetNextDestination(
01014 result->outhandle,
01015 reason,
01016 0,
01017 NULL,
01018 NULL,
01019 &result->outtimelimit,
01020 &result->outcallid.len,
01021 result->outcallid.buf,
01022 sizeof(callednum),
01023 callednum,
01024 sizeof(callingnum),
01025 callingnum,
01026 sizeof(destination),
01027 destination,
01028 0,
01029 NULL,
01030 &tokenlen,
01031 token);
01032 if (error == OSPC_ERR_NO_ERROR) {
01033 result->numresults--;
01034 result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
01035 ast_debug(1, "OSP: outtimelimit '%d'\n", result->outtimelimit);
01036 ast_debug(1, "OSP: called '%s'\n", callednum);
01037 ast_debug(1, "OSP: calling '%s'\n", callingnum);
01038 ast_debug(1, "OSP: destination '%s'\n", destination);
01039 ast_debug(1, "OSP: token size '%d'\n", tokenlen);
01040
01041 if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
01042 break;
01043 } else if (!result->numresults) {
01044 ast_debug(1, "OSP: No more destination\n");
01045 OSPPTransactionRecordFailure(result->outhandle, reason);
01046 if (result->inhandle != OSP_INVALID_HANDLE) {
01047 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01048 }
01049 res = 0;
01050 break;
01051 }
01052 } else {
01053 ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
01054 result->numresults = 0;
01055 result->outtimelimit = OSP_DEF_TIMELIMIT;
01056 if (result->inhandle != OSP_INVALID_HANDLE) {
01057 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
01058 }
01059 res = -1;
01060 break;
01061 }
01062 }
01063 return res;
01064 }
01065
01066
01067
01068
01069
01070
01071
01072
01073 static int osp_next(
01074 const char* provider,
01075 int cause,
01076 struct osp_result* result)
01077 {
01078 int res;
01079 struct osp_provider* p = NULL;
01080 char callingnum[OSP_NORSTR_SIZE];
01081 char callednum[OSP_NORSTR_SIZE];
01082 char destination[OSP_NORSTR_SIZE];
01083 unsigned int tokenlen;
01084 char token[OSP_TOKSTR_SIZE];
01085 enum OSPEFAILREASON reason;
01086 int error;
01087
01088 result->tech[0] = '\0';
01089 result->dest[0] = '\0';
01090 result->called[0] = '\0';
01091 result->calling[0] = '\0';
01092 result->token[0] = '\0';
01093 result->networkid[0] = '\0';
01094 result->outtimelimit = OSP_DEF_TIMELIMIT;
01095
01096 if ((res = osp_get_provider(provider, &p)) <= 0) {
01097 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", provider);
01098 return res;
01099 }
01100
01101 if (result->outhandle == OSP_INVALID_HANDLE) {
01102 ast_debug(1, "OSP: Transaction handle undefined\n");
01103 result->numresults = 0;
01104 if (result->inhandle != OSP_INVALID_HANDLE) {
01105 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
01106 }
01107 return -1;
01108 }
01109
01110 reason = asterisk2osp(cause);
01111
01112 if (!result->numresults) {
01113 ast_debug(1, "OSP: No more destination\n");
01114 OSPPTransactionRecordFailure(result->outhandle, reason);
01115 if (result->inhandle != OSP_INVALID_HANDLE) {
01116 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01117 }
01118 return 0;
01119 }
01120
01121 while(result->numresults) {
01122 result->outcallid.len = sizeof(result->outcallid.buf);
01123 tokenlen = sizeof(token);
01124 error = OSPPTransactionGetNextDestination(
01125 result->outhandle,
01126 reason,
01127 0,
01128 NULL,
01129 NULL,
01130 &result->outtimelimit,
01131 &result->outcallid.len,
01132 result->outcallid.buf,
01133 sizeof(callednum),
01134 callednum,
01135 sizeof(callingnum),
01136 callingnum,
01137 sizeof(destination),
01138 destination,
01139 0,
01140 NULL,
01141 &tokenlen,
01142 token);
01143 if (error == OSPC_ERR_NO_ERROR) {
01144 result->numresults--;
01145 result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
01146 ast_debug(1, "OSP: outtimelimit '%d'\n", result->outtimelimit);
01147 ast_debug(1, "OSP: called '%s'\n", callednum);
01148 ast_debug(1, "OSP: calling '%s'\n", callingnum);
01149 ast_debug(1, "OSP: destination '%s'\n", destination);
01150 ast_debug(1, "OSP: token size '%d'\n", tokenlen);
01151
01152 if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
01153 res = 1;
01154 break;
01155 } else if (!result->numresults) {
01156 ast_debug(1, "OSP: No more destination\n");
01157 OSPPTransactionRecordFailure(result->outhandle, reason);
01158 if (result->inhandle != OSP_INVALID_HANDLE) {
01159 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01160 }
01161 res = 0;
01162 break;
01163 }
01164 } else {
01165 ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
01166 result->token[0] = '\0';
01167 result->numresults = 0;
01168 result->outtimelimit = OSP_DEF_TIMELIMIT;
01169 if (result->inhandle != OSP_INVALID_HANDLE) {
01170 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
01171 }
01172 res = -1;
01173 break;
01174 }
01175 }
01176
01177 return res;
01178 }
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191 static int osp_finish(
01192 int handle,
01193 int recorded,
01194 int cause,
01195 time_t start,
01196 time_t connect_time,
01197 time_t end,
01198 unsigned int release)
01199 {
01200 int res;
01201 enum OSPEFAILREASON reason;
01202 time_t alert = 0;
01203 unsigned isPddInfoPresent = 0;
01204 unsigned pdd = 0;
01205 unsigned int dummy = 0;
01206 int error;
01207
01208 if (handle == OSP_INVALID_HANDLE) {
01209 return 0;
01210 }
01211
01212 if (!recorded) {
01213 reason = asterisk2osp(cause);
01214 OSPPTransactionRecordFailure(handle, reason);
01215 }
01216
01217 error = OSPPTransactionReportUsage(
01218 handle,
01219 difftime(end, connect_time),
01220 start,
01221 end,
01222 alert,
01223 connect_time,
01224 isPddInfoPresent,
01225 pdd,
01226 release,
01227 (unsigned char*)"",
01228 0,
01229 0,
01230 0,
01231 0,
01232 &dummy,
01233 NULL);
01234 if (error == OSPC_ERR_NO_ERROR) {
01235 ast_debug(1, "OSP: Usage reported\n");
01236 res = 1;
01237 } else {
01238 ast_debug(1, "OSP: Unable to report usage, error '%d'\n", error);
01239 res = -1;
01240 }
01241 OSPPTransactionDelete(handle);
01242
01243 return res;
01244 }
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254 static int ospauth_exec(
01255 struct ast_channel* chan,
01256 void* data)
01257 {
01258 int res;
01259 const char* provider = OSP_DEF_PROVIDER;
01260 struct varshead* headp;
01261 struct ast_var_t* current;
01262 const char* source = "";
01263 const char* token = "";
01264 int handle;
01265 unsigned int timelimit;
01266 char buffer[OSP_INTSTR_SIZE];
01267 const char* status;
01268 char* tmp;
01269
01270 AST_DECLARE_APP_ARGS(args,
01271 AST_APP_ARG(provider);
01272 AST_APP_ARG(options);
01273 );
01274
01275 if (!(tmp = ast_strdupa(data))) {
01276 ast_log(LOG_ERROR, "Out of memory\n");
01277 return -1;
01278 }
01279
01280 AST_STANDARD_APP_ARGS(args, tmp);
01281
01282 if (!ast_strlen_zero(args.provider)) {
01283 provider = args.provider;
01284 }
01285 ast_debug(1, "OSPAuth: provider '%s'\n", provider);
01286
01287 headp = &chan->varshead;
01288 AST_LIST_TRAVERSE(headp, current, entries) {
01289 if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
01290 source = ast_var_value(current);
01291 } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
01292 token = ast_var_value(current);
01293 }
01294 }
01295
01296 ast_debug(1, "OSPAuth: source '%s'\n", source);
01297 ast_debug(1, "OSPAuth: token size '%zd'\n", strlen(token));
01298
01299 if ((res = osp_auth(provider, &handle, source, chan->cid.cid_num, chan->exten, token, &timelimit)) > 0) {
01300 status = AST_OSP_SUCCESS;
01301 } else {
01302 timelimit = OSP_DEF_TIMELIMIT;
01303 if (!res) {
01304 status = AST_OSP_FAILED;
01305 } else {
01306 status = AST_OSP_ERROR;
01307 }
01308 }
01309
01310 snprintf(buffer, sizeof(buffer), "%d", handle);
01311 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
01312 ast_debug(1, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
01313 snprintf(buffer, sizeof(buffer), "%d", timelimit);
01314 pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
01315 ast_debug(1, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
01316 pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
01317 ast_debug(1, "OSPAuth: %s\n", status);
01318
01319 if(res <= 0) {
01320 res = -1;
01321 } else {
01322 res = 0;
01323 }
01324
01325 return res;
01326 }
01327
01328
01329
01330
01331
01332
01333
01334 static int osplookup_exec(
01335 struct ast_channel* chan,
01336 void* data)
01337 {
01338 int res, cres;
01339 const char* provider = OSP_DEF_PROVIDER;
01340 struct varshead* headp;
01341 struct ast_var_t* current;
01342 const char* srcdev = "";
01343 const char* netid = "";
01344 char buffer[OSP_TOKSTR_SIZE];
01345 unsigned int callidtypes = OSP_CALLID_UNDEFINED;
01346 struct osp_result result;
01347 const char* status;
01348 char* tmp;
01349
01350 AST_DECLARE_APP_ARGS(args,
01351 AST_APP_ARG(exten);
01352 AST_APP_ARG(provider);
01353 AST_APP_ARG(options);
01354 );
01355
01356 if (ast_strlen_zero(data)) {
01357 ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[|provider[|options]])\n");
01358 return -1;
01359 }
01360
01361 if (!(tmp = ast_strdupa(data))) {
01362 ast_log(LOG_ERROR, "Out of memory\n");
01363 return -1;
01364 }
01365
01366 AST_STANDARD_APP_ARGS(args, tmp);
01367
01368 ast_debug(1, "OSPLookup: exten '%s'\n", args.exten);
01369
01370 if (!ast_strlen_zero(args.provider)) {
01371 provider = args.provider;
01372 }
01373 ast_debug(1, "OSPlookup: provider '%s'\n", provider);
01374
01375 if (args.options) {
01376 if (strchr(args.options, 'h')) {
01377 callidtypes |= OSP_CALLID_H323;
01378 }
01379 if (strchr(args.options, 's')) {
01380 callidtypes |= OSP_CALLID_SIP;
01381 }
01382 if (strchr(args.options, 'i')) {
01383 callidtypes |= OSP_CALLID_IAX;
01384 }
01385 }
01386 ast_debug(1, "OSPLookup: call id types '%d'\n", callidtypes);
01387
01388 result.inhandle = OSP_INVALID_HANDLE;
01389 result.intimelimit = OSP_DEF_TIMELIMIT;
01390
01391 headp = &chan->varshead;
01392 AST_LIST_TRAVERSE(headp, current, entries) {
01393 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
01394 if (sscanf(ast_var_value(current), "%d", &result.inhandle) != 1) {
01395 result.inhandle = OSP_INVALID_HANDLE;
01396 }
01397 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
01398 if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) {
01399 result.intimelimit = OSP_DEF_TIMELIMIT;
01400 }
01401 } else if (!strcasecmp(ast_var_name(current), "OSPINNETWORKID")) {
01402 netid = ast_var_value(current);
01403 } else if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
01404 srcdev = ast_var_value(current);
01405 }
01406 }
01407 ast_debug(1, "OSPLookup: OSPINHANDLE '%d'\n", result.inhandle);
01408 ast_debug(1, "OSPLookup: OSPINTIMELIMIT '%d'\n", result.intimelimit);
01409 ast_debug(1, "OSPLookup: OSPINNETWORKID '%s'\n", netid);
01410 ast_debug(1, "OSPLookup: source device '%s'\n", srcdev);
01411
01412 if ((cres = ast_autoservice_start(chan)) < 0) {
01413 return -1;
01414 }
01415
01416 if ((res = osp_lookup(provider, srcdev, chan->cid.cid_num, args.exten, callidtypes, &result)) > 0) {
01417 status = AST_OSP_SUCCESS;
01418 } else {
01419 result.tech[0] = '\0';
01420 result.dest[0] = '\0';
01421 result.called[0] = '\0';
01422 result.calling[0] = '\0';
01423 result.token[0] = '\0';
01424 result.networkid[0] = '\0';
01425 result.numresults = 0;
01426 result.outtimelimit = OSP_DEF_TIMELIMIT;
01427 result.outcallid.buf[0] = '\0';
01428 result.outcallid.len = 0;
01429 if (!res) {
01430 status = AST_OSP_FAILED;
01431 } else {
01432 status = AST_OSP_ERROR;
01433 }
01434 }
01435
01436 snprintf(buffer, sizeof(buffer), "%d", result.outhandle);
01437 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
01438 ast_debug(1, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
01439 pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
01440 ast_debug(1, "OSPLookup: OSPTECH '%s'\n", result.tech);
01441 pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
01442 ast_debug(1, "OSPLookup: OSPDEST '%s'\n", result.dest);
01443 pbx_builtin_setvar_helper(chan, "OSPCALLED", result.called);
01444 ast_debug(1, "OSPLookup: OSPCALLED '%s'\n", result.called);
01445 pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
01446 ast_debug(1, "OSPLookup: OSPCALLING '%s'\n", result.calling);
01447 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
01448 ast_debug(1, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
01449 snprintf(buffer, sizeof(buffer), "%d", result.numresults);
01450 pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
01451 ast_debug(1, "OSPLookup: OSPRESULTS '%s'\n", buffer);
01452 snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
01453 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
01454 ast_debug(1, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
01455 snprintf(buffer, sizeof(buffer), "%d", callidtypes);
01456 pbx_builtin_setvar_helper(chan, "OSPOUTCALLIDTYPES", buffer);
01457 ast_debug(1, "OSPLookup: OSPOUTCALLIDTYPES '%s'\n", buffer);
01458 pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
01459 ast_debug(1, "OSPLookup: %s\n", status);
01460
01461 if (!strcasecmp(result.tech, OSP_TECH_H323)) {
01462 if ((callidtypes & OSP_CALLID_H323) && (result.outcallid.len != 0)) {
01463 osp_uuid2str(result.outcallid.buf, buffer, sizeof(buffer));
01464 } else {
01465 buffer[0] = '\0';
01466 }
01467 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
01468 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
01469 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
01470 } else if (!strcasecmp(result.tech, OSP_TECH_SIP)) {
01471 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
01472 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
01473 if (!ast_strlen_zero(result.token)) {
01474 snprintf(buffer, sizeof(buffer), "%s%s", OSP_SIP_HEADER, result.token);
01475 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
01476 ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
01477 }
01478 } else if (!strcasecmp(result.tech, OSP_TECH_IAX)) {
01479 snprintf(buffer, sizeof(buffer), "%s/%s/%s", result.tech, result.dest, result.called);
01480 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
01481 }
01482
01483 if ((cres = ast_autoservice_stop(chan)) < 0) {
01484 return -1;
01485 }
01486
01487 if(res <= 0) {
01488 res = -1;
01489 } else {
01490 res = 0;
01491 }
01492
01493 return res;
01494 }
01495
01496
01497
01498
01499
01500
01501
01502 static int ospnext_exec(
01503 struct ast_channel* chan,
01504 void* data)
01505 {
01506 int res;
01507 const char* provider = OSP_DEF_PROVIDER;
01508 int cause = 0;
01509 struct varshead* headp;
01510 struct ast_var_t* current;
01511 struct osp_result result;
01512 char buffer[OSP_TOKSTR_SIZE];
01513 unsigned int callidtypes = OSP_CALLID_UNDEFINED;
01514 const char* status;
01515 char* tmp;
01516
01517 AST_DECLARE_APP_ARGS(args,
01518 AST_APP_ARG(cause);
01519 AST_APP_ARG(provider);
01520 AST_APP_ARG(options);
01521 );
01522
01523 if (ast_strlen_zero(data)) {
01524 ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[|provider[|options]])\n");
01525 return -1;
01526 }
01527
01528 if (!(tmp = ast_strdupa(data))) {
01529 ast_log(LOG_ERROR, "Out of memory\n");
01530 return -1;
01531 }
01532
01533 AST_STANDARD_APP_ARGS(args, tmp);
01534
01535 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%d", &cause) != 1) {
01536 cause = 0;
01537 }
01538 ast_debug(1, "OSPNext: cause '%d'\n", cause);
01539
01540 if (!ast_strlen_zero(args.provider)) {
01541 provider = args.provider;
01542 }
01543 ast_debug(1, "OSPlookup: provider '%s'\n", provider);
01544
01545 result.inhandle = OSP_INVALID_HANDLE;
01546 result.outhandle = OSP_INVALID_HANDLE;
01547 result.intimelimit = OSP_DEF_TIMELIMIT;
01548 result.numresults = 0;
01549
01550 headp = &chan->varshead;
01551 AST_LIST_TRAVERSE(headp, current, entries) {
01552 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
01553 if (sscanf(ast_var_value(current), "%d", &result.inhandle) != 1) {
01554 result.inhandle = OSP_INVALID_HANDLE;
01555 }
01556 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
01557 if (sscanf(ast_var_value(current), "%d", &result.outhandle) != 1) {
01558 result.outhandle = OSP_INVALID_HANDLE;
01559 }
01560 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
01561 if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) {
01562 result.intimelimit = OSP_DEF_TIMELIMIT;
01563 }
01564 } else if (!strcasecmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) {
01565 if (sscanf(ast_var_value(current), "%d", &callidtypes) != 1) {
01566 callidtypes = OSP_CALLID_UNDEFINED;
01567 }
01568 } else if (!strcasecmp(ast_var_name(current), "OSPRESULTS")) {
01569 if (sscanf(ast_var_value(current), "%d", &result.numresults) != 1) {
01570 result.numresults = 0;
01571 }
01572 }
01573 }
01574 ast_debug(1, "OSPNext: OSPINHANDLE '%d'\n", result.inhandle);
01575 ast_debug(1, "OSPNext: OSPOUTHANDLE '%d'\n", result.outhandle);
01576 ast_debug(1, "OSPNext: OSPINTIMELIMIT '%d'\n", result.intimelimit);
01577 ast_debug(1, "OSPNext: OSPOUTCALLIDTYPES '%d'\n", callidtypes);
01578 ast_debug(1, "OSPNext: OSPRESULTS '%d'\n", result.numresults);
01579
01580 if ((res = osp_next(provider, cause, &result)) > 0) {
01581 status = AST_OSP_SUCCESS;
01582 } else {
01583 result.tech[0] = '\0';
01584 result.dest[0] = '\0';
01585 result.called[0] = '\0';
01586 result.calling[0] = '\0';
01587 result.token[0] = '\0';
01588 result.networkid[0] = '\0';
01589 result.numresults = 0;
01590 result.outtimelimit = OSP_DEF_TIMELIMIT;
01591 result.outcallid.buf[0] = '\0';
01592 result.outcallid.len = 0;
01593 if (!res) {
01594 status = AST_OSP_FAILED;
01595 } else {
01596 status = AST_OSP_ERROR;
01597 }
01598 }
01599
01600 pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
01601 ast_debug(1, "OSPNext: OSPTECH '%s'\n", result.tech);
01602 pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
01603 ast_debug(1, "OSPNext: OSPDEST '%s'\n", result.dest);
01604 pbx_builtin_setvar_helper(chan, "OSPCALLED", result.called);
01605 ast_debug(1, "OSPNext: OSPCALLED'%s'\n", result.called);
01606 pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
01607 ast_debug(1, "OSPNext: OSPCALLING '%s'\n", result.calling);
01608 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
01609 ast_debug(1, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
01610 snprintf(buffer, sizeof(buffer), "%d", result.numresults);
01611 pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
01612 ast_debug(1, "OSPNext: OSPRESULTS '%s'\n", buffer);
01613 snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
01614 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
01615 ast_debug(1, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
01616 pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
01617 ast_debug(1, "OSPNext: %s\n", status);
01618
01619 if (!strcasecmp(result.tech, OSP_TECH_H323)) {
01620 if ((callidtypes & OSP_CALLID_H323) && (result.outcallid.len != 0)) {
01621 osp_uuid2str(result.outcallid.buf, buffer, sizeof(buffer));
01622 } else {
01623 buffer[0] = '\0';
01624 }
01625 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
01626 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
01627 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
01628 } else if (!strcasecmp(result.tech, OSP_TECH_SIP)) {
01629 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
01630 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
01631 if (!ast_strlen_zero(result.token)) {
01632 snprintf(buffer, sizeof(buffer), "%s%s", OSP_SIP_HEADER, result.token);
01633 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
01634 ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
01635 }
01636 } else if (!strcasecmp(result.tech, OSP_TECH_IAX)) {
01637 snprintf(buffer, sizeof(buffer), "%s/%s/%s", result.tech, result.dest, result.called);
01638 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
01639 }
01640
01641 if(res <= 0) {
01642 res = -1;
01643 } else {
01644 res = 0;
01645 }
01646
01647 return res;
01648 }
01649
01650
01651
01652
01653
01654
01655
01656 static int ospfinished_exec(
01657 struct ast_channel* chan,
01658 void* data)
01659 {
01660 int res = 1;
01661 int cause = 0;
01662 struct varshead* headp;
01663 struct ast_var_t* current;
01664 int inhandle = OSP_INVALID_HANDLE;
01665 int outhandle = OSP_INVALID_HANDLE;
01666 int recorded = 0;
01667 time_t start, connect_time, end;
01668 unsigned int release;
01669 char buffer[OSP_INTSTR_SIZE];
01670 const char* status;
01671 char* tmp;
01672
01673 AST_DECLARE_APP_ARGS(args,
01674 AST_APP_ARG(cause);
01675 AST_APP_ARG(options);
01676 );
01677
01678 if (!(tmp = ast_strdupa(data))) {
01679 ast_log(LOG_ERROR, "Out of memory\n");
01680 return -1;
01681 }
01682
01683 AST_STANDARD_APP_ARGS(args, tmp);
01684
01685 headp = &chan->varshead;
01686 AST_LIST_TRAVERSE(headp, current, entries) {
01687 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
01688 if (sscanf(ast_var_value(current), "%d", &inhandle) != 1) {
01689 inhandle = OSP_INVALID_HANDLE;
01690 }
01691 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
01692 if (sscanf(ast_var_value(current), "%d", &outhandle) != 1) {
01693 outhandle = OSP_INVALID_HANDLE;
01694 }
01695 } else if (!recorded &&
01696 (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") ||
01697 !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") ||
01698 !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS")))
01699 {
01700 if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) {
01701 recorded = 1;
01702 }
01703 }
01704 }
01705 ast_debug(1, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
01706 ast_debug(1, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
01707 ast_debug(1, "OSPFinish: recorded '%d'\n", recorded);
01708
01709 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%d", &cause) != 1) {
01710 cause = 0;
01711 }
01712 ast_debug(1, "OSPFinish: cause '%d'\n", cause);
01713
01714 if (chan->cdr) {
01715 start = chan->cdr->start.tv_sec;
01716 connect_time = chan->cdr->answer.tv_sec;
01717 if (connect_time) {
01718 end = time(NULL);
01719 } else {
01720 end = connect_time;
01721 }
01722 } else {
01723 start = 0;
01724 connect_time = 0;
01725 end = 0;
01726 }
01727 ast_debug(1, "OSPFinish: start '%ld'\n", start);
01728 ast_debug(1, "OSPFinish: connect '%ld'\n", connect_time);
01729 ast_debug(1, "OSPFinish: end '%ld'\n", end);
01730
01731 release = ast_check_hangup(chan) ? 0 : 1;
01732
01733 if (osp_finish(outhandle, recorded, cause, start, connect_time, end, release) <= 0) {
01734 ast_debug(1, "OSPFinish: Unable to report usage for outbound call\n");
01735 }
01736 switch (cause) {
01737 case AST_CAUSE_NORMAL_CLEARING:
01738 break;
01739 default:
01740 cause = AST_CAUSE_NO_ROUTE_DESTINATION;
01741 break;
01742 }
01743 if (osp_finish(inhandle, recorded, cause, start, connect_time, end, release) <= 0) {
01744 ast_debug(1, "OSPFinish: Unable to report usage for inbound call\n");
01745 }
01746 snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
01747 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
01748 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
01749
01750 if (res > 0) {
01751 status = AST_OSP_SUCCESS;
01752 } else if (!res) {
01753 status = AST_OSP_FAILED;
01754 } else {
01755 status = AST_OSP_ERROR;
01756 }
01757 pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
01758
01759 if(!res) {
01760 res = -1;
01761 } else {
01762 res = 0;
01763 }
01764
01765 return res;
01766 }
01767
01768
01769
01770 static int osp_unload(void);
01771 static int osp_load(int reload)
01772 {
01773 const char* t;
01774 unsigned int v;
01775 struct ast_config* cfg;
01776 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01777 int error = OSPC_ERR_NO_ERROR;
01778
01779 if ((cfg = ast_config_load(OSP_CONFIG_FILE, config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
01780 return 0;
01781
01782 if (cfg) {
01783 if (reload)
01784 osp_unload();
01785
01786 t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate");
01787 if (t && ast_true(t)) {
01788 if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
01789 ast_log(LOG_WARNING, "OSP: Unable to enable hardware accelleration\n");
01790 OSPPInit(0);
01791 } else {
01792 osp_hardware = 1;
01793 }
01794 } else {
01795 OSPPInit(0);
01796 }
01797 ast_debug(1, "OSP: osp_hardware '%d'\n", osp_hardware);
01798
01799 t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat");
01800 if (t) {
01801 if ((sscanf(t, "%d", &v) == 1) &&
01802 ((v == TOKEN_ALGO_SIGNED) || (v == TOKEN_ALGO_UNSIGNED) || (v == TOKEN_ALGO_BOTH)))
01803 {
01804 osp_tokenformat = v;
01805 } else {
01806 ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n",
01807 TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, t);
01808 }
01809 }
01810 ast_debug(1, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
01811
01812 t = ast_category_browse(cfg, NULL);
01813 while(t) {
01814 if (strcasecmp(t, OSP_GENERAL_CAT)) {
01815 osp_create_provider(cfg, t);
01816 }
01817 t = ast_category_browse(cfg, t);
01818 }
01819
01820 osp_initialized = 1;
01821
01822 ast_config_destroy(cfg);
01823 } else {
01824 ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
01825 return 0;
01826 }
01827 ast_debug(1, "OSP: osp_initialized '%d'\n", osp_initialized);
01828
01829 return 1;
01830 }
01831
01832 static int osp_unload(void)
01833 {
01834 struct osp_provider* p;
01835 struct osp_provider* next;
01836
01837 if (osp_initialized) {
01838 ast_mutex_lock(&osplock);
01839 p = ospproviders;
01840 while(p) {
01841 next = p->next;
01842 OSPPProviderDelete(p->handle, 0);
01843 ast_free(p);
01844 p = next;
01845 }
01846 ospproviders = NULL;
01847 ast_mutex_unlock(&osplock);
01848
01849 OSPPCleanup();
01850
01851 osp_tokenformat = TOKEN_ALGO_SIGNED;
01852 osp_hardware = 0;
01853 osp_initialized = 0;
01854 }
01855 return 0;
01856 }
01857
01858 static char *handle_cli_osp_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01859 {
01860 int i;
01861 int found = 0;
01862 struct osp_provider* p;
01863 const char* provider = NULL;
01864 const char* tokenalgo;
01865
01866 switch (cmd) {
01867 case CLI_INIT:
01868 e->command = "osp show";
01869 e->usage =
01870 "Usage: osp show\n"
01871 " Displays information on Open Settlement Protocol support\n";
01872 return NULL;
01873 case CLI_GENERATE:
01874 return NULL;
01875 }
01876
01877 if ((a->argc < 2) || (a->argc > 3))
01878 return CLI_SHOWUSAGE;
01879 if (a->argc > 2)
01880 provider = a->argv[2];
01881 if (!provider) {
01882 switch (osp_tokenformat) {
01883 case TOKEN_ALGO_BOTH:
01884 tokenalgo = "Both";
01885 break;
01886 case TOKEN_ALGO_UNSIGNED:
01887 tokenalgo = "Unsigned";
01888 break;
01889 case TOKEN_ALGO_SIGNED:
01890 default:
01891 tokenalgo = "Signed";
01892 break;
01893 }
01894 ast_cli(a->fd, "OSP: %s %s %s\n",
01895 osp_initialized ? "Initialized" : "Uninitialized", osp_hardware ? "Accelerated" : "Normal", tokenalgo);
01896 }
01897
01898 ast_mutex_lock(&osplock);
01899 p = ospproviders;
01900 while(p) {
01901 if (!provider || !strcasecmp(p->name, provider)) {
01902 if (found) {
01903 ast_cli(a->fd, "\n");
01904 }
01905 ast_cli(a->fd, " == OSP Provider '%s' == \n", p->name);
01906 ast_cli(a->fd, "Local Private Key: %s\n", p->privatekey);
01907 ast_cli(a->fd, "Local Certificate: %s\n", p->localcert);
01908 for (i = 0; i < p->cacount; i++) {
01909 ast_cli(a->fd, "CA Certificate %d: %s\n", i + 1, p->cacerts[i]);
01910 }
01911 for (i = 0; i < p->spcount; i++) {
01912 ast_cli(a->fd, "Service Point %d: %s\n", i + 1, p->srvpoints[i]);
01913 }
01914 ast_cli(a->fd, "Max Connections: %d\n", p->maxconnections);
01915 ast_cli(a->fd, "Retry Delay: %d seconds\n", p->retrydelay);
01916 ast_cli(a->fd, "Retry Limit: %d\n", p->retrylimit);
01917 ast_cli(a->fd, "Timeout: %d milliseconds\n", p->timeout);
01918 ast_cli(a->fd, "Source: %s\n", strlen(p->source) ? p->source : "<unspecified>");
01919 ast_cli(a->fd, "Auth Policy %d\n", p->authpolicy);
01920 ast_cli(a->fd, "Default protocol %s\n", p->defaultprotocol);
01921 ast_cli(a->fd, "OSP Handle: %d\n", p->handle);
01922 found++;
01923 }
01924 p = p->next;
01925 }
01926 ast_mutex_unlock(&osplock);
01927
01928 if (!found) {
01929 if (provider) {
01930 ast_cli(a->fd, "Unable to find OSP provider '%s'\n", provider);
01931 } else {
01932 ast_cli(a->fd, "No OSP providers configured\n");
01933 }
01934 }
01935 return CLI_SUCCESS;
01936 }
01937
01938 static const char* app1= "OSPAuth";
01939 static const char* synopsis1 = "OSP authentication";
01940 static const char* descrip1 =
01941 " OSPAuth([provider[,options]]): Authenticate a SIP INVITE by OSP and sets\n"
01942 "the variables:\n"
01943 " ${OSPINHANDLE}: The inbound call transaction handle\n"
01944 " ${OSPINTIMELIMIT}: The inbound call duration limit in seconds\n"
01945 "\n"
01946 "This application sets the following channel variable upon completion:\n"
01947 " OSPAUTHSTATUS The status of the OSP Auth attempt as a text string, one of\n"
01948 " SUCCESS | FAILED | ERROR\n";
01949
01950 static const char* app2= "OSPLookup";
01951 static const char* synopsis2 = "Lookup destination by OSP";
01952 static const char* descrip2 =
01953 " OSPLookup(exten[,provider[,options]]): Looks up an extension via OSP and sets\n"
01954 "the variables, where 'n' is the number of the result beginning with 1:\n"
01955 " ${OSPOUTHANDLE}: The OSP Handle for anything remaining\n"
01956 " ${OSPTECH}: The technology to use for the call\n"
01957 " ${OSPDEST}: The destination to use for the call\n"
01958 " ${OSPCALLED}: The called number to use for the call\n"
01959 " ${OSPCALLING}: The calling number to use for the call\n"
01960 " ${OSPDIALSTR}: The dial command string\n"
01961 " ${OSPOUTTOKEN}: The actual OSP token as a string\n"
01962 " ${OSPOUTTIMELIMIT}: The outbound call duration limit in seconds\n"
01963 " ${OSPOUTCALLIDTYPES}: The outbound call id types\n"
01964 " ${OSPOUTCALLID}: The outbound call id\n"
01965 " ${OSPRESULTS}: The number of OSP results total remaining\n"
01966 "\n"
01967 "The option string may contain the following character:\n"
01968 " 'h' -- generate H323 call id for the outbound call\n"
01969 " 's' -- generate SIP call id for the outbound call. Have not been implemented\n"
01970 " 'i' -- generate IAX call id for the outbound call. Have not been implemented\n"
01971 "This application sets the following channel variable upon completion:\n"
01972 " OSPLOOKUPSTATUS The status of the OSP Lookup attempt as a text string, one of\n"
01973 " SUCCESS | FAILED | ERROR\n";
01974
01975 static const char* app3 = "OSPNext";
01976 static const char* synopsis3 = "Lookup next destination by OSP";
01977 static const char* descrip3 =
01978 " OSPNext(cause[,provider[,options]]): Looks up the next OSP Destination for ${OSPOUTHANDLE}\n"
01979 "See OSPLookup for more information\n"
01980 "\n"
01981 "This application sets the following channel variable upon completion:\n"
01982 " OSPNEXTSTATUS The status of the OSP Next attempt as a text string, one of\n"
01983 " SUCCESS | FAILED | ERROR\n";
01984
01985 static const char* app4 = "OSPFinish";
01986 static const char* synopsis4 = "Record OSP entry";
01987 static const char* descrip4 =
01988 " OSPFinish([status[,options]]): Records call state for ${OSPINHANDLE}, according to\n"
01989 "status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or CHANUNAVAIL\n"
01990 "or coincidentally, just what the Dial application stores in its ${DIALSTATUS}.\n"
01991 "\n"
01992 "This application sets the following channel variable upon completion:\n"
01993 " OSPFINISHSTATUS The status of the OSP Finish attempt as a text string, one of\n"
01994 " SUCCESS | FAILED | ERROR \n";
01995
01996 static struct ast_cli_entry cli_osp[] = {
01997 AST_CLI_DEFINE(handle_cli_osp_show, "Displays OSF information")
01998 };
01999
02000 static int load_module(void)
02001 {
02002 int res;
02003
02004 if (!osp_load(0))
02005 return AST_MODULE_LOAD_DECLINE;
02006
02007 ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
02008 res = ast_register_application(app1, ospauth_exec, synopsis1, descrip1);
02009 res |= ast_register_application(app2, osplookup_exec, synopsis2, descrip2);
02010 res |= ast_register_application(app3, ospnext_exec, synopsis3, descrip3);
02011 res |= ast_register_application(app4, ospfinished_exec, synopsis4, descrip4);
02012
02013 return res;
02014 }
02015
02016 static int unload_module(void)
02017 {
02018 int res;
02019
02020 res = ast_unregister_application(app4);
02021 res |= ast_unregister_application(app3);
02022 res |= ast_unregister_application(app2);
02023 res |= ast_unregister_application(app1);
02024 ast_cli_unregister_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
02025 osp_unload();
02026
02027 return res;
02028 }
02029
02030 static int reload(void)
02031 {
02032 osp_load(1);
02033
02034 return 0;
02035 }
02036
02037 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
02038 .load = load_module,
02039 .unload = unload_module,
02040 .reload = reload,
02041 );