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