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: 281497 $")
00039
00040 #include <osp/osp.h>
00041 #include <osp/osputils.h>
00042 #include <osp/ospb64.h>
00043
00044 #include "asterisk/paths.h"
00045 #include "asterisk/lock.h"
00046 #include "asterisk/config.h"
00047 #include "asterisk/utils.h"
00048 #include "asterisk/causes.h"
00049 #include "asterisk/channel.h"
00050 #include "asterisk/app.h"
00051 #include "asterisk/module.h"
00052 #include "asterisk/pbx.h"
00053 #include "asterisk/cli.h"
00054 #include "asterisk/astosp.h"
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 #define OSP_SIZE_INTSTR ((unsigned int)16)
00430 #define OSP_SIZE_NORSTR ((unsigned int)256)
00431 #define OSP_SIZE_KEYSTR ((unsigned int)1024)
00432 #define OSP_SIZE_TOKSTR ((unsigned int)4096)
00433 #define OSP_SIZE_TECHSTR ((unsigned int)32)
00434 #define OSP_SIZE_UUID ((unsigned int)16)
00435 #define OSP_SIZE_UUIDSTR ((unsigned int)36)
00436 #define OSP_SIZE_QOSSTR ((unsigned int)1024)
00437
00438
00439 #define OSP_CALLID_UNDEF ((unsigned int)0)
00440 #define OSP_CALLID_SIP ((unsigned int)(1 << 0))
00441 #define OSP_CALLID_H323 ((unsigned int)(1 << 1))
00442 #define OSP_CALLID_IAX ((unsigned int)(1 << 2))
00443 #define OSP_CALLID_MAXNUM ((unsigned int)3)
00444
00445
00446 #define OSP_PROT_SIP ((const char*)"SIP")
00447 #define OSP_PROT_H323 ((const char*)"H323")
00448 #define OSP_PROT_IAX ((const char*)"IAX")
00449 #define OSP_PROT_SKYPE ((const char*)"SKYPE")
00450
00451
00452 #define OSP_TECH_SIP ((const char*)"SIP")
00453 #define OSP_TECH_H323 ((const char*)"H323")
00454 #define OSP_TECH_IAX ((const char*)"IAX2")
00455 #define OSP_TECH_SKYPE ((const char*)"SKYPE")
00456
00457
00458 #define OSP_SIP_HEADER ((const char*)"P-OSP-Auth-Token")
00459
00460
00461 enum osp_authpolicy {
00462 OSP_AUTH_NO = 0,
00463 OSP_AUTH_YES,
00464 OSP_AUTH_EXC
00465 };
00466
00467
00468 enum osp_workmode {
00469 OSP_MODE_DIRECT= 0,
00470 OSP_MODE_INDIRECT
00471 };
00472
00473
00474 enum osp_srvtype {
00475 OSP_SRV_VOICE = 0,
00476 OSP_SRV_NPQUERY
00477 };
00478
00479
00480 #define OSP_OK ((int)1)
00481 #define OSP_FAILED ((int)0)
00482 #define OSP_ERROR ((int)-1)
00483 #define OSP_AST_OK ((int)0)
00484 #define OSP_AST_ERROR ((int)-1)
00485 #define OSP_INVALID_HANDLE ((int)-1)
00486 #define OSP_CONFIG_FILE ((const char*)"osp.conf")
00487 #define OSP_GENERAL_CAT ((const char*)"general")
00488 #define OSP_DEF_PROVIDER ((const char*)"default")
00489 #define OSP_MAX_CERTS ((unsigned int)10)
00490 #define OSP_MAX_SPOINTS ((unsigned int)10)
00491 #define OSP_DEF_MAXCONNECT ((unsigned int)20)
00492 #define OSP_MIN_MAXCONNECT ((unsigned int)1)
00493 #define OSP_MAX_MAXCONNECT ((unsigned int)1000)
00494 #define OSP_DEF_RETRYDELAY ((unsigned int)0)
00495 #define OSP_MIN_RETRYDELAY ((unsigned int)0)
00496 #define OSP_MAX_RETRYDELAY ((unsigned int)10)
00497 #define OSP_DEF_RETRYLIMIT ((unsigned int)2)
00498 #define OSP_MIN_RETRYLIMIT ((unsigned int)0)
00499 #define OSP_MAX_RETRYLIMIT ((unsigned int)100)
00500 #define OSP_DEF_TIMEOUT ((unsigned int)500)
00501 #define OSP_MIN_TIMEOUT ((unsigned int)200)
00502 #define OSP_MAX_TIMEOUT ((unsigned int)10000)
00503 #define OSP_DEF_AUTHPOLICY OSP_AUTH_YES
00504 #define OSP_AUDIT_URL ((const char*)"localhost")
00505 #define OSP_LOCAL_VALIDATION ((int)1)
00506 #define OSP_SSL_LIFETIME ((unsigned int)300)
00507 #define OSP_HTTP_PERSISTENCE ((int)1)
00508 #define OSP_CUSTOMER_ID ((const char*)"")
00509 #define OSP_DEVICE_ID ((const char*)"")
00510 #define OSP_DEF_MAXDESTS ((unsigned int)5)
00511 #define OSP_DEF_TIMELIMIT ((unsigned int)0)
00512 #define OSP_DEF_PROTOCOL OSP_PROT_SIP
00513 #define OSP_DEF_WORKMODE OSP_MODE_DIRECT
00514 #define OSP_DEF_SRVTYPE OSP_SRV_VOICE
00515 #define OSP_MAX_CUSTOMINFO ((unsigned int)8)
00516 #define OSP_DEF_INTSTATS ((int)-1)
00517 #define OSP_DEF_FLOATSTATS ((float)-1)
00518
00519
00520 struct osp_provider {
00521 OSPTPROVHANDLE handle;
00522 char name[OSP_SIZE_NORSTR];
00523 char privatekey[OSP_SIZE_NORSTR];
00524 char localcert[OSP_SIZE_NORSTR];
00525 unsigned int canum;
00526 char cacerts[OSP_MAX_CERTS][OSP_SIZE_NORSTR];
00527 unsigned int spnum;
00528 char spoints[OSP_MAX_SPOINTS][OSP_SIZE_NORSTR];
00529 unsigned int maxconnect;
00530 unsigned int retrydelay;
00531 unsigned int retrylimit;
00532 unsigned int timeout;
00533 char source[OSP_SIZE_NORSTR];
00534 enum osp_authpolicy authpolicy;
00535 const char* defprotocol;
00536 enum osp_workmode workmode;
00537 enum osp_srvtype srvtype;
00538 struct osp_provider* next;
00539 };
00540
00541
00542 struct osp_callid {
00543 unsigned char buf[OSP_SIZE_NORSTR];
00544 unsigned int len;
00545 };
00546
00547
00548 struct osp_npdata {
00549 const char* rn;
00550 const char* cic;
00551 int npdi;
00552 const char* opname[OSPC_OPNAME_NUMBER];
00553 };
00554
00555
00556 struct osp_diversion {
00557 const char* user;
00558 const char* host;
00559 };
00560
00561
00562 struct osp_results {
00563 int inhandle;
00564 int outhandle;
00565 unsigned int intimelimit;
00566 unsigned int outtimelimit;
00567 char tech[OSP_SIZE_TECHSTR];
00568 char dest[OSP_SIZE_NORSTR];
00569 char calling[OSP_SIZE_NORSTR];
00570 char called[OSP_SIZE_NORSTR];
00571 char token[OSP_SIZE_TOKSTR];
00572 char networkid[OSP_SIZE_NORSTR];
00573 char nprn[OSP_SIZE_NORSTR];
00574 char npcic[OSP_SIZE_NORSTR];
00575 int npdi;
00576 char opname[OSPC_OPNAME_NUMBER][OSP_SIZE_NORSTR];
00577 unsigned int numdests;
00578 struct osp_callid outcallid;
00579 };
00580
00581
00582 enum osp_callleg {
00583 OSP_CALL_INBOUND,
00584 OSP_CALL_OUTBOUND
00585 };
00586
00587
00588 enum osp_direction {
00589 OSP_DIR_RX = 0,
00590 OSP_DIR_TX,
00591 OSP_DIR_NUMBER
00592 };
00593
00594
00595 struct osp_metrics {
00596 int value;
00597 float min;
00598 float max;
00599 float avg;
00600 float ndev;
00601 float sdev;
00602 };
00603
00604
00605 AST_MUTEX_DEFINE_STATIC(osp_lock);
00606 static int osp_initialized = 0;
00607 static int osp_hardware = 0;
00608 static int osp_security = 0;
00609 static struct osp_provider* osp_providers = NULL;
00610 static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED;
00611
00612
00613 const char* B64PKey = "MIIBOgIBAAJBAK8t5l+PUbTC4lvwlNxV5lpl+2dwSZGW46dowTe6y133XyVEwNiiRma2YNk3xKs/TJ3Wl9Wpns2SYEAJsFfSTukCAwEAAQJAPz13vCm2GmZ8Zyp74usTxLCqSJZNyMRLHQWBM0g44Iuy4wE3vpi7Wq+xYuSOH2mu4OddnxswCP4QhaXVQavTAQIhAOBVCKXtppEw9UaOBL4vW0Ed/6EA/1D8hDW6St0h7EXJAiEAx+iRmZKhJD6VT84dtX5ZYNVk3j3dAcIOovpzUj9a0CECIEduTCapmZQ5xqAEsLXuVlxRtQgLTUD4ZxDElPn8x0MhAiBE2HlcND0+qDbvtwJQQOUzDgqg5xk3w8capboVdzAlQQIhAMC+lDL7+gDYkNAft5Mu+NObJmQs4Cr+DkDFsKqoxqrm";
00614 const char* B64LCert = "MIIBeTCCASMCEHqkOHVRRWr+1COq3CR/xsowDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTA1MDYyMzAwMjkxOFoXDTA2MDYyNDAwMjkxOFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCvLeZfj1G0wuJb8JTcVeZaZftncEmRluOnaME3ustd918lRMDYokZmtmDZN8SrP0yd1pfVqZ7NkmBACbBX0k7pAgMBAAEwDQYJKoZIhvcNAQEEBQADQQDnV8QNFVVJx/+7IselU0wsepqMurivXZzuxOmTEmTVDzCJx1xhA8jd3vGAj7XDIYiPub1PV23eY5a2ARJuw5w9";
00615 const char* B64CACert = "MIIBYDCCAQoCAQEwDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTAyMDIwNDE4MjU1MloXDTEyMDIwMzE4MjU1MlowOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPGeGwV41EIhX0jEDFLRXQhDEr50OUQPq+f55VwQd0TQNts06BP29+UiNdRW3c3IRHdZcJdC1Cg68ME9cgeq0h8CAwEAATANBgkqhkiG9w0BAQQFAANBAGkzBSj1EnnmUxbaiG1N4xjIuLAWydun7o3bFk2tV8dBIhnuh445obYyk1EnQ27kI7eACCILBZqi2MHDOIMnoN0=";
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625 static int osp_create_provider(
00626 struct ast_config* cfg,
00627 const char* name)
00628 {
00629 int res = OSP_FAILED;
00630 struct ast_variable* var;
00631 struct osp_provider* provider;
00632 OSPTPRIVATEKEY privatekey;
00633 OSPT_CERT localcert;
00634 OSPT_CERT cacerts[OSP_MAX_CERTS];
00635 const OSPT_CERT* pcacerts[OSP_MAX_CERTS];
00636 const char* pspoints[OSP_MAX_SPOINTS];
00637 unsigned char privatekeydata[OSP_SIZE_KEYSTR];
00638 unsigned char localcertdata[OSP_SIZE_KEYSTR];
00639 unsigned char cacertdata[OSP_SIZE_KEYSTR];
00640 int i, num, error = OSPC_ERR_NO_ERROR;
00641
00642 if (!(provider = ast_calloc(1, sizeof(*provider)))) {
00643 ast_log(LOG_ERROR, "Out of memory\n");
00644 return OSP_ERROR;
00645 }
00646
00647
00648 provider->handle = OSP_INVALID_HANDLE;
00649 ast_copy_string(provider->name, name, sizeof(provider->name));
00650 snprintf(provider->privatekey, sizeof(provider->privatekey), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, name);
00651 snprintf(provider->localcert, sizeof(provider->localcert), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, name);
00652 snprintf(provider->cacerts[0], sizeof(provider->cacerts[0]), "%s/%s-cacert_0.pem", ast_config_AST_KEY_DIR, name);
00653 provider->maxconnect = OSP_DEF_MAXCONNECT;
00654 provider->retrydelay = OSP_DEF_RETRYDELAY;
00655 provider->retrylimit = OSP_DEF_RETRYLIMIT;
00656 provider->timeout = OSP_DEF_TIMEOUT;
00657 provider->authpolicy = OSP_DEF_AUTHPOLICY;
00658 provider->defprotocol = OSP_DEF_PROTOCOL;
00659 provider->workmode = OSP_DEF_WORKMODE;
00660 provider->srvtype = OSP_DEF_SRVTYPE;
00661
00662 for (var = ast_variable_browse(cfg, name); var != NULL; var = var->next) {
00663 if (!strcasecmp(var->name, "privatekey")) {
00664 if (osp_security) {
00665 if (var->value[0] == '/') {
00666 ast_copy_string(provider->privatekey, var->value, sizeof(provider->privatekey));
00667 } else {
00668 snprintf(provider->privatekey, sizeof(provider->privatekey), "%s/%s", ast_config_AST_KEY_DIR, var->value);
00669 }
00670 ast_debug(1, "OSP: privatekey '%s'\n", provider->privatekey);
00671 }
00672 } else if (!strcasecmp(var->name, "localcert")) {
00673 if (osp_security) {
00674 if (var->value[0] == '/') {
00675 ast_copy_string(provider->localcert, var->value, sizeof(provider->localcert));
00676 } else {
00677 snprintf(provider->localcert, sizeof(provider->localcert), "%s/%s", ast_config_AST_KEY_DIR, var->value);
00678 }
00679 ast_debug(1, "OSP: localcert '%s'\n", provider->localcert);
00680 }
00681 } else if (!strcasecmp(var->name, "cacert")) {
00682 if (osp_security) {
00683 if (provider->canum < OSP_MAX_CERTS) {
00684 if (var->value[0] == '/') {
00685 ast_copy_string(provider->cacerts[provider->canum], var->value, sizeof(provider->cacerts[provider->canum]));
00686 } else {
00687 snprintf(provider->cacerts[provider->canum], sizeof(provider->cacerts[provider->canum]), "%s/%s", ast_config_AST_KEY_DIR, var->value);
00688 }
00689 ast_debug(1, "OSP: cacerts[%d]: '%s'\n", provider->canum, provider->cacerts[provider->canum]);
00690 provider->canum++;
00691 } else {
00692 ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", var->lineno);
00693 }
00694 }
00695 } else if (!strcasecmp(var->name, "servicepoint")) {
00696 if (provider->spnum < OSP_MAX_SPOINTS) {
00697 ast_copy_string(provider->spoints[provider->spnum], var->value, sizeof(provider->spoints[provider->spnum]));
00698 ast_debug(1, "OSP: servicepoint[%d]: '%s'\n", provider->spnum, provider->spoints[provider->spnum]);
00699 provider->spnum++;
00700 } else {
00701 ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", var->lineno);
00702 }
00703 } else if (!strcasecmp(var->name, "maxconnect")) {
00704 if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_MAXCONNECT) && (num <= OSP_MAX_MAXCONNECT)) {
00705 provider->maxconnect = num;
00706 ast_debug(1, "OSP: maxconnect '%d'\n", num);
00707 } else {
00708 ast_log(LOG_WARNING, "OSP: maxconnect should be an integer from %d to %d, not '%s' at line %d\n",
00709 OSP_MIN_MAXCONNECT, OSP_MAX_MAXCONNECT, var->value, var->lineno);
00710 }
00711 } else if (!strcasecmp(var->name, "retrydelay")) {
00712 if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_RETRYDELAY) && (num <= OSP_MAX_RETRYDELAY)) {
00713 provider->retrydelay = num;
00714 ast_debug(1, "OSP: retrydelay '%d'\n", num);
00715 } else {
00716 ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n",
00717 OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY, var->value, var->lineno);
00718 }
00719 } else if (!strcasecmp(var->name, "retrylimit")) {
00720 if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_RETRYLIMIT) && (num <= OSP_MAX_RETRYLIMIT)) {
00721 provider->retrylimit = num;
00722 ast_debug(1, "OSP: retrylimit '%d'\n", num);
00723 } else {
00724 ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n",
00725 OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT, var->value, var->lineno);
00726 }
00727 } else if (!strcasecmp(var->name, "timeout")) {
00728 if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_TIMEOUT) && (num <= OSP_MAX_TIMEOUT)) {
00729 provider->timeout = num;
00730 ast_debug(1, "OSP: timeout '%d'\n", num);
00731 } else {
00732 ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n",
00733 OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT, var->value, var->lineno);
00734 }
00735 } else if (!strcasecmp(var->name, "source")) {
00736 ast_copy_string(provider->source, var->value, sizeof(provider->source));
00737 ast_debug(1, "OSP: source '%s'\n", provider->source);
00738 } else if (!strcasecmp(var->name, "authpolicy")) {
00739 if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_AUTH_NO) || (num == OSP_AUTH_YES) || (num == OSP_AUTH_EXC))) {
00740 provider->authpolicy = num;
00741 ast_debug(1, "OSP: authpolicy '%d'\n", num);
00742 } else {
00743 ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n",
00744 OSP_AUTH_NO, OSP_AUTH_YES, OSP_AUTH_EXC, var->value, var->lineno);
00745 }
00746 } else if (!strcasecmp(var->name, "defprotocol")) {
00747 if (!strcasecmp(var->value, OSP_PROT_SIP)) {
00748 provider->defprotocol = OSP_PROT_SIP;
00749 ast_debug(1, "OSP: default protocol SIP\n");
00750 } else if (!strcasecmp(var->value, OSP_PROT_H323)) {
00751 provider->defprotocol = OSP_PROT_H323;
00752 ast_debug(1, "OSP: default protocol H.323\n");
00753 } else if (!strcasecmp(var->value, OSP_PROT_IAX)) {
00754 provider->defprotocol = OSP_PROT_IAX;
00755 ast_debug(1, "OSP: default protocol IAX\n");
00756 } else if (!strcasecmp(var->value, OSP_PROT_SKYPE)) {
00757 provider->defprotocol = OSP_PROT_SKYPE;
00758 ast_debug(1, "OSP: default protocol Skype\n");
00759 } else {
00760 ast_log(LOG_WARNING, "OSP: default protocol should be %s, %s, %s or %s not '%s' at line %d\n",
00761 OSP_PROT_SIP, OSP_PROT_H323, OSP_PROT_IAX, OSP_PROT_SKYPE, var->value, var->lineno);
00762 }
00763 } else if (!strcasecmp(var->name, "workmode")) {
00764 if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_MODE_DIRECT) || (num == OSP_MODE_INDIRECT))) {
00765 provider->workmode = num;
00766 ast_debug(1, "OSP: workmode '%d'\n", num);
00767 } else {
00768 ast_log(LOG_WARNING, "OSP: workmode should be %d or %d, not '%s' at line %d\n",
00769 OSP_MODE_DIRECT, OSP_MODE_INDIRECT, var->value, var->lineno);
00770 }
00771 } else if (!strcasecmp(var->name, "servicetype")) {
00772 if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_SRV_VOICE) || (num == OSP_SRV_NPQUERY))) {
00773 provider->srvtype = num;
00774 ast_debug(1, "OSP: servicetype '%d'\n", num);
00775 } else {
00776 ast_log(LOG_WARNING, "OSP: servicetype should be %d or %d, not '%s' at line %d\n",
00777 OSP_SRV_VOICE, OSP_SRV_NPQUERY, var->value, var->lineno);
00778 }
00779 }
00780 }
00781
00782 if (provider->canum == 0) {
00783 provider->canum = 1;
00784 }
00785
00786 for (i = 0; i < provider->spnum; i++) {
00787 pspoints[i] = provider->spoints[i];
00788 }
00789
00790 if (osp_security) {
00791 privatekey.PrivateKeyData = NULL;
00792 privatekey.PrivateKeyLength = 0;
00793
00794 localcert.CertData = NULL;
00795 localcert.CertDataLength = 0;
00796
00797 for (i = 0; i < provider->canum; i++) {
00798 cacerts[i].CertData = NULL;
00799 cacerts[i].CertDataLength = 0;
00800 }
00801
00802 if ((error = OSPPUtilLoadPEMPrivateKey((unsigned char*)provider->privatekey, &privatekey)) != OSPC_ERR_NO_ERROR) {
00803 ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", provider->privatekey, error);
00804 } else if ((error = OSPPUtilLoadPEMCert((unsigned char*)provider->localcert, &localcert)) != OSPC_ERR_NO_ERROR) {
00805 ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", provider->localcert, error);
00806 } else {
00807 for (i = 0; i < provider->canum; i++) {
00808 if ((error = OSPPUtilLoadPEMCert((unsigned char*)provider->cacerts[i], &cacerts[i])) != OSPC_ERR_NO_ERROR) {
00809 ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", provider->cacerts[i], error);
00810 break;
00811 } else {
00812 pcacerts[i] = &cacerts[i];
00813 }
00814 }
00815 }
00816 } else {
00817 privatekey.PrivateKeyData = privatekeydata;
00818 privatekey.PrivateKeyLength = sizeof(privatekeydata);
00819
00820 localcert.CertData = localcertdata;
00821 localcert.CertDataLength = sizeof(localcertdata);
00822
00823 cacerts[0].CertData = cacertdata;
00824 cacerts[0].CertDataLength = sizeof(cacertdata);
00825 pcacerts[0] = &cacerts[0];
00826
00827 if ((error = OSPPBase64Decode(B64PKey, strlen(B64PKey), privatekey.PrivateKeyData, &privatekey.PrivateKeyLength)) != OSPC_ERR_NO_ERROR) {
00828 ast_log(LOG_WARNING, "OSP: Unable to decode private key, error '%d'\n", error);
00829 } else if ((error = OSPPBase64Decode(B64LCert, strlen(B64LCert), localcert.CertData, &localcert.CertDataLength)) != OSPC_ERR_NO_ERROR) {
00830 ast_log(LOG_WARNING, "OSP: Unable to decode local cert, error '%d'\n", error);
00831 } else if ((error = OSPPBase64Decode(B64CACert, strlen(B64CACert), cacerts[0].CertData, &cacerts[0].CertDataLength)) != OSPC_ERR_NO_ERROR) {
00832 ast_log(LOG_WARNING, "OSP: Unable to decode cacert, error '%d'\n", error);
00833 }
00834 }
00835
00836 if (error == OSPC_ERR_NO_ERROR) {
00837 error = OSPPProviderNew(provider->spnum,
00838 pspoints,
00839 NULL,
00840 OSP_AUDIT_URL,
00841 &privatekey,
00842 &localcert,
00843 provider->canum,
00844 pcacerts,
00845 OSP_LOCAL_VALIDATION,
00846 OSP_SSL_LIFETIME,
00847 provider->maxconnect,
00848 OSP_HTTP_PERSISTENCE,
00849 provider->retrydelay,
00850 provider->retrylimit,
00851 provider->timeout,
00852 OSP_CUSTOMER_ID,
00853 OSP_DEVICE_ID,
00854 &provider->handle);
00855 if (error != OSPC_ERR_NO_ERROR) {
00856 ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", name, error);
00857 res = OSP_ERROR;
00858 } else {
00859 ast_debug(1, "OSP: provider '%s'\n", name);
00860 ast_mutex_lock(&osp_lock);
00861 provider->next = osp_providers;
00862 osp_providers = provider;
00863 ast_mutex_unlock(&osp_lock);
00864 res = OSP_OK;
00865 }
00866 }
00867
00868 if (osp_security) {
00869 for (i = 0; i < provider->canum; i++) {
00870 if (cacerts[i].CertData) {
00871 ast_free(cacerts[i].CertData);
00872 }
00873 }
00874 if (localcert.CertData) {
00875 ast_free(localcert.CertData);
00876 }
00877 if (privatekey.PrivateKeyData) {
00878 ast_free(privatekey.PrivateKeyData);
00879 }
00880 }
00881
00882 if (res != OSP_OK) {
00883 ast_free(provider);
00884 }
00885
00886 return res;
00887 }
00888
00889
00890
00891
00892
00893
00894
00895 static int osp_get_provider(
00896 const char* name,
00897 struct osp_provider** provider)
00898 {
00899 int res = OSP_FAILED;
00900 struct osp_provider* p;
00901
00902 *provider = NULL;
00903
00904 ast_mutex_lock(&osp_lock);
00905 for (p = osp_providers; p != NULL; p = p->next) {
00906 if (!strcasecmp(p->name, name)) {
00907 *provider = p;
00908 ast_debug(1, "OSP: find provider '%s'\n", name);
00909 res = OSP_OK;
00910 break;
00911 }
00912 }
00913 ast_mutex_unlock(&osp_lock);
00914
00915 return res;
00916 }
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926 static int osp_create_transaction(
00927 const char* name,
00928 int* trans,
00929 char* source,
00930 unsigned int srcsize)
00931 {
00932 int res = OSP_FAILED;
00933 struct osp_provider* provider;
00934 int error;
00935
00936 if ((trans == NULL) || (source == NULL) || (srcsize <= 0)) {
00937 ast_log(LOG_ERROR, "Invalid parameters\n");
00938 return OSP_ERROR;
00939 }
00940
00941 *trans = OSP_INVALID_HANDLE;
00942 *source = '\0';
00943
00944 ast_mutex_lock(&osp_lock);
00945 for (provider = osp_providers; provider; provider = provider->next) {
00946 if (!strcasecmp(provider->name, name)) {
00947 error = OSPPTransactionNew(provider->handle, trans);
00948 if (error == OSPC_ERR_NO_ERROR) {
00949 ast_debug(1, "OSP: transaction '%d'\n", *trans);
00950 ast_copy_string(source, provider->source, srcsize);
00951 ast_debug(1, "OSP: source '%s'\n", source);
00952 res = OSP_OK;
00953 } else {
00954 *trans = OSP_INVALID_HANDLE;
00955 ast_debug(1, "OSP: Unable to create transaction handle, error '%d'\n", error);
00956 *source = '\0';
00957 res = OSP_ERROR;
00958 }
00959 break;
00960 }
00961 }
00962 ast_mutex_unlock(&osp_lock);
00963
00964 return res;
00965 }
00966
00967
00968
00969
00970
00971
00972
00973 static void osp_convert_inout(
00974 const char* src,
00975 char* dest,
00976 unsigned int destsize)
00977 {
00978 struct in_addr inp;
00979 char buffer[OSP_SIZE_NORSTR];
00980 char* port;
00981
00982 if ((dest != NULL) && (destsize > 0)) {
00983 if (!ast_strlen_zero(src)) {
00984 ast_copy_string(buffer, src, sizeof(buffer));
00985
00986 if((port = strchr(buffer, ':')) != NULL) {
00987 *port = '\0';
00988 port++;
00989 }
00990
00991 if (inet_pton(AF_INET, buffer, &inp) == 1) {
00992 if (port != NULL) {
00993 snprintf(dest, destsize, "[%s]:%s", buffer, port);
00994 } else {
00995 snprintf(dest, destsize, "[%s]", buffer);
00996 }
00997 dest[destsize - 1] = '\0';
00998 } else {
00999 ast_copy_string(dest, src, destsize);
01000 }
01001 } else {
01002 *dest = '\0';
01003 }
01004 }
01005 }
01006
01007
01008
01009
01010
01011
01012
01013 static void osp_convert_outin(
01014 const char* src,
01015 char* dest,
01016 unsigned int destsize)
01017 {
01018 char buffer[OSP_SIZE_NORSTR];
01019 char* end;
01020 char* port;
01021
01022 if ((dest != NULL) && (destsize > 0)) {
01023 if (!ast_strlen_zero(src)) {
01024 ast_copy_string(buffer, src, sizeof(buffer));
01025
01026 if (buffer[0] == '[') {
01027 if((port = strchr(buffer + 1, ':')) != NULL) {
01028 *port = '\0';
01029 port++;
01030 }
01031
01032 if ((end = strchr(buffer + 1, ']')) != NULL) {
01033 *end = '\0';
01034 }
01035
01036 if (port != NULL) {
01037 snprintf(dest, destsize, "%s:%s", buffer + 1, port);
01038 dest[destsize - 1] = '\0';
01039 } else {
01040 ast_copy_string(dest, buffer + 1, destsize);
01041 }
01042 } else {
01043 ast_copy_string(dest, src, destsize);
01044 }
01045 } else {
01046 *dest = '\0';
01047 }
01048 }
01049 }
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 static int osp_validate_token(
01063 int trans,
01064 const char* source,
01065 const char* destination,
01066 const char* calling,
01067 const char* called,
01068 const char* token,
01069 unsigned int* timelimit)
01070 {
01071 int res;
01072 int tokenlen;
01073 unsigned char tokenstr[OSP_SIZE_TOKSTR];
01074 char src[OSP_SIZE_NORSTR];
01075 char dest[OSP_SIZE_NORSTR];
01076 unsigned int authorised;
01077 unsigned int dummy = 0;
01078 int error;
01079
01080 if (timelimit == NULL) {
01081 ast_log(LOG_ERROR, "Invalid parameters\n");
01082 return OSP_ERROR;
01083 }
01084
01085 tokenlen = ast_base64decode(tokenstr, token, strlen(token));
01086 osp_convert_inout(source, src, sizeof(src));
01087 osp_convert_inout(destination, dest, sizeof(dest));
01088 error = OSPPTransactionValidateAuthorisation(trans,
01089 src,
01090 dest,
01091 NULL,
01092 NULL,
01093 calling ? calling : "",
01094 OSPC_NFORMAT_E164,
01095 called,
01096 OSPC_NFORMAT_E164,
01097 0,
01098 NULL,
01099 tokenlen,
01100 (char*)tokenstr,
01101 &authorised,
01102 timelimit,
01103 &dummy,
01104 NULL,
01105 osp_tokenformat);
01106 if (error != OSPC_ERR_NO_ERROR) {
01107 ast_log(LOG_WARNING, "OSP: Unable to validate inbound token, error '%d'\n", error);
01108 *timelimit = 0;
01109 res = OSP_ERROR;
01110 } else if (authorised) {
01111 ast_debug(1, "OSP: Authorised\n");
01112 res = OSP_OK;
01113 } else {
01114 ast_debug(1, "OSP: Unauthorised\n");
01115 res = OSP_FAILED;
01116 }
01117
01118 return res;
01119 }
01120
01121
01122
01123
01124
01125
01126
01127 static unsigned int osp_choose_timelimit(
01128 unsigned int in,
01129 unsigned int out)
01130 {
01131 if (in == OSP_DEF_TIMELIMIT) {
01132 return out;
01133 } else if (out == OSP_DEF_TIMELIMIT) {
01134 return in;
01135 } else {
01136 return in < out ? in : out;
01137 }
01138 }
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152 static int osp_check_destination(
01153 struct osp_provider* provider,
01154 const char* calling,
01155 const char* called,
01156 const char* destination,
01157 unsigned int tokenlen,
01158 const char* token,
01159 OSPEFAILREASON* reason,
01160 struct osp_results* results)
01161 {
01162 int res;
01163 OSPE_DEST_OSPENABLED enabled;
01164 OSPE_DEST_PROTOCOL protocol;
01165 char dest[OSP_SIZE_NORSTR];
01166 OSPE_OPERATOR_NAME type;
01167 int error;
01168
01169 if ((provider == NULL) || (reason == NULL) || (results == NULL)) {
01170 ast_log(LOG_ERROR, "Invalid parameters\n");
01171 return OSP_ERROR;
01172 }
01173
01174 if ((error = OSPPTransactionIsDestOSPEnabled(results->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) {
01175 ast_debug(1, "OSP: Unable to get destination OSP version, error '%d'\n", error);
01176 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
01177 return OSP_ERROR;
01178 }
01179
01180 if (enabled == OSPC_DOSP_FALSE) {
01181 results->token[0] = '\0';
01182 } else {
01183 ast_base64encode(results->token, (const unsigned char*)token, tokenlen, sizeof(results->token) - 1);
01184 }
01185
01186 if ((error = OSPPTransactionGetDestinationNetworkId(results->outhandle, sizeof(results->networkid), results->networkid)) != OSPC_ERR_NO_ERROR) {
01187 ast_debug(1, "OSP: Unable to get destination network ID, error '%d'\n", error);
01188 results->networkid[0] = '\0';
01189 }
01190
01191 error = OSPPTransactionGetNumberPortabilityParameters(results->outhandle,
01192 sizeof(results->nprn),
01193 results->nprn,
01194 sizeof(results->npcic),
01195 results->npcic,
01196 &results->npdi);
01197 if (error != OSPC_ERR_NO_ERROR) {
01198 ast_debug(1, "OSP: Unable to get number portability parameters, error '%d'\n", error);
01199 results->nprn[0] = '\0';
01200 results->npcic[0] = '\0';
01201 results->npdi = 0;
01202 }
01203
01204 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
01205 error = OSPPTransactionGetOperatorName(results->outhandle, type, sizeof(results->opname[type]), results->opname[type]);
01206 if (error != OSPC_ERR_NO_ERROR) {
01207 ast_debug(1, "OSP: Unable to get operator name of type '%d', error '%d'\n", type, error);
01208 results->opname[type][0] = '\0';
01209 }
01210 }
01211
01212 if ((error = OSPPTransactionGetDestProtocol(results->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
01213 ast_debug(1, "OSP: Unable to get destination protocol, error '%d'\n", error);
01214 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
01215 results->token[0] = '\0';
01216 results->networkid[0] = '\0';
01217 results->nprn[0] = '\0';
01218 results->npcic[0] = '\0';
01219 results->npdi = 0;
01220 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
01221 results->opname[type][0] = '\0';
01222 }
01223 return OSP_ERROR;
01224 }
01225
01226 res = OSP_OK;
01227 osp_convert_outin(destination, dest, sizeof(dest));
01228 switch(protocol) {
01229 case OSPC_DPROT_SIP:
01230 ast_debug(1, "OSP: protocol SIP\n");
01231 ast_copy_string(results->tech, OSP_TECH_SIP, sizeof(results->tech));
01232 ast_copy_string(results->dest, dest, sizeof(results->dest));
01233 ast_copy_string(results->calling, calling, sizeof(results->calling));
01234 ast_copy_string(results->called, called, sizeof(results->called));
01235 break;
01236 case OSPC_DPROT_Q931:
01237 ast_debug(1, "OSP: protocol Q.931\n");
01238 ast_copy_string(results->tech, OSP_TECH_H323, sizeof(results->tech));
01239 ast_copy_string(results->dest, dest, sizeof(results->dest));
01240 ast_copy_string(results->calling, calling, sizeof(results->calling));
01241 ast_copy_string(results->called, called, sizeof(results->called));
01242 break;
01243 case OSPC_DPROT_IAX:
01244 ast_debug(1, "OSP: protocol IAX\n");
01245 ast_copy_string(results->tech, OSP_TECH_IAX, sizeof(results->tech));
01246 ast_copy_string(results->dest, dest, sizeof(results->dest));
01247 ast_copy_string(results->calling, calling, sizeof(results->calling));
01248 ast_copy_string(results->called, called, sizeof(results->called));
01249 break;
01250 case OSPC_DPROT_SKYPE:
01251 ast_debug(1, "OSP: protocol Skype\n");
01252 ast_copy_string(results->tech, OSP_TECH_SKYPE, sizeof(results->tech));
01253 ast_copy_string(results->dest, dest, sizeof(results->dest));
01254 ast_copy_string(results->calling, calling, sizeof(results->calling));
01255 ast_copy_string(results->called, called, sizeof(results->called));
01256 break;
01257 case OSPC_DPROT_UNDEFINED:
01258 case OSPC_DPROT_UNKNOWN:
01259 ast_debug(1, "OSP: unknown/undefined protocol '%d'\n", protocol);
01260 ast_debug(1, "OSP: use default protocol '%s'\n", provider->defprotocol);
01261 ast_copy_string(results->tech, provider->defprotocol, sizeof(results->tech));
01262 ast_copy_string(results->dest, dest, sizeof(results->dest));
01263 ast_copy_string(results->calling, calling, sizeof(results->calling));
01264 ast_copy_string(results->called, called, sizeof(results->called));
01265 break;
01266 case OSPC_DPROT_LRQ:
01267 case OSPC_DPROT_T37:
01268 case OSPC_DPROT_T38:
01269 case OSPC_DPROT_SMPP:
01270 case OSPC_DPROT_XMPP:
01271 default:
01272 ast_log(LOG_WARNING, "OSP: unsupported protocol '%d'\n", protocol);
01273 *reason = OSPC_FAIL_PROTOCOL_ERROR;
01274 results->token[0] = '\0';
01275 results->networkid[0] = '\0';
01276 results->nprn[0] = '\0';
01277 results->npcic[0] = '\0';
01278 results->npdi = 0;
01279 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
01280 results->opname[type][0] = '\0';
01281 }
01282 res = OSP_FAILED;
01283 break;
01284 }
01285
01286 return res;
01287 }
01288
01289
01290
01291
01292
01293
01294 static OSPEFAILREASON asterisk2osp(
01295 int cause)
01296 {
01297 return (OSPEFAILREASON)cause;
01298 }
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311 static int osp_auth(
01312 const char* name,
01313 int* trans,
01314 const char* source,
01315 const char* calling,
01316 const char* called,
01317 const char* token,
01318 unsigned int* timelimit)
01319 {
01320 int res;
01321 struct osp_provider* provider = NULL;
01322 char dest[OSP_SIZE_NORSTR];
01323
01324 if ((trans == NULL) || (timelimit == NULL)) {
01325 ast_log(LOG_ERROR, "Invalid parameters\n");
01326 return OSP_ERROR;
01327 }
01328
01329 *trans = OSP_INVALID_HANDLE;
01330 *timelimit = OSP_DEF_TIMELIMIT;
01331
01332 if ((res = osp_get_provider(name, &provider)) <= 0) {
01333 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
01334 return res;
01335 }
01336
01337 switch (provider->authpolicy) {
01338 case OSP_AUTH_NO:
01339 res = OSP_OK;
01340 break;
01341 case OSP_AUTH_EXC:
01342 if (ast_strlen_zero(token)) {
01343 res = OSP_FAILED;
01344 } else if ((res = osp_create_transaction(name, trans, dest, sizeof(dest))) <= 0) {
01345 ast_debug(1, "OSP: Unable to generate transaction handle\n");
01346 *trans = OSP_INVALID_HANDLE;
01347 res = OSP_FAILED;
01348 } else if((res = osp_validate_token(*trans, source, dest, calling, called, token, timelimit)) <= 0) {
01349 OSPPTransactionRecordFailure(*trans, OSPC_FAIL_CALL_REJECTED);
01350 }
01351 break;
01352 case OSP_AUTH_YES:
01353 default:
01354 if (ast_strlen_zero(token)) {
01355 res = OSP_OK;
01356 } else if ((res = osp_create_transaction(name, trans, dest, sizeof(dest))) <= 0) {
01357 ast_debug(1, "OSP: Unable to generate transaction handle\n");
01358 *trans = OSP_INVALID_HANDLE;
01359 res = OSP_FAILED;
01360 } else if((res = osp_validate_token(*trans, source, dest, calling, called, token, timelimit)) <= 0) {
01361 OSPPTransactionRecordFailure(*trans, OSPC_FAIL_CALL_REJECTED);
01362 }
01363 break;
01364 }
01365
01366 return res;
01367 }
01368
01369
01370
01371
01372
01373
01374
01375 static int osp_create_uuid(
01376 unsigned char* uuid,
01377 unsigned int* bufsize)
01378 {
01379 int i, res;
01380 long int tmp[OSP_SIZE_UUID / sizeof(long int)];
01381
01382 if ((uuid != NULL) && (*bufsize >= OSP_SIZE_UUID)) {
01383 for (i = 0; i < OSP_SIZE_UUID / sizeof(long int); i++) {
01384 tmp[i] = ast_random();
01385 }
01386 memcpy(uuid, tmp, OSP_SIZE_UUID);
01387 *bufsize = OSP_SIZE_UUID;
01388 res = OSP_OK;
01389 } else {
01390 ast_log(LOG_ERROR, "Invalid parameters\n");
01391 res = OSP_ERROR;
01392 }
01393
01394 return res;
01395 }
01396
01397
01398
01399
01400
01401
01402
01403
01404 static int osp_uuid2str(
01405 unsigned char* uuid,
01406 char* buffer,
01407 unsigned int bufsize)
01408 {
01409 int res;
01410
01411 if ((uuid != NULL) && (bufsize > OSP_SIZE_UUIDSTR)) {
01412 snprintf(buffer, bufsize, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
01413 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
01414 uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
01415 res = OSP_OK;
01416 } else {
01417 ast_log(LOG_ERROR, "Invalid parameters\n");
01418 res = OSP_ERROR;
01419 }
01420
01421 return res;
01422 }
01423
01424
01425
01426
01427
01428
01429
01430 static int osp_create_callid(
01431 unsigned int type,
01432 struct osp_callid* callid)
01433 {
01434 int res;
01435
01436 if (callid == NULL) {
01437 ast_log(LOG_ERROR, "Invalid parameters\n");
01438 res = OSP_ERROR;
01439 }
01440
01441 callid->len = sizeof(callid->buf);
01442 switch (type) {
01443 case OSP_CALLID_H323:
01444 res = osp_create_uuid(callid->buf, &callid->len);
01445 break;
01446 case OSP_CALLID_SIP:
01447 case OSP_CALLID_IAX:
01448 res = OSP_FAILED;
01449 default:
01450 res = OSP_ERROR;
01451 break;
01452 }
01453
01454 if ((res != OSP_OK) && (callid->len != 0)) {
01455 callid->buf[0] = '\0';
01456 callid->len = 0;
01457 }
01458
01459 return res;
01460 }
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477 static int osp_lookup(
01478 const char* name,
01479 unsigned int callidtypes,
01480 const char* actualsrc,
01481 const char* srcdev,
01482 const char* calling,
01483 const char* called,
01484 const char* snetid,
01485 struct osp_npdata* np,
01486 struct osp_diversion* div,
01487 const char* cinfo[],
01488 struct osp_results* results)
01489 {
01490 int res;
01491 struct osp_provider* provider = NULL;
01492 char source[OSP_SIZE_NORSTR];
01493 char callingnum[OSP_SIZE_NORSTR];
01494 char callednum[OSP_SIZE_NORSTR];
01495 char destination[OSP_SIZE_NORSTR];
01496 char* tmp;
01497 unsigned int tokenlen;
01498 char token[OSP_SIZE_TOKSTR];
01499 char src[OSP_SIZE_NORSTR];
01500 char dev[OSP_SIZE_NORSTR];
01501 char host[OSP_SIZE_NORSTR];
01502 unsigned int i, type;
01503 struct osp_callid callid;
01504 unsigned int callidnum;
01505 OSPT_CALL_ID* callids[OSP_CALLID_MAXNUM];
01506 char dest[OSP_SIZE_NORSTR];
01507 const char* preferred[2] = { NULL };
01508 unsigned int dummy = 0;
01509 OSPEFAILREASON reason;
01510 int error;
01511
01512 if (results == NULL) {
01513 ast_log(LOG_ERROR, "Invalid parameters\n");
01514 res = OSP_ERROR;
01515 }
01516
01517 osp_convert_inout(results->dest, dest, sizeof(dest));
01518
01519 results->outhandle = OSP_INVALID_HANDLE;
01520 results->tech[0] = '\0';
01521 results->calling[0] = '\0';
01522 results->called[0] = '\0';
01523 results->token[0] = '\0';
01524 results->networkid[0] = '\0';
01525 results->nprn[0] = '\0';
01526 results->npcic[0] = '\0';
01527 results->npdi = 0;
01528 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
01529 results->opname[type][0] = '\0';
01530 }
01531 results->numdests = 0;
01532 results->outtimelimit = OSP_DEF_TIMELIMIT;
01533
01534 if ((res = osp_get_provider(name, &provider)) <= 0) {
01535 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
01536 return res;
01537 }
01538
01539 if ((res = osp_create_transaction(name, &results->outhandle, source, sizeof(source))) <= 0) {
01540 ast_debug(1, "OSP: Unable to generate transaction handle\n");
01541 results->outhandle = OSP_INVALID_HANDLE;
01542 if (results->inhandle != OSP_INVALID_HANDLE) {
01543 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
01544 }
01545 return OSP_ERROR;
01546 }
01547
01548 if (!ast_strlen_zero(snetid)) {
01549 OSPPTransactionSetNetworkIds(results->outhandle, snetid, "");
01550 }
01551
01552 OSPPTransactionSetNumberPortability(results->outhandle, np->rn, np->cic, np->npdi);
01553
01554 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
01555 OSPPTransactionSetOperatorName(results->outhandle, type, np->opname[type]);
01556 }
01557
01558 osp_convert_inout(div->host, host, sizeof(host));
01559 OSPPTransactionSetDiversion(results->outhandle, div->user, host);
01560
01561 if (cinfo != NULL) {
01562 for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
01563 if (!ast_strlen_zero(cinfo[i])) {
01564 OSPPTransactionSetCustomInfo(results->outhandle, i, cinfo[i]);
01565 }
01566 }
01567 }
01568
01569 ast_copy_string(callednum, called, sizeof(callednum));
01570 if((tmp = strchr(callednum, ';')) != NULL) {
01571 *tmp = '\0';
01572 }
01573
01574 callidnum = 0;
01575 callids[0] = NULL;
01576 for (i = 0; i < OSP_CALLID_MAXNUM; i++) {
01577 type = 1 << i;
01578 if (callidtypes & type) {
01579 error = osp_create_callid(type, &callid);
01580 if (error == 1) {
01581 callids[callidnum] = OSPPCallIdNew(callid.len, callid.buf);
01582 callidnum++;
01583 }
01584 }
01585 }
01586
01587 if (provider->workmode == OSP_MODE_INDIRECT) {
01588 osp_convert_inout(srcdev, src, sizeof(src));
01589 if (ast_strlen_zero(actualsrc)) {
01590 osp_convert_inout(srcdev, dev, sizeof(dev));
01591 } else {
01592 osp_convert_inout(actualsrc, dev, sizeof(dev));
01593 }
01594 } else {
01595 osp_convert_inout(source, src, sizeof(src));
01596 osp_convert_inout(srcdev, dev, sizeof(dev));
01597 }
01598
01599 if (provider->srvtype == OSP_SRV_NPQUERY) {
01600 OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_NPQUERY);
01601 if (!ast_strlen_zero(dest)) {
01602 preferred[0] = dest;
01603 }
01604 results->numdests = 1;
01605 } else {
01606 OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_VOICE);
01607 results->numdests = OSP_DEF_MAXDESTS;
01608 }
01609 error = OSPPTransactionRequestAuthorisation(results->outhandle,
01610 src,
01611 dev,
01612 calling ? calling : "",
01613 OSPC_NFORMAT_E164,
01614 callednum,
01615 OSPC_NFORMAT_E164,
01616 NULL,
01617 callidnum,
01618 callids,
01619 preferred,
01620 &results->numdests,
01621 &dummy,
01622 NULL);
01623
01624 for (i = 0; i < callidnum; i++) {
01625 OSPPCallIdDelete(&callids[i]);
01626 }
01627
01628 if (error != OSPC_ERR_NO_ERROR) {
01629 ast_log(LOG_WARNING, "OSP: Unable to request authorization, error '%d'\n", error);
01630 results->numdests = 0;
01631 if (results->inhandle != OSP_INVALID_HANDLE) {
01632 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
01633 }
01634 return OSP_ERROR;
01635 }
01636
01637 if (!results->numdests) {
01638 ast_debug(1, "OSP: No more destination\n");
01639 if (results->inhandle != OSP_INVALID_HANDLE) {
01640 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01641 }
01642 return OSP_FAILED;
01643 }
01644
01645 results->outcallid.len = sizeof(results->outcallid.buf);
01646 tokenlen = sizeof(token);
01647 error = OSPPTransactionGetFirstDestination(results->outhandle,
01648 0,
01649 NULL,
01650 NULL,
01651 &results->outtimelimit,
01652 &results->outcallid.len,
01653 results->outcallid.buf,
01654 sizeof(callednum),
01655 callednum,
01656 sizeof(callingnum),
01657 callingnum,
01658 sizeof(destination),
01659 destination,
01660 0,
01661 NULL,
01662 &tokenlen,
01663 token);
01664 if (error != OSPC_ERR_NO_ERROR) {
01665 ast_debug(1, "OSP: Unable to get first route, error '%d'\n", error);
01666 results->numdests = 0;
01667 results->outtimelimit = OSP_DEF_TIMELIMIT;
01668 if (results->inhandle != OSP_INVALID_HANDLE) {
01669 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01670 }
01671 return OSP_ERROR;
01672 }
01673
01674 results->numdests--;
01675 results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
01676 ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
01677 ast_debug(1, "OSP: calling '%s'\n", callingnum);
01678 ast_debug(1, "OSP: called '%s'\n", callednum);
01679 ast_debug(1, "OSP: destination '%s'\n", destination);
01680 ast_debug(1, "OSP: token size '%d'\n", tokenlen);
01681
01682 if ((res = osp_check_destination(provider, callingnum, callednum, destination, tokenlen, token, &reason, results)) > 0) {
01683 return OSP_OK;
01684 }
01685
01686 if (!results->numdests) {
01687 ast_debug(1, "OSP: No more destination\n");
01688 results->outtimelimit = OSP_DEF_TIMELIMIT;
01689 OSPPTransactionRecordFailure(results->outhandle, reason);
01690 if (results->inhandle != OSP_INVALID_HANDLE) {
01691 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01692 }
01693 return OSP_FAILED;
01694 }
01695
01696 while(results->numdests) {
01697 results->outcallid.len = sizeof(results->outcallid.buf);
01698 tokenlen = sizeof(token);
01699 error = OSPPTransactionGetNextDestination(results->outhandle,
01700 reason,
01701 0,
01702 NULL,
01703 NULL,
01704 &results->outtimelimit,
01705 &results->outcallid.len,
01706 results->outcallid.buf,
01707 sizeof(callednum),
01708 callednum,
01709 sizeof(callingnum),
01710 callingnum,
01711 sizeof(destination),
01712 destination,
01713 0,
01714 NULL,
01715 &tokenlen,
01716 token);
01717 if (error == OSPC_ERR_NO_ERROR) {
01718 results->numdests--;
01719 results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
01720 ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
01721 ast_debug(1, "OSP: calling '%s'\n", callingnum);
01722 ast_debug(1, "OSP: called '%s'\n", callednum);
01723 ast_debug(1, "OSP: destination '%s'\n", destination);
01724 ast_debug(1, "OSP: token size '%d'\n", tokenlen);
01725
01726 if ((res = osp_check_destination(provider, callingnum, callednum, destination, tokenlen, token, &reason, results)) > 0) {
01727 break;
01728 } else if (!results->numdests) {
01729 ast_debug(1, "OSP: No more destination\n");
01730 OSPPTransactionRecordFailure(results->outhandle, reason);
01731 if (results->inhandle != OSP_INVALID_HANDLE) {
01732 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01733 }
01734 res = OSP_FAILED;
01735 break;
01736 }
01737 } else {
01738 ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
01739 results->numdests = 0;
01740 results->outtimelimit = OSP_DEF_TIMELIMIT;
01741 if (results->inhandle != OSP_INVALID_HANDLE) {
01742 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
01743 }
01744 res = OSP_ERROR;
01745 break;
01746 }
01747 }
01748
01749 return res;
01750 }
01751
01752
01753
01754
01755
01756
01757
01758
01759 static int osp_next(
01760 const char* name,
01761 int cause,
01762 struct osp_results* results)
01763 {
01764 int res;
01765 struct osp_provider* provider = NULL;
01766 char calling[OSP_SIZE_NORSTR];
01767 char called[OSP_SIZE_NORSTR];
01768 char dest[OSP_SIZE_NORSTR];
01769 unsigned int tokenlen;
01770 char token[OSP_SIZE_TOKSTR];
01771 OSPEFAILREASON reason;
01772 OSPE_OPERATOR_NAME type;
01773 int error;
01774
01775 if (results == NULL) {
01776 ast_log(LOG_ERROR, "Invalid parameters\n");
01777 res = OSP_ERROR;
01778 }
01779
01780 results->tech[0] = '\0';
01781 results->dest[0] = '\0';
01782 results->calling[0] = '\0';
01783 results->called[0] = '\0';
01784 results->token[0] = '\0';
01785 results->networkid[0] = '\0';
01786 results->nprn[0] = '\0';
01787 results->npcic[0] = '\0';
01788 results->npdi = 0;
01789 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
01790 results->opname[type][0] = '\0';
01791 }
01792 results->outtimelimit = OSP_DEF_TIMELIMIT;
01793
01794 if ((res = osp_get_provider(name, &provider)) <= 0) {
01795 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
01796 return res;
01797 }
01798
01799 if (results->outhandle == OSP_INVALID_HANDLE) {
01800 ast_debug(1, "OSP: Transaction handle undefined\n");
01801 results->numdests = 0;
01802 if (results->inhandle != OSP_INVALID_HANDLE) {
01803 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
01804 }
01805 return OSP_ERROR;
01806 }
01807
01808 reason = asterisk2osp(cause);
01809
01810 if (!results->numdests) {
01811 ast_debug(1, "OSP: No more destination\n");
01812 OSPPTransactionRecordFailure(results->outhandle, reason);
01813 if (results->inhandle != OSP_INVALID_HANDLE) {
01814 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01815 }
01816 return OSP_FAILED;
01817 }
01818
01819 while(results->numdests) {
01820 results->outcallid.len = sizeof(results->outcallid.buf);
01821 tokenlen = sizeof(token);
01822 error = OSPPTransactionGetNextDestination(
01823 results->outhandle,
01824 reason,
01825 0,
01826 NULL,
01827 NULL,
01828 &results->outtimelimit,
01829 &results->outcallid.len,
01830 results->outcallid.buf,
01831 sizeof(called),
01832 called,
01833 sizeof(calling),
01834 calling,
01835 sizeof(dest),
01836 dest,
01837 0,
01838 NULL,
01839 &tokenlen,
01840 token);
01841 if (error == OSPC_ERR_NO_ERROR) {
01842 results->numdests--;
01843 results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
01844 ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
01845 ast_debug(1, "OSP: calling '%s'\n", calling);
01846 ast_debug(1, "OSP: called '%s'\n", called);
01847 ast_debug(1, "OSP: destination '%s'\n", dest);
01848 ast_debug(1, "OSP: token size '%d'\n", tokenlen);
01849
01850 if ((res = osp_check_destination(provider, calling, called, dest, tokenlen, token, &reason, results)) > 0) {
01851 res = OSP_OK;
01852 break;
01853 } else if (!results->numdests) {
01854 ast_debug(1, "OSP: No more destination\n");
01855 OSPPTransactionRecordFailure(results->outhandle, reason);
01856 if (results->inhandle != OSP_INVALID_HANDLE) {
01857 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01858 }
01859 res = OSP_FAILED;
01860 break;
01861 }
01862 } else {
01863 ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
01864 results->token[0] = '\0';
01865 results->numdests = 0;
01866 results->outtimelimit = OSP_DEF_TIMELIMIT;
01867 if (results->inhandle != OSP_INVALID_HANDLE) {
01868 OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
01869 }
01870 res = OSP_ERROR;
01871 break;
01872 }
01873 }
01874
01875 return res;
01876 }
01877
01878
01879
01880
01881
01882
01883 static int osp_get_varint(
01884 const char* vstr)
01885 {
01886 char* tmp;
01887 int value = OSP_DEF_INTSTATS;
01888
01889 if (!ast_strlen_zero(vstr)) {
01890 if ((tmp = strchr(vstr, '=')) != NULL) {
01891 tmp++;
01892 if (sscanf(tmp, "%30d", &value) != 1) {
01893 value = OSP_DEF_INTSTATS;
01894 }
01895 }
01896 }
01897
01898 return value;
01899 }
01900
01901
01902
01903
01904
01905
01906 static float osp_get_varfloat(
01907 const char* vstr)
01908 {
01909 char* tmp;
01910 float value = OSP_DEF_FLOATSTATS;
01911
01912 if (!ast_strlen_zero(vstr)) {
01913 if ((tmp = strchr(vstr, '=')) != NULL) {
01914 tmp++;
01915 if (sscanf(tmp, "%30f", &value) != 1) {
01916 value = OSP_DEF_FLOATSTATS;
01917 }
01918 }
01919 }
01920
01921 return value;
01922 }
01923
01924
01925
01926
01927
01928
01929
01930
01931 static int osp_report_qos(
01932 int trans,
01933 enum osp_callleg leg,
01934 const char* qos)
01935 {
01936 int res = OSP_FAILED;
01937 enum osp_direction dir;
01938 char buffer[OSP_SIZE_NORSTR];
01939 char* tmp;
01940 char* item;
01941 int totalpackets[OSP_DIR_NUMBER];
01942 struct osp_metrics lost[OSP_DIR_NUMBER];
01943 struct osp_metrics jitter[OSP_DIR_NUMBER];
01944 struct osp_metrics rtt;
01945 int value;
01946
01947 if (!ast_strlen_zero(qos)) {
01948 for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
01949 totalpackets[dir] = OSP_DEF_INTSTATS;
01950 }
01951
01952 for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
01953 lost[dir].value = OSP_DEF_INTSTATS;
01954 lost[dir].min = OSP_DEF_FLOATSTATS;
01955 lost[dir].max = OSP_DEF_FLOATSTATS;
01956 lost[dir].avg = OSP_DEF_FLOATSTATS;
01957 lost[dir].sdev = OSP_DEF_FLOATSTATS;
01958 }
01959
01960 for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
01961 jitter[dir].value = OSP_DEF_INTSTATS;
01962 jitter[dir].min = OSP_DEF_FLOATSTATS;
01963 jitter[dir].max = OSP_DEF_FLOATSTATS;
01964 jitter[dir].avg = OSP_DEF_FLOATSTATS;
01965 jitter[dir].sdev = OSP_DEF_FLOATSTATS;
01966 }
01967
01968 rtt.value = OSP_DEF_INTSTATS;
01969 rtt.min = OSP_DEF_FLOATSTATS;
01970 rtt.max = OSP_DEF_FLOATSTATS;
01971 rtt.avg = OSP_DEF_FLOATSTATS;
01972 rtt.sdev = OSP_DEF_FLOATSTATS;
01973
01974 ast_copy_string(buffer, qos, sizeof(buffer));
01975 for (item = strtok_r(buffer, ";", &tmp); item; item = strtok_r(NULL, ";", &tmp)) {
01976 if (!strncasecmp(item, "rxcount", strlen("rxcount"))) {
01977 totalpackets[OSP_DIR_RX] = osp_get_varint(item);
01978 } else if (!strncasecmp(item, "txcount", strlen("txcount"))) {
01979 totalpackets[OSP_DIR_TX] = osp_get_varint(item);
01980 } else if (!strncasecmp(item, "lp", strlen("lp"))) {
01981 lost[OSP_DIR_RX].value = osp_get_varint(item);
01982 } else if (!strncasecmp(item, "minrxlost", strlen("minrxlost"))) {
01983 lost[OSP_DIR_RX].min = osp_get_varfloat(item);
01984 } else if (!strncasecmp(item, "maxrxlost", strlen("maxrxlost"))) {
01985 lost[OSP_DIR_RX].max = osp_get_varfloat(item);
01986 } else if (!strncasecmp(item, "avgrxlost", strlen("avgrxlost"))) {
01987 lost[OSP_DIR_RX].avg = osp_get_varfloat(item);
01988 } else if (!strncasecmp(item, "stdevrxlost", strlen("stdevrxlost"))) {
01989 lost[OSP_DIR_RX].sdev = osp_get_varfloat(item);
01990 } else if (!strncasecmp(item, "rlp", strlen("rlp"))) {
01991 lost[OSP_DIR_TX].value = osp_get_varint(item);
01992 } else if (!strncasecmp(item, "reported_minlost", strlen("reported_minlost"))) {
01993 lost[OSP_DIR_TX].min = osp_get_varfloat(item);
01994 } else if (!strncasecmp(item, "reported_maxlost", strlen("reported_maxlost"))) {
01995 lost[OSP_DIR_TX].max = osp_get_varfloat(item);
01996 } else if (!strncasecmp(item, "reported_avglost", strlen("reported_avglost"))) {
01997 lost[OSP_DIR_TX].avg = osp_get_varfloat(item);
01998 } else if (!strncasecmp(item, "reported_stdevlost", strlen("reported_stdevlost"))) {
01999 lost[OSP_DIR_TX].sdev = osp_get_varfloat(item);
02000 } else if (!strncasecmp(item, "rxjitter", strlen("rxjitter"))) {
02001 jitter[OSP_DIR_RX].value = osp_get_varint(item);
02002 } else if (!strncasecmp(item, "minrxjitter", strlen("minrxjitter"))) {
02003 jitter[OSP_DIR_RX].min = osp_get_varfloat(item);
02004 } else if (!strncasecmp(item, "maxrxjitter", strlen("maxrxjitter"))) {
02005 jitter[OSP_DIR_RX].max = osp_get_varfloat(item);
02006 } else if (!strncasecmp(item, "avgrxjitter", strlen("avgjitter"))) {
02007 jitter[OSP_DIR_RX].avg = osp_get_varfloat(item);
02008 } else if (!strncasecmp(item, "stdevrxjitter", strlen("stdevjitter"))) {
02009 jitter[OSP_DIR_RX].sdev = osp_get_varfloat(item);
02010 } else if (!strncasecmp(item, "txjitter", strlen("txjitter"))) {
02011 jitter[OSP_DIR_TX].value = osp_get_varint(item);
02012 } else if (!strncasecmp(item, "reported_minjitter", strlen("reported_minjitter"))) {
02013 jitter[OSP_DIR_TX].min = osp_get_varfloat(item);
02014 } else if (!strncasecmp(item, "reported_maxjitter", strlen("reported_maxjitter"))) {
02015 jitter[OSP_DIR_TX].max = osp_get_varfloat(item);
02016 } else if (!strncasecmp(item, "reported_avgjitter", strlen("reported_avgjitter"))) {
02017 jitter[OSP_DIR_TX].avg = osp_get_varfloat(item);
02018 } else if (!strncasecmp(item, "reported_stdevjitter", strlen("reported_stdevjitter"))) {
02019 jitter[OSP_DIR_TX].sdev = osp_get_varfloat(item);
02020 } else if (!strncasecmp(item, "rtt", strlen("rtt"))) {
02021 rtt.value = osp_get_varint(item);
02022 } else if (!strncasecmp(item, "minrtt", strlen("minrtt"))) {
02023 rtt.min = osp_get_varfloat(item);
02024 } else if (!strncasecmp(item, "maxrtt", strlen("maxrtt"))) {
02025 rtt.max = osp_get_varfloat(item);
02026 } else if (!strncasecmp(item, "avgrtt", strlen("avgrtt"))) {
02027 rtt.avg = osp_get_varfloat(item);
02028 } else if (!strncasecmp(item, "stdevrtt", strlen("stdevrtt"))) {
02029 rtt.sdev = osp_get_varfloat(item);
02030 }
02031 }
02032
02033 ast_debug(1, "OSP: call leg '%d'\n", leg);
02034 ast_debug(1, "OSP: rxcount '%d'\n", totalpackets[OSP_DIR_RX]);
02035 ast_debug(1, "OSP: txcount '%d'\n", totalpackets[OSP_DIR_TX]);
02036 ast_debug(1, "OSP: lp '%d'\n",lost[OSP_DIR_RX].value);
02037 ast_debug(1, "OSP: minrxlost '%f'\n", lost[OSP_DIR_RX].min);
02038 ast_debug(1, "OSP: maxrxlost '%f'\n", lost[OSP_DIR_RX].max);
02039 ast_debug(1, "OSP: avgrxlost '%f'\n", lost[OSP_DIR_RX].avg);
02040 ast_debug(1, "OSP: stdevrxlost '%f'\n", lost[OSP_DIR_RX].sdev);
02041 ast_debug(1, "OSP: rlp '%d'\n", lost[OSP_DIR_TX].value);
02042 ast_debug(1, "OSP: reported_minlost '%f'\n", lost[OSP_DIR_TX].min);
02043 ast_debug(1, "OSP: reported_maxlost '%f'\n", lost[OSP_DIR_TX].max);
02044 ast_debug(1, "OSP: reported_avglost '%f'\n", lost[OSP_DIR_TX].avg);
02045 ast_debug(1, "OSP: reported_stdevlost '%f'\n", lost[OSP_DIR_TX].sdev);
02046 ast_debug(1, "OSP: rxjitter '%d'\n", jitter[OSP_DIR_RX].value);
02047 ast_debug(1, "OSP: minrxjitter '%f'\n", jitter[OSP_DIR_RX].min);
02048 ast_debug(1, "OSP: maxrxjitter '%f'\n", jitter[OSP_DIR_RX].max);
02049 ast_debug(1, "OSP: avgrxjitter '%f'\n", jitter[OSP_DIR_RX].avg);
02050 ast_debug(1, "OSP: stdevrxjitter '%f'\n", jitter[OSP_DIR_RX].sdev);
02051 ast_debug(1, "OSP: txjitter '%d'\n", jitter[OSP_DIR_TX].value);
02052 ast_debug(1, "OSP: reported_minjitter '%f'\n", jitter[OSP_DIR_TX].min);
02053 ast_debug(1, "OSP: reported_maxjitter '%f'\n", jitter[OSP_DIR_TX].max);
02054 ast_debug(1, "OSP: reported_avgjitter '%f'\n", jitter[OSP_DIR_TX].avg);
02055 ast_debug(1, "OSP: reported_stdevjitter '%f'\n", jitter[OSP_DIR_TX].sdev);
02056 ast_debug(1, "OSP: rtt '%d'\n", rtt.value);
02057 ast_debug(1, "OSP: minrtt '%f'\n", rtt.min);
02058 ast_debug(1, "OSP: maxrtt '%f'\n", rtt.max);
02059 ast_debug(1, "OSP: avgrtt '%f'\n", rtt.avg);
02060 ast_debug(1, "OSP: stdevrtt '%f'\n", rtt.sdev);
02061
02062 if (leg == OSP_CALL_INBOUND) {
02063 OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_DOWNSTREAM, totalpackets[OSP_DIR_RX]);
02064 OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM, totalpackets[OSP_DIR_TX]);
02065 if (lost[OSP_DIR_RX].value >= 0) {
02066 value = lost[OSP_DIR_RX].value;
02067 } else {
02068 value = (int)lost[OSP_DIR_RX].avg;
02069 }
02070 OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_DOWNSTREAM, value, OSP_DEF_INTSTATS);
02071 if (lost[OSP_DIR_TX].value >= 0) {
02072 value = lost[OSP_DIR_TX].value;
02073 } else {
02074 value = (int)lost[OSP_DIR_TX].avg;
02075 }
02076 OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM, value, OSP_DEF_INTSTATS);
02077 if (jitter[OSP_DIR_RX].value >= 0) {
02078 value = jitter[OSP_DIR_RX].value;
02079 } else {
02080 value = (int)jitter[OSP_DIR_RX].avg;
02081 }
02082 OSPPTransactionSetJitter(trans,
02083 OSPC_SMETRIC_RTP,
02084 OSPC_SFLOW_DOWNSTREAM,
02085 OSP_DEF_INTSTATS,
02086 (int)jitter[OSP_DIR_RX].min,
02087 (int)jitter[OSP_DIR_RX].max,
02088 value, jitter[OSP_DIR_RX].sdev);
02089 if (jitter[OSP_DIR_TX].value >= 0) {
02090 value = jitter[OSP_DIR_TX].value;
02091 } else {
02092 value = (int)jitter[OSP_DIR_TX].avg;
02093 }
02094 OSPPTransactionSetJitter(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_UPSTREAM,
02095 OSP_DEF_INTSTATS, (int)jitter[OSP_DIR_TX].min, (int)jitter[OSP_DIR_TX].max, value, jitter[OSP_DIR_TX].sdev);
02096 } else {
02097 OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_UPSTREAM, totalpackets[OSP_DIR_RX]);
02098 OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_DOWNSTREAM, totalpackets[OSP_DIR_TX]);
02099 OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SFLOW_UPSTREAM, lost[OSP_DIR_RX].value, OSP_DEF_INTSTATS);
02100 OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SFLOW_DOWNSTREAM, lost[OSP_DIR_TX].value, OSP_DEF_INTSTATS);
02101 if (jitter[OSP_DIR_RX].value >= 0) {
02102 value = jitter[OSP_DIR_RX].value;
02103 } else {
02104 value = (int)jitter[OSP_DIR_RX].avg;
02105 }
02106 OSPPTransactionSetJitter(trans,
02107 OSPC_SMETRIC_RTP,
02108 OSPC_SFLOW_UPSTREAM,
02109 OSP_DEF_INTSTATS,
02110 (int)jitter[OSP_DIR_RX].min,
02111 (int)jitter[OSP_DIR_RX].max,
02112 value,
02113 jitter[OSP_DIR_RX].sdev);
02114 if (jitter[OSP_DIR_TX].value >= 0) {
02115 value = jitter[OSP_DIR_TX].value;
02116 } else {
02117 value = (int)jitter[OSP_DIR_TX].avg;
02118 }
02119 OSPPTransactionSetJitter(trans,
02120 OSPC_SMETRIC_RTCP,
02121 OSPC_SFLOW_DOWNSTREAM,
02122 OSP_DEF_INTSTATS,
02123 (int)jitter[OSP_DIR_TX].min,
02124 (int)jitter[OSP_DIR_TX].max,
02125 value,
02126 jitter[OSP_DIR_TX].sdev);
02127 }
02128 if (rtt.value >= 0) {
02129 value = rtt.value;
02130 } else {
02131 value = (int)rtt.avg;
02132 }
02133 OSPPTransactionSetRoundTripDelay(trans, OSP_DEF_INTSTATS, (int)rtt.min, (int)rtt.max, value, rtt.sdev);
02134
02135 res = OSP_OK;
02136 }
02137
02138 return res;
02139 }
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154 static int osp_finish(
02155 int trans,
02156 int recorded,
02157 int cause,
02158 time_t start,
02159 time_t connect,
02160 time_t end,
02161 unsigned int release,
02162 const char* inqos,
02163 const char* outqos)
02164 {
02165 int res;
02166 OSPEFAILREASON reason;
02167 time_t alert = 0;
02168 unsigned isPddInfoPresent = 0;
02169 unsigned pdd = 0;
02170 unsigned int dummy = 0;
02171 int error;
02172
02173 if (trans == OSP_INVALID_HANDLE) {
02174 return OSP_FAILED;
02175 }
02176
02177 if (!recorded) {
02178 reason = asterisk2osp(cause);
02179 OSPPTransactionRecordFailure(trans, reason);
02180 }
02181
02182 osp_report_qos(trans, OSP_CALL_INBOUND, inqos);
02183 osp_report_qos(trans, OSP_CALL_OUTBOUND, outqos);
02184
02185 error = OSPPTransactionReportUsage(trans,
02186 difftime(end, connect),
02187 start,
02188 end,
02189 alert,
02190 connect,
02191 isPddInfoPresent,
02192 pdd,
02193 release,
02194 NULL,
02195 OSP_DEF_INTSTATS,
02196 OSP_DEF_INTSTATS,
02197 OSP_DEF_INTSTATS,
02198 OSP_DEF_INTSTATS,
02199 &dummy,
02200 NULL);
02201 if (error == OSPC_ERR_NO_ERROR) {
02202 ast_debug(1, "OSP: Usage reported\n");
02203 res = OSP_OK;
02204 } else {
02205 ast_debug(1, "OSP: Unable to report usage, error '%d'\n", error);
02206 res = OSP_ERROR;
02207 }
02208 OSPPTransactionDelete(trans);
02209
02210 return res;
02211 }
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221 static int ospauth_exec(
02222 struct ast_channel *chan,
02223 const char *data)
02224 {
02225 int res;
02226 const char* provider = OSP_DEF_PROVIDER;
02227 struct varshead* headp;
02228 struct ast_var_t* current;
02229 const char* source = "";
02230 const char* token = "";
02231 int handle;
02232 unsigned int timelimit;
02233 char buffer[OSP_SIZE_INTSTR];
02234 const char* status;
02235 char* tmp;
02236
02237 AST_DECLARE_APP_ARGS(args,
02238 AST_APP_ARG(provider);
02239 AST_APP_ARG(options);
02240 );
02241
02242 if (!(tmp = ast_strdupa(data))) {
02243 ast_log(LOG_ERROR, "Out of memory\n");
02244 return OSP_AST_ERROR;
02245 }
02246
02247 AST_STANDARD_APP_ARGS(args, tmp);
02248
02249 if (!ast_strlen_zero(args.provider)) {
02250 provider = args.provider;
02251 }
02252 ast_debug(1, "OSPAuth: provider '%s'\n", provider);
02253
02254 headp = &chan->varshead;
02255 AST_LIST_TRAVERSE(headp, current, entries) {
02256 if (!strcasecmp(ast_var_name(current), "OSPINPEERIP")) {
02257 source = ast_var_value(current);
02258 } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
02259 token = ast_var_value(current);
02260 }
02261 }
02262
02263 ast_debug(1, "OSPAuth: source '%s'\n", source);
02264 ast_debug(1, "OSPAuth: token size '%zd'\n", strlen(token));
02265
02266 res = osp_auth(provider, &handle, source,
02267 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
02268 chan->exten, token, &timelimit);
02269 if (res > 0) {
02270 status = AST_OSP_SUCCESS;
02271 } else {
02272 timelimit = OSP_DEF_TIMELIMIT;
02273 if (!res) {
02274 status = AST_OSP_FAILED;
02275 } else {
02276 status = AST_OSP_ERROR;
02277 }
02278 }
02279
02280 snprintf(buffer, sizeof(buffer), "%d", handle);
02281 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
02282 ast_debug(1, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
02283 snprintf(buffer, sizeof(buffer), "%d", timelimit);
02284 pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
02285 ast_debug(1, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
02286 pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
02287 ast_debug(1, "OSPAuth: %s\n", status);
02288
02289 if(res != OSP_OK) {
02290 res = OSP_AST_ERROR;
02291 } else {
02292 res = OSP_AST_OK;
02293 }
02294
02295 return res;
02296 }
02297
02298
02299
02300
02301
02302
02303
02304 static int osplookup_exec(
02305 struct ast_channel* chan,
02306 const char * data)
02307 {
02308 int res, cres;
02309 const char* provider = OSP_DEF_PROVIDER;
02310 unsigned int callidtypes = OSP_CALLID_UNDEF;
02311 struct varshead* headp;
02312 struct ast_var_t* current;
02313 const char* actualsrc = "";
02314 const char* srcdev = "";
02315 const char* snetid = "";
02316 struct osp_npdata np;
02317 OSPE_OPERATOR_NAME type;
02318 struct osp_diversion div;
02319 unsigned int i;
02320 const char* cinfo[OSP_MAX_CUSTOMINFO] = { NULL };
02321 char buffer[OSP_SIZE_TOKSTR];
02322 struct osp_results results;
02323 const char* status;
02324 char* tmp;
02325
02326 AST_DECLARE_APP_ARGS(args,
02327 AST_APP_ARG(exten);
02328 AST_APP_ARG(provider);
02329 AST_APP_ARG(options);
02330 );
02331
02332 if (ast_strlen_zero(data)) {
02333 ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[,provider[,options]])\n");
02334 return OSP_AST_ERROR;
02335 }
02336
02337 if (!(tmp = ast_strdupa(data))) {
02338 ast_log(LOG_ERROR, "Out of memory\n");
02339 return OSP_AST_ERROR;
02340 }
02341
02342 AST_STANDARD_APP_ARGS(args, tmp);
02343
02344 ast_debug(1, "OSPLookup: exten '%s'\n", args.exten);
02345
02346 if (!ast_strlen_zero(args.provider)) {
02347 provider = args.provider;
02348 }
02349 ast_debug(1, "OSPlookup: provider '%s'\n", provider);
02350
02351 if (args.options) {
02352 if (strchr(args.options, 'h')) {
02353 callidtypes |= OSP_CALLID_H323;
02354 }
02355 if (strchr(args.options, 's')) {
02356 callidtypes |= OSP_CALLID_SIP;
02357 }
02358 if (strchr(args.options, 'i')) {
02359 callidtypes |= OSP_CALLID_IAX;
02360 }
02361 }
02362 ast_debug(1, "OSPLookup: call id types '%d'\n", callidtypes);
02363
02364 results.inhandle = OSP_INVALID_HANDLE;
02365 results.intimelimit = OSP_DEF_TIMELIMIT;
02366 results.dest[0] = '\0';
02367
02368 np.rn = "";
02369 np.cic = "";
02370 np.npdi = 0;
02371 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
02372 np.opname[type] = "";
02373 }
02374
02375 div.user = "";
02376 div.host = "";
02377
02378 headp = &chan->varshead;
02379 AST_LIST_TRAVERSE(headp, current, entries) {
02380 if (!strcasecmp(ast_var_name(current), "OSPINACTUALSRC")) {
02381 actualsrc = ast_var_value(current);
02382 } else if (!strcasecmp(ast_var_name(current), "OSPINPEERIP")) {
02383 srcdev = ast_var_value(current);
02384 } else if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
02385 if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
02386 results.inhandle = OSP_INVALID_HANDLE;
02387 }
02388 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
02389 if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
02390 results.intimelimit = OSP_DEF_TIMELIMIT;
02391 }
02392 } else if (!strcasecmp(ast_var_name(current), "OSPINNETWORKID")) {
02393 snetid = ast_var_value(current);
02394 } else if (!strcasecmp(ast_var_name(current), "OSPINNPRN")) {
02395 np.rn = ast_var_value(current);
02396 } else if (!strcasecmp(ast_var_name(current), "OSPINNPCIC")) {
02397 np.cic = ast_var_value(current);
02398 } else if (!strcasecmp(ast_var_name(current), "OSPINNPDI")) {
02399 if (ast_true(ast_var_value(current))) {
02400 np.npdi = 1;
02401 }
02402 } else if (!strcasecmp(ast_var_name(current), "OSPINSPID")) {
02403 np.opname[OSPC_OPNAME_SPID] = ast_var_value(current);
02404 } else if (!strcasecmp(ast_var_name(current), "OSPINOCN")) {
02405 np.opname[OSPC_OPNAME_OCN] = ast_var_value(current);
02406 } else if (!strcasecmp(ast_var_name(current), "OSPINSPN")) {
02407 np.opname[OSPC_OPNAME_SPN] = ast_var_value(current);
02408 } else if (!strcasecmp(ast_var_name(current), "OSPINALTSPN")) {
02409 np.opname[OSPC_OPNAME_ALTSPN] = ast_var_value(current);
02410 } else if (!strcasecmp(ast_var_name(current), "OSPINMCC")) {
02411 np.opname[OSPC_OPNAME_MCC] = ast_var_value(current);
02412 } else if (!strcasecmp(ast_var_name(current), "OSPINMNC")) {
02413 np.opname[OSPC_OPNAME_MNC] = ast_var_value(current);
02414 } else if (!strcasecmp(ast_var_name(current), "OSPINTOHOST")) {
02415 ast_copy_string(results.dest, ast_var_value(current), sizeof(results.dest));
02416 } else if (!strcasecmp(ast_var_name(current), "OSPINDIVUSER")) {
02417 div.user = ast_var_value(current);
02418 } else if (!strcasecmp(ast_var_name(current), "OSPINDIVHOST")) {
02419 div.host = ast_var_value(current);
02420 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO1")) {
02421 cinfo[0] = ast_var_value(current);
02422 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO2")) {
02423 cinfo[1] = ast_var_value(current);
02424 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO3")) {
02425 cinfo[2] = ast_var_value(current);
02426 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO4")) {
02427 cinfo[3] = ast_var_value(current);
02428 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO5")) {
02429 cinfo[4] = ast_var_value(current);
02430 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO6")) {
02431 cinfo[5] = ast_var_value(current);
02432 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO7")) {
02433 cinfo[6] = ast_var_value(current);
02434 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO8")) {
02435 cinfo[7] = ast_var_value(current);
02436 }
02437 }
02438 ast_debug(1, "OSPLookup: actual source device '%s'\n", actualsrc);
02439 ast_debug(1, "OSPLookup: source device '%s'\n", srcdev);
02440 ast_debug(1, "OSPLookup: OSPINHANDLE '%d'\n", results.inhandle);
02441 ast_debug(1, "OSPLookup: OSPINTIMELIMIT '%d'\n", results.intimelimit);
02442 ast_debug(1, "OSPLookup: OSPINNETWORKID '%s'\n", snetid);
02443 ast_debug(1, "OSPLookup: OSPINNPRN '%s'\n", np.rn);
02444 ast_debug(1, "OSPLookup: OSPINNPCIC '%s'\n", np.cic);
02445 ast_debug(1, "OSPLookup: OSPINNPDI '%d'\n", np.npdi);
02446 ast_debug(1, "OSPLookup: OSPINSPID '%s'\n", np.opname[OSPC_OPNAME_SPID]);
02447 ast_debug(1, "OSPLookup: OSPINOCN '%s'\n", np.opname[OSPC_OPNAME_OCN]);
02448 ast_debug(1, "OSPLookup: OSPINSPN '%s'\n", np.opname[OSPC_OPNAME_SPN]);
02449 ast_debug(1, "OSPLookup: OSPINALTSPN '%s'\n", np.opname[OSPC_OPNAME_ALTSPN]);
02450 ast_debug(1, "OSPLookup: OSPINMCC '%s'\n", np.opname[OSPC_OPNAME_MCC]);
02451 ast_debug(1, "OSPLookup: OSPINMNC '%s'\n", np.opname[OSPC_OPNAME_MNC]);
02452 ast_debug(1, "OSPLookup: OSPINTOHOST '%s'\n", results.dest);
02453 ast_debug(1, "OSPLookup: OSPINDIVUSER '%s'\n", div.user);
02454 ast_debug(1, "OSPLookup: OSPINDIVHOST'%s'\n", div.host);
02455 for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
02456 if (!ast_strlen_zero(cinfo[i])) {
02457 ast_debug(1, "OSPLookup: OSPINCUSTOMINFO%d '%s'\n", i, cinfo[i]);
02458 }
02459 }
02460
02461 if ((cres = ast_autoservice_start(chan)) < 0) {
02462 return OSP_AST_ERROR;
02463 }
02464
02465 res = osp_lookup(provider, callidtypes, actualsrc, srcdev,
02466 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
02467 args.exten, snetid, &np, &div, cinfo, &results);
02468 if (res > 0) {
02469 status = AST_OSP_SUCCESS;
02470 } else {
02471 results.tech[0] = '\0';
02472 results.dest[0] = '\0';
02473 results.calling[0] = '\0';
02474 results.called[0] = '\0';
02475 results.token[0] = '\0';
02476 results.networkid[0] = '\0';
02477 results.nprn[0] = '\0';
02478 results.npcic[0] = '\0';
02479 results.npdi = 0;
02480 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
02481 results.opname[type][0] = '\0';
02482 }
02483 results.numdests = 0;
02484 results.outtimelimit = OSP_DEF_TIMELIMIT;
02485 results.outcallid.buf[0] = '\0';
02486 results.outcallid.len = 0;
02487 if (!res) {
02488 status = AST_OSP_FAILED;
02489 } else {
02490 status = AST_OSP_ERROR;
02491 }
02492 }
02493
02494 snprintf(buffer, sizeof(buffer), "%d", results.outhandle);
02495 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
02496 ast_debug(1, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
02497 pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.tech);
02498 ast_debug(1, "OSPLookup: OSPOUTTECH '%s'\n", results.tech);
02499 pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
02500 ast_debug(1, "OSPLookup: OSPDESTINATION '%s'\n", results.dest);
02501 pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
02502 ast_debug(1, "OSPLookup: OSPOUTCALLING '%s'\n", results.calling);
02503 pbx_builtin_setvar_helper(chan, "OSPOUTCALLED", results.called);
02504 ast_debug(1, "OSPLookup: OSPOUTCALLED '%s'\n", results.called);
02505 pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", results.networkid);
02506 ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", results.networkid);
02507 pbx_builtin_setvar_helper(chan, "OSPOUTNPRN", results.nprn);
02508 ast_debug(1, "OSPLookup: OSPOUTNPRN '%s'\n", results.nprn);
02509 pbx_builtin_setvar_helper(chan, "OSPOUTNPCIC", results.npcic);
02510 ast_debug(1, "OSPLookup: OSPOUTNPCIC '%s'\n", results.npcic);
02511 snprintf(buffer, sizeof(buffer), "%d", results.npdi);
02512 pbx_builtin_setvar_helper(chan, "OSPOUTNPDI", buffer);
02513 ast_debug(1, "OSPLookup: OSPOUTNPDI'%s'\n", buffer);
02514 pbx_builtin_setvar_helper(chan, "OSPOUTSPID", results.opname[OSPC_OPNAME_SPID]);
02515 ast_debug(1, "OSPLookup: OSPOUTSPID '%s'\n", results.opname[OSPC_OPNAME_SPID]);
02516 pbx_builtin_setvar_helper(chan, "OSPOUTOCN", results.opname[OSPC_OPNAME_OCN]);
02517 ast_debug(1, "OSPLookup: OSPOUTOCN '%s'\n", results.opname[OSPC_OPNAME_OCN]);
02518 pbx_builtin_setvar_helper(chan, "OSPOUTSPN", results.opname[OSPC_OPNAME_SPN]);
02519 ast_debug(1, "OSPLookup: OSPOUTSPN '%s'\n", results.opname[OSPC_OPNAME_SPN]);
02520 pbx_builtin_setvar_helper(chan, "OSPOUTALTSPN", results.opname[OSPC_OPNAME_ALTSPN]);
02521 ast_debug(1, "OSPLookup: OSPOUTALTSPN '%s'\n", results.opname[OSPC_OPNAME_ALTSPN]);
02522 pbx_builtin_setvar_helper(chan, "OSPOUTMCC", results.opname[OSPC_OPNAME_MCC]);
02523 ast_debug(1, "OSPLookup: OSPOUTMCC '%s'\n", results.opname[OSPC_OPNAME_MCC]);
02524 pbx_builtin_setvar_helper(chan, "OSPOUTMNC", results.opname[OSPC_OPNAME_MNC]);
02525 ast_debug(1, "OSPLookup: OSPOUTMNC '%s'\n", results.opname[OSPC_OPNAME_MNC]);
02526 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", results.token);
02527 ast_debug(1, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(results.token));
02528 snprintf(buffer, sizeof(buffer), "%d", results.numdests);
02529 pbx_builtin_setvar_helper(chan, "OSPDESTREMAILS", buffer);
02530 ast_debug(1, "OSPLookup: OSPDESTREMAILS '%s'\n", buffer);
02531 snprintf(buffer, sizeof(buffer), "%d", results.outtimelimit);
02532 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
02533 ast_debug(1, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
02534 snprintf(buffer, sizeof(buffer), "%d", callidtypes);
02535 pbx_builtin_setvar_helper(chan, "OSPOUTCALLIDTYPES", buffer);
02536 ast_debug(1, "OSPLookup: OSPOUTCALLIDTYPES '%s'\n", buffer);
02537 pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
02538 ast_debug(1, "OSPLookup: %s\n", status);
02539
02540 if (!strcasecmp(results.tech, OSP_TECH_SIP)) {
02541 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
02542 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02543 if (!ast_strlen_zero(results.token)) {
02544 snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
02545 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
02546 ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
02547 }
02548 } else if (!strcasecmp(results.tech, OSP_TECH_H323)) {
02549 if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
02550 osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
02551 } else {
02552 buffer[0] = '\0';
02553 }
02554 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
02555 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
02556 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02557 } else if (!strcasecmp(results.tech, OSP_TECH_IAX)) {
02558 snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.tech, results.dest, results.called);
02559 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02560 } else if (!strcasecmp(results.tech, OSP_TECH_SKYPE)) {
02561 snprintf(buffer, sizeof(buffer), "%s/%s", results.tech, results.called);
02562 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02563 }
02564
02565 if ((cres = ast_autoservice_stop(chan)) < 0) {
02566 return OSP_AST_ERROR;
02567 }
02568
02569 if(res != OSP_OK) {
02570 res = OSP_AST_ERROR;
02571 } else {
02572 res = OSP_AST_OK;
02573 }
02574
02575 return res;
02576 }
02577
02578
02579
02580
02581
02582
02583
02584 static int ospnext_exec(
02585 struct ast_channel* chan,
02586 const char * data)
02587 {
02588 int res;
02589 const char* provider = OSP_DEF_PROVIDER;
02590 int cause = 0;
02591 struct varshead* headp;
02592 struct ast_var_t* current;
02593 struct osp_results results;
02594 OSPE_OPERATOR_NAME type;
02595 char buffer[OSP_SIZE_TOKSTR];
02596 unsigned int callidtypes = OSP_CALLID_UNDEF;
02597 const char* status;
02598 char* tmp;
02599
02600 AST_DECLARE_APP_ARGS(args,
02601 AST_APP_ARG(cause);
02602 AST_APP_ARG(provider);
02603 AST_APP_ARG(options);
02604 );
02605
02606 if (ast_strlen_zero(data)) {
02607 ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[,provider[,options]])\n");
02608 return OSP_AST_ERROR;
02609 }
02610
02611 if (!(tmp = ast_strdupa(data))) {
02612 ast_log(LOG_ERROR, "Out of memory\n");
02613 return OSP_AST_ERROR;
02614 }
02615
02616 AST_STANDARD_APP_ARGS(args, tmp);
02617
02618 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
02619 cause = 0;
02620 }
02621 ast_debug(1, "OSPNext: cause '%d'\n", cause);
02622
02623 if (!ast_strlen_zero(args.provider)) {
02624 provider = args.provider;
02625 }
02626 ast_debug(1, "OSPlookup: provider '%s'\n", provider);
02627
02628 results.inhandle = OSP_INVALID_HANDLE;
02629 results.outhandle = OSP_INVALID_HANDLE;
02630 results.intimelimit = OSP_DEF_TIMELIMIT;
02631 results.numdests = 0;
02632
02633 headp = &chan->varshead;
02634 AST_LIST_TRAVERSE(headp, current, entries) {
02635 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
02636 if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
02637 results.inhandle = OSP_INVALID_HANDLE;
02638 }
02639 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
02640 if (sscanf(ast_var_value(current), "%30d", &results.outhandle) != 1) {
02641 results.outhandle = OSP_INVALID_HANDLE;
02642 }
02643 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
02644 if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
02645 results.intimelimit = OSP_DEF_TIMELIMIT;
02646 }
02647 } else if (!strcasecmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) {
02648 if (sscanf(ast_var_value(current), "%30d", &callidtypes) != 1) {
02649 callidtypes = OSP_CALLID_UNDEF;
02650 }
02651 } else if (!strcasecmp(ast_var_name(current), "OSPDESTREMAILS")) {
02652 if (sscanf(ast_var_value(current), "%30d", &results.numdests) != 1) {
02653 results.numdests = 0;
02654 }
02655 }
02656 }
02657 ast_debug(1, "OSPNext: OSPINHANDLE '%d'\n", results.inhandle);
02658 ast_debug(1, "OSPNext: OSPOUTHANDLE '%d'\n", results.outhandle);
02659 ast_debug(1, "OSPNext: OSPINTIMELIMIT '%d'\n", results.intimelimit);
02660 ast_debug(1, "OSPNext: OSPOUTCALLIDTYPES '%d'\n", callidtypes);
02661 ast_debug(1, "OSPNext: OSPDESTREMAILS '%d'\n", results.numdests);
02662
02663 if ((res = osp_next(provider, cause, &results)) > 0) {
02664 status = AST_OSP_SUCCESS;
02665 } else {
02666 results.tech[0] = '\0';
02667 results.dest[0] = '\0';
02668 results.calling[0] = '\0';
02669 results.called[0] = '\0';
02670 results.token[0] = '\0';
02671 results.networkid[0] = '\0';
02672 results.nprn[0] = '\0';
02673 results.npcic[0] = '\0';
02674 results.npdi = 0;
02675 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
02676 results.opname[type][0] = '\0';
02677 }
02678 results.numdests = 0;
02679 results.outtimelimit = OSP_DEF_TIMELIMIT;
02680 results.outcallid.buf[0] = '\0';
02681 results.outcallid.len = 0;
02682 if (!res) {
02683 status = AST_OSP_FAILED;
02684 } else {
02685 status = AST_OSP_ERROR;
02686 }
02687 }
02688
02689 pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.tech);
02690 ast_debug(1, "OSPNext: OSPOUTTECH '%s'\n", results.tech);
02691 pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
02692 ast_debug(1, "OSPNext: OSPDESTINATION '%s'\n", results.dest);
02693 pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
02694 ast_debug(1, "OSPNext: OSPOUTCALLING '%s'\n", results.calling);
02695 pbx_builtin_setvar_helper(chan, "OSPOUTCALLED", results.called);
02696 ast_debug(1, "OSPNext: OSPOUTCALLED'%s'\n", results.called);
02697 pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", results.networkid);
02698 ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", results.networkid);
02699 pbx_builtin_setvar_helper(chan, "OSPOUTNPRN", results.nprn);
02700 ast_debug(1, "OSPLookup: OSPOUTNPRN '%s'\n", results.nprn);
02701 pbx_builtin_setvar_helper(chan, "OSPOUTNPCIC", results.npcic);
02702 ast_debug(1, "OSPLookup: OSPOUTNPCIC '%s'\n", results.npcic);
02703 snprintf(buffer, sizeof(buffer), "%d", results.npdi);
02704 pbx_builtin_setvar_helper(chan, "OSPOUTNPDI", buffer);
02705 ast_debug(1, "OSPLookup: OSPOUTNPDI'%s'\n", buffer);
02706 pbx_builtin_setvar_helper(chan, "OSPOUTSPID", results.opname[OSPC_OPNAME_SPID]);
02707 ast_debug(1, "OSPLookup: OSPOUTSPID '%s'\n", results.opname[OSPC_OPNAME_SPID]);
02708 pbx_builtin_setvar_helper(chan, "OSPOUTOCN", results.opname[OSPC_OPNAME_OCN]);
02709 ast_debug(1, "OSPLookup: OSPOUTOCN '%s'\n", results.opname[OSPC_OPNAME_OCN]);
02710 pbx_builtin_setvar_helper(chan, "OSPOUTSPN", results.opname[OSPC_OPNAME_SPN]);
02711 ast_debug(1, "OSPLookup: OSPOUTSPN '%s'\n", results.opname[OSPC_OPNAME_SPN]);
02712 pbx_builtin_setvar_helper(chan, "OSPOUTALTSPN", results.opname[OSPC_OPNAME_ALTSPN]);
02713 ast_debug(1, "OSPLookup: OSPOUTALTSPN '%s'\n", results.opname[OSPC_OPNAME_ALTSPN]);
02714 pbx_builtin_setvar_helper(chan, "OSPOUTMCC", results.opname[OSPC_OPNAME_MCC]);
02715 ast_debug(1, "OSPLookup: OSPOUTMCC '%s'\n", results.opname[OSPC_OPNAME_MCC]);
02716 pbx_builtin_setvar_helper(chan, "OSPOUTMNC", results.opname[OSPC_OPNAME_MNC]);
02717 ast_debug(1, "OSPLookup: OSPOUTMNC '%s'\n", results.opname[OSPC_OPNAME_MNC]);
02718 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", results.token);
02719 ast_debug(1, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(results.token));
02720 snprintf(buffer, sizeof(buffer), "%d", results.numdests);
02721 pbx_builtin_setvar_helper(chan, "OSPDESTREMAILS", buffer);
02722 ast_debug(1, "OSPNext: OSPDESTREMAILS '%s'\n", buffer);
02723 snprintf(buffer, sizeof(buffer), "%d", results.outtimelimit);
02724 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
02725 ast_debug(1, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
02726 pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
02727 ast_debug(1, "OSPNext: %s\n", status);
02728
02729 if (!strcasecmp(results.tech, OSP_TECH_SIP)) {
02730 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
02731 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02732 if (!ast_strlen_zero(results.token)) {
02733 snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
02734 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
02735 ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
02736 }
02737 } else if (!strcasecmp(results.tech, OSP_TECH_H323)) {
02738 if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
02739 osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
02740 } else {
02741 buffer[0] = '\0';
02742 }
02743 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
02744 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
02745 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02746 } else if (!strcasecmp(results.tech, OSP_TECH_IAX)) {
02747 snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.tech, results.dest, results.called);
02748 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02749 } else if (!strcasecmp(results.tech, OSP_TECH_SKYPE)) {
02750 snprintf(buffer, sizeof(buffer), "%s/%s", results.tech, results.called);
02751 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02752 }
02753
02754 if(res != OSP_OK) {
02755 res = OSP_AST_ERROR;
02756 } else {
02757 res = OSP_AST_OK;
02758 }
02759
02760 return res;
02761 }
02762
02763
02764
02765
02766
02767
02768
02769 static int ospfinished_exec(
02770 struct ast_channel* chan,
02771 const char * data)
02772 {
02773 int res = OSP_OK;
02774 int cause = 0;
02775 struct varshead* headp;
02776 struct ast_var_t* current;
02777 int inhandle = OSP_INVALID_HANDLE;
02778 int outhandle = OSP_INVALID_HANDLE;
02779 int recorded = 0;
02780 time_t start, connect, end;
02781 unsigned int release;
02782 char buffer[OSP_SIZE_INTSTR];
02783 char inqos[OSP_SIZE_QOSSTR] = { 0 };
02784 char outqos[OSP_SIZE_QOSSTR] = { 0 };
02785 const char* status;
02786 char* tmp;
02787
02788 AST_DECLARE_APP_ARGS(args,
02789 AST_APP_ARG(cause);
02790 AST_APP_ARG(options);
02791 );
02792
02793 if (!(tmp = ast_strdupa(data))) {
02794 ast_log(LOG_ERROR, "Out of memory\n");
02795 return OSP_AST_ERROR;
02796 }
02797
02798 AST_STANDARD_APP_ARGS(args, tmp);
02799
02800 headp = &chan->varshead;
02801 AST_LIST_TRAVERSE(headp, current, entries) {
02802 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
02803 if (sscanf(ast_var_value(current), "%30d", &inhandle) != 1) {
02804 inhandle = OSP_INVALID_HANDLE;
02805 }
02806 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
02807 if (sscanf(ast_var_value(current), "%30d", &outhandle) != 1) {
02808 outhandle = OSP_INVALID_HANDLE;
02809 }
02810 } else if (!recorded &&
02811 (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") ||
02812 !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") ||
02813 !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS")))
02814 {
02815 if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) {
02816 recorded = 1;
02817 }
02818 } else if (!strcasecmp(ast_var_name(current), "OSPINAUDIOQOS")) {
02819 ast_copy_string(inqos, ast_var_value(current), sizeof(inqos));
02820 } else if (!strcasecmp(ast_var_name(current), "OSPOUTAUDIOQOS")) {
02821 ast_copy_string(outqos, ast_var_value(current), sizeof(outqos));
02822 }
02823 }
02824 ast_debug(1, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
02825 ast_debug(1, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
02826 ast_debug(1, "OSPFinish: recorded '%d'\n", recorded);
02827 ast_debug(1, "OSPFinish: OSPINAUDIOQOS '%s'\n", inqos);
02828 ast_debug(1, "OSPFinish: OSPOUTAUDIOQOS '%s'\n", outqos);
02829
02830 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
02831 cause = 0;
02832 }
02833 ast_debug(1, "OSPFinish: cause '%d'\n", cause);
02834
02835 if (chan->cdr) {
02836 start = chan->cdr->start.tv_sec;
02837 connect = chan->cdr->answer.tv_sec;
02838 if (connect) {
02839 end = time(NULL);
02840 } else {
02841 end = connect;
02842 }
02843 } else {
02844 start = 0;
02845 connect = 0;
02846 end = 0;
02847 }
02848 ast_debug(1, "OSPFinish: start '%ld'\n", start);
02849 ast_debug(1, "OSPFinish: connect '%ld'\n", connect);
02850 ast_debug(1, "OSPFinish: end '%ld'\n", end);
02851
02852 release = ast_check_hangup(chan) ? 0 : 1;
02853
02854 if (osp_finish(outhandle, recorded, cause, start, connect, end, release, inqos, outqos) <= 0) {
02855 ast_debug(1, "OSPFinish: Unable to report usage for outbound call\n");
02856 }
02857 switch (cause) {
02858 case AST_CAUSE_NORMAL_CLEARING:
02859 break;
02860 default:
02861 cause = AST_CAUSE_NO_ROUTE_DESTINATION;
02862 break;
02863 }
02864 if (osp_finish(inhandle, recorded, cause, start, connect, end, release, inqos, outqos) <= 0) {
02865 ast_debug(1, "OSPFinish: Unable to report usage for inbound call\n");
02866 }
02867 snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
02868 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
02869 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
02870
02871 if (res > 0) {
02872 status = AST_OSP_SUCCESS;
02873 } else if (!res) {
02874 status = AST_OSP_FAILED;
02875 } else {
02876 status = AST_OSP_ERROR;
02877 }
02878 pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
02879
02880 if(res != OSP_OK) {
02881 res = OSP_AST_ERROR;
02882 } else {
02883 res = OSP_AST_OK;
02884 }
02885
02886 return res;
02887 }
02888
02889
02890
02891 static int osp_unload(void)
02892 {
02893 struct osp_provider* provider;
02894 struct osp_provider* next;
02895
02896 if (osp_initialized) {
02897 ast_mutex_lock(&osp_lock);
02898 for (provider = osp_providers; provider; provider = next) {
02899 next = provider->next;
02900 OSPPProviderDelete(provider->handle, 0);
02901 ast_free(provider);
02902 }
02903 osp_providers = NULL;
02904 ast_mutex_unlock(&osp_lock);
02905
02906 OSPPCleanup();
02907
02908 osp_tokenformat = TOKEN_ALGO_SIGNED;
02909 osp_security = 0;
02910 osp_hardware = 0;
02911 osp_initialized = 0;
02912 }
02913
02914 return 0;
02915 }
02916
02917 static int osp_load(int reload)
02918 {
02919 const char* cvar;
02920 unsigned int ivar;
02921 struct ast_config* cfg;
02922 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02923 int error = OSPC_ERR_NO_ERROR;
02924
02925 if ((cfg = ast_config_load(OSP_CONFIG_FILE, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
02926 return 0;
02927 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02928 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", OSP_CONFIG_FILE);
02929 return 0;
02930 }
02931
02932 if (cfg) {
02933 if (reload) {
02934 osp_unload();
02935 }
02936
02937 if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate")) && ast_true(cvar)) {
02938 if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
02939 ast_log(LOG_WARNING, "OSP: Unable to enable hardware accelleration\n");
02940 OSPPInit(0);
02941 } else {
02942 osp_hardware = 1;
02943 }
02944 } else {
02945 OSPPInit(0);
02946 }
02947 ast_debug(1, "OSP: osp_hardware '%d'\n", osp_hardware);
02948
02949 if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "securityfeatures")) && ast_true(cvar)) {
02950 osp_security = 1;
02951 }
02952 ast_debug(1, "OSP: osp_security '%d'\n", osp_security);
02953
02954 if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat"))) {
02955 if ((sscanf(cvar, "%30d", &ivar) == 1) &&
02956 ((ivar == TOKEN_ALGO_SIGNED) || (ivar == TOKEN_ALGO_UNSIGNED) || (ivar == TOKEN_ALGO_BOTH)))
02957 {
02958 osp_tokenformat = ivar;
02959 } else {
02960 ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n",
02961 TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, cvar);
02962 }
02963 }
02964 ast_debug(1, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
02965
02966 for (cvar = ast_category_browse(cfg, NULL); cvar != NULL; cvar = ast_category_browse(cfg, cvar)) {
02967 if (strcasecmp(cvar, OSP_GENERAL_CAT)) {
02968 osp_create_provider(cfg, cvar);
02969 }
02970 }
02971
02972 osp_initialized = 1;
02973
02974 ast_config_destroy(cfg);
02975 } else {
02976 ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
02977 return 0;
02978 }
02979 ast_debug(1, "OSP: osp_initialized '%d'\n", osp_initialized);
02980
02981 return 1;
02982 }
02983
02984 static char *handle_cli_osp_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02985 {
02986 int i;
02987 int found = 0;
02988 struct osp_provider* provider;
02989 const char* name = NULL;
02990 const char* tokenalgo;
02991
02992 switch (cmd) {
02993 case CLI_INIT:
02994 e->command = "osp show";
02995 e->usage =
02996 "Usage: osp show\n"
02997 " Displays information on Open Settlement Protocol support\n";
02998 return NULL;
02999 case CLI_GENERATE:
03000 return NULL;
03001 }
03002
03003 if ((a->argc < 2) || (a->argc > 3)) {
03004 return CLI_SHOWUSAGE;
03005 }
03006
03007 if (a->argc > 2) {
03008 name = a->argv[2];
03009 }
03010
03011 if (!name) {
03012 switch (osp_tokenformat) {
03013 case TOKEN_ALGO_BOTH:
03014 tokenalgo = "Both";
03015 break;
03016 case TOKEN_ALGO_UNSIGNED:
03017 tokenalgo = "Unsigned";
03018 break;
03019 case TOKEN_ALGO_SIGNED:
03020 default:
03021 tokenalgo = "Signed";
03022 break;
03023 }
03024 ast_cli(a->fd, "OSP: %s/%s/%s/%s\n",
03025 osp_initialized ? "Initialized" : "Uninitialized",
03026 osp_hardware ? "Accelerated" : "Normal",
03027 osp_security ? "Enabled" : "Disabled",
03028 tokenalgo);
03029 }
03030
03031 ast_mutex_lock(&osp_lock);
03032 for (provider = osp_providers; provider; provider = provider->next) {
03033 if (!name || !strcasecmp(provider->name, name)) {
03034 if (found) {
03035 ast_cli(a->fd, "\n");
03036 }
03037 ast_cli(a->fd, " == OSP Provider '%s' == \n", provider->name);
03038 if (osp_security) {
03039 ast_cli(a->fd, "Local Private Key: %s\n", provider->privatekey);
03040 ast_cli(a->fd, "Local Certificate: %s\n", provider->localcert);
03041 for (i = 0; i < provider->canum; i++) {
03042 ast_cli(a->fd, "CA Certificate %d: %s\n", i + 1, provider->cacerts[i]);
03043 }
03044 }
03045 for (i = 0; i < provider->spnum; i++) {
03046 ast_cli(a->fd, "Service Point %d: %s\n", i + 1, provider->spoints[i]);
03047 }
03048 ast_cli(a->fd, "Max Connections: %d\n", provider->maxconnect);
03049 ast_cli(a->fd, "Retry Delay: %d seconds\n", provider->retrydelay);
03050 ast_cli(a->fd, "Retry Limit: %d\n", provider->retrylimit);
03051 ast_cli(a->fd, "Timeout: %d milliseconds\n", provider->timeout);
03052 ast_cli(a->fd, "Source: %s\n", strlen(provider->source) ? provider->source : "<unspecified>");
03053 ast_cli(a->fd, "Auth Policy %d\n", provider->authpolicy);
03054 ast_cli(a->fd, "Default protocol %s\n", provider->defprotocol);
03055 ast_cli(a->fd, "Work mode %d\n", provider->workmode);
03056 ast_cli(a->fd, "Service type %d\n", provider->srvtype);
03057 ast_cli(a->fd, "OSP Handle: %d\n", provider->handle);
03058 found++;
03059 }
03060 }
03061 ast_mutex_unlock(&osp_lock);
03062
03063 if (!found) {
03064 if (name) {
03065 ast_cli(a->fd, "Unable to find OSP provider '%s'\n", name);
03066 } else {
03067 ast_cli(a->fd, "No OSP providers configured\n");
03068 }
03069 }
03070
03071 return CLI_SUCCESS;
03072 }
03073
03074
03075 static const char app1[] = "OSPAuth";
03076
03077
03078 static const char app2[] = "OSPLookup";
03079
03080
03081 static const char app3[] = "OSPNext";
03082
03083
03084 static const char app4[] = "OSPFinish";
03085
03086 static struct ast_cli_entry cli_osp[] = {
03087 AST_CLI_DEFINE(handle_cli_osp_show, "Displays OSF information")
03088 };
03089
03090 static int load_module(void)
03091 {
03092 int res;
03093
03094 if (!osp_load(0))
03095 return AST_MODULE_LOAD_DECLINE;
03096
03097 ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
03098 res = ast_register_application_xml(app1, ospauth_exec);
03099 res |= ast_register_application_xml(app2, osplookup_exec);
03100 res |= ast_register_application_xml(app3, ospnext_exec);
03101 res |= ast_register_application_xml(app4, ospfinished_exec);
03102
03103 return res;
03104 }
03105
03106 static int unload_module(void)
03107 {
03108 int res;
03109
03110 res = ast_unregister_application(app4);
03111 res |= ast_unregister_application(app3);
03112 res |= ast_unregister_application(app2);
03113 res |= ast_unregister_application(app1);
03114 ast_cli_unregister_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
03115 osp_unload();
03116
03117 return res;
03118 }
03119
03120 static int reload(void)
03121 {
03122 osp_load(1);
03123
03124 return 0;
03125 }
03126
03127 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
03128 .load = load_module,
03129 .unload = unload_module,
03130 .reload = reload,
03131 );