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