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: 370642 $")
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 tmp = ast_strdupa(data);
02244
02245 AST_STANDARD_APP_ARGS(args, tmp);
02246
02247 if (!ast_strlen_zero(args.provider)) {
02248 provider = args.provider;
02249 }
02250 ast_debug(1, "OSPAuth: provider '%s'\n", provider);
02251
02252 headp = &chan->varshead;
02253 AST_LIST_TRAVERSE(headp, current, entries) {
02254 if (!strcasecmp(ast_var_name(current), "OSPINPEERIP")) {
02255 source = ast_var_value(current);
02256 } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
02257 token = ast_var_value(current);
02258 }
02259 }
02260
02261 ast_debug(1, "OSPAuth: source '%s'\n", source);
02262 ast_debug(1, "OSPAuth: token size '%zd'\n", strlen(token));
02263
02264 res = osp_auth(provider, &handle, source,
02265 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
02266 chan->exten, token, &timelimit);
02267 if (res > 0) {
02268 status = AST_OSP_SUCCESS;
02269 } else {
02270 timelimit = OSP_DEF_TIMELIMIT;
02271 if (!res) {
02272 status = AST_OSP_FAILED;
02273 } else {
02274 status = AST_OSP_ERROR;
02275 }
02276 }
02277
02278 snprintf(buffer, sizeof(buffer), "%d", handle);
02279 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
02280 ast_debug(1, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
02281 snprintf(buffer, sizeof(buffer), "%d", timelimit);
02282 pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
02283 ast_debug(1, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
02284 pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
02285 ast_debug(1, "OSPAuth: %s\n", status);
02286
02287 if(res != OSP_OK) {
02288 res = OSP_AST_ERROR;
02289 } else {
02290 res = OSP_AST_OK;
02291 }
02292
02293 return res;
02294 }
02295
02296
02297
02298
02299
02300
02301
02302 static int osplookup_exec(
02303 struct ast_channel* chan,
02304 const char * data)
02305 {
02306 int res, cres;
02307 const char* provider = OSP_DEF_PROVIDER;
02308 unsigned int callidtypes = OSP_CALLID_UNDEF;
02309 struct varshead* headp;
02310 struct ast_var_t* current;
02311 const char* actualsrc = "";
02312 const char* srcdev = "";
02313 const char* snetid = "";
02314 struct osp_npdata np;
02315 OSPE_OPERATOR_NAME type;
02316 struct osp_diversion div;
02317 unsigned int i;
02318 const char* cinfo[OSP_MAX_CUSTOMINFO] = { NULL };
02319 char buffer[OSP_SIZE_TOKSTR];
02320 struct osp_results results;
02321 const char* status;
02322 char* tmp;
02323
02324 AST_DECLARE_APP_ARGS(args,
02325 AST_APP_ARG(exten);
02326 AST_APP_ARG(provider);
02327 AST_APP_ARG(options);
02328 );
02329
02330 if (ast_strlen_zero(data)) {
02331 ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[,provider[,options]])\n");
02332 return OSP_AST_ERROR;
02333 }
02334
02335 tmp = ast_strdupa(data);
02336
02337 AST_STANDARD_APP_ARGS(args, tmp);
02338
02339 ast_debug(1, "OSPLookup: exten '%s'\n", args.exten);
02340
02341 if (!ast_strlen_zero(args.provider)) {
02342 provider = args.provider;
02343 }
02344 ast_debug(1, "OSPlookup: provider '%s'\n", provider);
02345
02346 if (args.options) {
02347 if (strchr(args.options, 'h')) {
02348 callidtypes |= OSP_CALLID_H323;
02349 }
02350 if (strchr(args.options, 's')) {
02351 callidtypes |= OSP_CALLID_SIP;
02352 }
02353 if (strchr(args.options, 'i')) {
02354 callidtypes |= OSP_CALLID_IAX;
02355 }
02356 }
02357 ast_debug(1, "OSPLookup: call id types '%d'\n", callidtypes);
02358
02359 results.inhandle = OSP_INVALID_HANDLE;
02360 results.intimelimit = OSP_DEF_TIMELIMIT;
02361 results.dest[0] = '\0';
02362
02363 np.rn = "";
02364 np.cic = "";
02365 np.npdi = 0;
02366 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
02367 np.opname[type] = "";
02368 }
02369
02370 div.user = "";
02371 div.host = "";
02372
02373 headp = &chan->varshead;
02374 AST_LIST_TRAVERSE(headp, current, entries) {
02375 if (!strcasecmp(ast_var_name(current), "OSPINACTUALSRC")) {
02376 actualsrc = ast_var_value(current);
02377 } else if (!strcasecmp(ast_var_name(current), "OSPINPEERIP")) {
02378 srcdev = ast_var_value(current);
02379 } else if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
02380 if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
02381 results.inhandle = OSP_INVALID_HANDLE;
02382 }
02383 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
02384 if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
02385 results.intimelimit = OSP_DEF_TIMELIMIT;
02386 }
02387 } else if (!strcasecmp(ast_var_name(current), "OSPINNETWORKID")) {
02388 snetid = ast_var_value(current);
02389 } else if (!strcasecmp(ast_var_name(current), "OSPINNPRN")) {
02390 np.rn = ast_var_value(current);
02391 } else if (!strcasecmp(ast_var_name(current), "OSPINNPCIC")) {
02392 np.cic = ast_var_value(current);
02393 } else if (!strcasecmp(ast_var_name(current), "OSPINNPDI")) {
02394 if (ast_true(ast_var_value(current))) {
02395 np.npdi = 1;
02396 }
02397 } else if (!strcasecmp(ast_var_name(current), "OSPINSPID")) {
02398 np.opname[OSPC_OPNAME_SPID] = ast_var_value(current);
02399 } else if (!strcasecmp(ast_var_name(current), "OSPINOCN")) {
02400 np.opname[OSPC_OPNAME_OCN] = ast_var_value(current);
02401 } else if (!strcasecmp(ast_var_name(current), "OSPINSPN")) {
02402 np.opname[OSPC_OPNAME_SPN] = ast_var_value(current);
02403 } else if (!strcasecmp(ast_var_name(current), "OSPINALTSPN")) {
02404 np.opname[OSPC_OPNAME_ALTSPN] = ast_var_value(current);
02405 } else if (!strcasecmp(ast_var_name(current), "OSPINMCC")) {
02406 np.opname[OSPC_OPNAME_MCC] = ast_var_value(current);
02407 } else if (!strcasecmp(ast_var_name(current), "OSPINMNC")) {
02408 np.opname[OSPC_OPNAME_MNC] = ast_var_value(current);
02409 } else if (!strcasecmp(ast_var_name(current), "OSPINTOHOST")) {
02410 ast_copy_string(results.dest, ast_var_value(current), sizeof(results.dest));
02411 } else if (!strcasecmp(ast_var_name(current), "OSPINDIVUSER")) {
02412 div.user = ast_var_value(current);
02413 } else if (!strcasecmp(ast_var_name(current), "OSPINDIVHOST")) {
02414 div.host = ast_var_value(current);
02415 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO1")) {
02416 cinfo[0] = ast_var_value(current);
02417 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO2")) {
02418 cinfo[1] = ast_var_value(current);
02419 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO3")) {
02420 cinfo[2] = ast_var_value(current);
02421 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO4")) {
02422 cinfo[3] = ast_var_value(current);
02423 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO5")) {
02424 cinfo[4] = ast_var_value(current);
02425 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO6")) {
02426 cinfo[5] = ast_var_value(current);
02427 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO7")) {
02428 cinfo[6] = ast_var_value(current);
02429 } else if (!strcasecmp(ast_var_name(current), "OSPINCUSTOMINFO8")) {
02430 cinfo[7] = ast_var_value(current);
02431 }
02432 }
02433 ast_debug(1, "OSPLookup: actual source device '%s'\n", actualsrc);
02434 ast_debug(1, "OSPLookup: source device '%s'\n", srcdev);
02435 ast_debug(1, "OSPLookup: OSPINHANDLE '%d'\n", results.inhandle);
02436 ast_debug(1, "OSPLookup: OSPINTIMELIMIT '%d'\n", results.intimelimit);
02437 ast_debug(1, "OSPLookup: OSPINNETWORKID '%s'\n", snetid);
02438 ast_debug(1, "OSPLookup: OSPINNPRN '%s'\n", np.rn);
02439 ast_debug(1, "OSPLookup: OSPINNPCIC '%s'\n", np.cic);
02440 ast_debug(1, "OSPLookup: OSPINNPDI '%d'\n", np.npdi);
02441 ast_debug(1, "OSPLookup: OSPINSPID '%s'\n", np.opname[OSPC_OPNAME_SPID]);
02442 ast_debug(1, "OSPLookup: OSPINOCN '%s'\n", np.opname[OSPC_OPNAME_OCN]);
02443 ast_debug(1, "OSPLookup: OSPINSPN '%s'\n", np.opname[OSPC_OPNAME_SPN]);
02444 ast_debug(1, "OSPLookup: OSPINALTSPN '%s'\n", np.opname[OSPC_OPNAME_ALTSPN]);
02445 ast_debug(1, "OSPLookup: OSPINMCC '%s'\n", np.opname[OSPC_OPNAME_MCC]);
02446 ast_debug(1, "OSPLookup: OSPINMNC '%s'\n", np.opname[OSPC_OPNAME_MNC]);
02447 ast_debug(1, "OSPLookup: OSPINTOHOST '%s'\n", results.dest);
02448 ast_debug(1, "OSPLookup: OSPINDIVUSER '%s'\n", div.user);
02449 ast_debug(1, "OSPLookup: OSPINDIVHOST'%s'\n", div.host);
02450 for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
02451 if (!ast_strlen_zero(cinfo[i])) {
02452 ast_debug(1, "OSPLookup: OSPINCUSTOMINFO%d '%s'\n", i, cinfo[i]);
02453 }
02454 }
02455
02456 if ((cres = ast_autoservice_start(chan)) < 0) {
02457 return OSP_AST_ERROR;
02458 }
02459
02460 res = osp_lookup(provider, callidtypes, actualsrc, srcdev,
02461 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
02462 args.exten, snetid, &np, &div, cinfo, &results);
02463 if (res > 0) {
02464 status = AST_OSP_SUCCESS;
02465 } else {
02466 results.tech[0] = '\0';
02467 results.dest[0] = '\0';
02468 results.calling[0] = '\0';
02469 results.called[0] = '\0';
02470 results.token[0] = '\0';
02471 results.networkid[0] = '\0';
02472 results.nprn[0] = '\0';
02473 results.npcic[0] = '\0';
02474 results.npdi = 0;
02475 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
02476 results.opname[type][0] = '\0';
02477 }
02478 results.numdests = 0;
02479 results.outtimelimit = OSP_DEF_TIMELIMIT;
02480 results.outcallid.buf[0] = '\0';
02481 results.outcallid.len = 0;
02482 if (!res) {
02483 status = AST_OSP_FAILED;
02484 } else {
02485 status = AST_OSP_ERROR;
02486 }
02487 }
02488
02489 snprintf(buffer, sizeof(buffer), "%d", results.outhandle);
02490 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
02491 ast_debug(1, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
02492 pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.tech);
02493 ast_debug(1, "OSPLookup: OSPOUTTECH '%s'\n", results.tech);
02494 pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
02495 ast_debug(1, "OSPLookup: OSPDESTINATION '%s'\n", results.dest);
02496 pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
02497 ast_debug(1, "OSPLookup: OSPOUTCALLING '%s'\n", results.calling);
02498 pbx_builtin_setvar_helper(chan, "OSPOUTCALLED", results.called);
02499 ast_debug(1, "OSPLookup: OSPOUTCALLED '%s'\n", results.called);
02500 pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", results.networkid);
02501 ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", results.networkid);
02502 pbx_builtin_setvar_helper(chan, "OSPOUTNPRN", results.nprn);
02503 ast_debug(1, "OSPLookup: OSPOUTNPRN '%s'\n", results.nprn);
02504 pbx_builtin_setvar_helper(chan, "OSPOUTNPCIC", results.npcic);
02505 ast_debug(1, "OSPLookup: OSPOUTNPCIC '%s'\n", results.npcic);
02506 snprintf(buffer, sizeof(buffer), "%d", results.npdi);
02507 pbx_builtin_setvar_helper(chan, "OSPOUTNPDI", buffer);
02508 ast_debug(1, "OSPLookup: OSPOUTNPDI'%s'\n", buffer);
02509 pbx_builtin_setvar_helper(chan, "OSPOUTSPID", results.opname[OSPC_OPNAME_SPID]);
02510 ast_debug(1, "OSPLookup: OSPOUTSPID '%s'\n", results.opname[OSPC_OPNAME_SPID]);
02511 pbx_builtin_setvar_helper(chan, "OSPOUTOCN", results.opname[OSPC_OPNAME_OCN]);
02512 ast_debug(1, "OSPLookup: OSPOUTOCN '%s'\n", results.opname[OSPC_OPNAME_OCN]);
02513 pbx_builtin_setvar_helper(chan, "OSPOUTSPN", results.opname[OSPC_OPNAME_SPN]);
02514 ast_debug(1, "OSPLookup: OSPOUTSPN '%s'\n", results.opname[OSPC_OPNAME_SPN]);
02515 pbx_builtin_setvar_helper(chan, "OSPOUTALTSPN", results.opname[OSPC_OPNAME_ALTSPN]);
02516 ast_debug(1, "OSPLookup: OSPOUTALTSPN '%s'\n", results.opname[OSPC_OPNAME_ALTSPN]);
02517 pbx_builtin_setvar_helper(chan, "OSPOUTMCC", results.opname[OSPC_OPNAME_MCC]);
02518 ast_debug(1, "OSPLookup: OSPOUTMCC '%s'\n", results.opname[OSPC_OPNAME_MCC]);
02519 pbx_builtin_setvar_helper(chan, "OSPOUTMNC", results.opname[OSPC_OPNAME_MNC]);
02520 ast_debug(1, "OSPLookup: OSPOUTMNC '%s'\n", results.opname[OSPC_OPNAME_MNC]);
02521 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", results.token);
02522 ast_debug(1, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(results.token));
02523 snprintf(buffer, sizeof(buffer), "%d", results.numdests);
02524 pbx_builtin_setvar_helper(chan, "OSPDESTREMAILS", buffer);
02525 ast_debug(1, "OSPLookup: OSPDESTREMAILS '%s'\n", buffer);
02526 snprintf(buffer, sizeof(buffer), "%d", results.outtimelimit);
02527 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
02528 ast_debug(1, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
02529 snprintf(buffer, sizeof(buffer), "%d", callidtypes);
02530 pbx_builtin_setvar_helper(chan, "OSPOUTCALLIDTYPES", buffer);
02531 ast_debug(1, "OSPLookup: OSPOUTCALLIDTYPES '%s'\n", buffer);
02532 pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
02533 ast_debug(1, "OSPLookup: %s\n", status);
02534
02535 if (!strcasecmp(results.tech, OSP_TECH_SIP)) {
02536 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
02537 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02538 if (!ast_strlen_zero(results.token)) {
02539 snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
02540 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
02541 ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
02542 }
02543 } else if (!strcasecmp(results.tech, OSP_TECH_H323)) {
02544 if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
02545 osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
02546 } else {
02547 buffer[0] = '\0';
02548 }
02549 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
02550 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
02551 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02552 } else if (!strcasecmp(results.tech, OSP_TECH_IAX)) {
02553 snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.tech, results.dest, results.called);
02554 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02555 } else if (!strcasecmp(results.tech, OSP_TECH_SKYPE)) {
02556 snprintf(buffer, sizeof(buffer), "%s/%s", results.tech, results.called);
02557 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02558 }
02559
02560 if ((cres = ast_autoservice_stop(chan)) < 0) {
02561 return OSP_AST_ERROR;
02562 }
02563
02564 if(res != OSP_OK) {
02565 res = OSP_AST_ERROR;
02566 } else {
02567 res = OSP_AST_OK;
02568 }
02569
02570 return res;
02571 }
02572
02573
02574
02575
02576
02577
02578
02579 static int ospnext_exec(
02580 struct ast_channel* chan,
02581 const char * data)
02582 {
02583 int res;
02584 const char* provider = OSP_DEF_PROVIDER;
02585 int cause = 0;
02586 struct varshead* headp;
02587 struct ast_var_t* current;
02588 struct osp_results results;
02589 OSPE_OPERATOR_NAME type;
02590 char buffer[OSP_SIZE_TOKSTR];
02591 unsigned int callidtypes = OSP_CALLID_UNDEF;
02592 const char* status;
02593 char* tmp;
02594
02595 AST_DECLARE_APP_ARGS(args,
02596 AST_APP_ARG(cause);
02597 AST_APP_ARG(provider);
02598 AST_APP_ARG(options);
02599 );
02600
02601 if (ast_strlen_zero(data)) {
02602 ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[,provider[,options]])\n");
02603 return OSP_AST_ERROR;
02604 }
02605
02606 tmp = ast_strdupa(data);
02607
02608 AST_STANDARD_APP_ARGS(args, tmp);
02609
02610 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
02611 cause = 0;
02612 }
02613 ast_debug(1, "OSPNext: cause '%d'\n", cause);
02614
02615 if (!ast_strlen_zero(args.provider)) {
02616 provider = args.provider;
02617 }
02618 ast_debug(1, "OSPlookup: provider '%s'\n", provider);
02619
02620 results.inhandle = OSP_INVALID_HANDLE;
02621 results.outhandle = OSP_INVALID_HANDLE;
02622 results.intimelimit = OSP_DEF_TIMELIMIT;
02623 results.numdests = 0;
02624
02625 headp = &chan->varshead;
02626 AST_LIST_TRAVERSE(headp, current, entries) {
02627 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
02628 if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
02629 results.inhandle = OSP_INVALID_HANDLE;
02630 }
02631 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
02632 if (sscanf(ast_var_value(current), "%30d", &results.outhandle) != 1) {
02633 results.outhandle = OSP_INVALID_HANDLE;
02634 }
02635 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
02636 if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
02637 results.intimelimit = OSP_DEF_TIMELIMIT;
02638 }
02639 } else if (!strcasecmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) {
02640 if (sscanf(ast_var_value(current), "%30d", &callidtypes) != 1) {
02641 callidtypes = OSP_CALLID_UNDEF;
02642 }
02643 } else if (!strcasecmp(ast_var_name(current), "OSPDESTREMAILS")) {
02644 if (sscanf(ast_var_value(current), "%30d", &results.numdests) != 1) {
02645 results.numdests = 0;
02646 }
02647 }
02648 }
02649 ast_debug(1, "OSPNext: OSPINHANDLE '%d'\n", results.inhandle);
02650 ast_debug(1, "OSPNext: OSPOUTHANDLE '%d'\n", results.outhandle);
02651 ast_debug(1, "OSPNext: OSPINTIMELIMIT '%d'\n", results.intimelimit);
02652 ast_debug(1, "OSPNext: OSPOUTCALLIDTYPES '%d'\n", callidtypes);
02653 ast_debug(1, "OSPNext: OSPDESTREMAILS '%d'\n", results.numdests);
02654
02655 if ((res = osp_next(provider, cause, &results)) > 0) {
02656 status = AST_OSP_SUCCESS;
02657 } else {
02658 results.tech[0] = '\0';
02659 results.dest[0] = '\0';
02660 results.calling[0] = '\0';
02661 results.called[0] = '\0';
02662 results.token[0] = '\0';
02663 results.networkid[0] = '\0';
02664 results.nprn[0] = '\0';
02665 results.npcic[0] = '\0';
02666 results.npdi = 0;
02667 for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
02668 results.opname[type][0] = '\0';
02669 }
02670 results.numdests = 0;
02671 results.outtimelimit = OSP_DEF_TIMELIMIT;
02672 results.outcallid.buf[0] = '\0';
02673 results.outcallid.len = 0;
02674 if (!res) {
02675 status = AST_OSP_FAILED;
02676 } else {
02677 status = AST_OSP_ERROR;
02678 }
02679 }
02680
02681 pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.tech);
02682 ast_debug(1, "OSPNext: OSPOUTTECH '%s'\n", results.tech);
02683 pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
02684 ast_debug(1, "OSPNext: OSPDESTINATION '%s'\n", results.dest);
02685 pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
02686 ast_debug(1, "OSPNext: OSPOUTCALLING '%s'\n", results.calling);
02687 pbx_builtin_setvar_helper(chan, "OSPOUTCALLED", results.called);
02688 ast_debug(1, "OSPNext: OSPOUTCALLED'%s'\n", results.called);
02689 pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", results.networkid);
02690 ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", results.networkid);
02691 pbx_builtin_setvar_helper(chan, "OSPOUTNPRN", results.nprn);
02692 ast_debug(1, "OSPLookup: OSPOUTNPRN '%s'\n", results.nprn);
02693 pbx_builtin_setvar_helper(chan, "OSPOUTNPCIC", results.npcic);
02694 ast_debug(1, "OSPLookup: OSPOUTNPCIC '%s'\n", results.npcic);
02695 snprintf(buffer, sizeof(buffer), "%d", results.npdi);
02696 pbx_builtin_setvar_helper(chan, "OSPOUTNPDI", buffer);
02697 ast_debug(1, "OSPLookup: OSPOUTNPDI'%s'\n", buffer);
02698 pbx_builtin_setvar_helper(chan, "OSPOUTSPID", results.opname[OSPC_OPNAME_SPID]);
02699 ast_debug(1, "OSPLookup: OSPOUTSPID '%s'\n", results.opname[OSPC_OPNAME_SPID]);
02700 pbx_builtin_setvar_helper(chan, "OSPOUTOCN", results.opname[OSPC_OPNAME_OCN]);
02701 ast_debug(1, "OSPLookup: OSPOUTOCN '%s'\n", results.opname[OSPC_OPNAME_OCN]);
02702 pbx_builtin_setvar_helper(chan, "OSPOUTSPN", results.opname[OSPC_OPNAME_SPN]);
02703 ast_debug(1, "OSPLookup: OSPOUTSPN '%s'\n", results.opname[OSPC_OPNAME_SPN]);
02704 pbx_builtin_setvar_helper(chan, "OSPOUTALTSPN", results.opname[OSPC_OPNAME_ALTSPN]);
02705 ast_debug(1, "OSPLookup: OSPOUTALTSPN '%s'\n", results.opname[OSPC_OPNAME_ALTSPN]);
02706 pbx_builtin_setvar_helper(chan, "OSPOUTMCC", results.opname[OSPC_OPNAME_MCC]);
02707 ast_debug(1, "OSPLookup: OSPOUTMCC '%s'\n", results.opname[OSPC_OPNAME_MCC]);
02708 pbx_builtin_setvar_helper(chan, "OSPOUTMNC", results.opname[OSPC_OPNAME_MNC]);
02709 ast_debug(1, "OSPLookup: OSPOUTMNC '%s'\n", results.opname[OSPC_OPNAME_MNC]);
02710 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", results.token);
02711 ast_debug(1, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(results.token));
02712 snprintf(buffer, sizeof(buffer), "%d", results.numdests);
02713 pbx_builtin_setvar_helper(chan, "OSPDESTREMAILS", buffer);
02714 ast_debug(1, "OSPNext: OSPDESTREMAILS '%s'\n", buffer);
02715 snprintf(buffer, sizeof(buffer), "%d", results.outtimelimit);
02716 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
02717 ast_debug(1, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
02718 pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
02719 ast_debug(1, "OSPNext: %s\n", status);
02720
02721 if (!strcasecmp(results.tech, OSP_TECH_SIP)) {
02722 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
02723 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02724 if (!ast_strlen_zero(results.token)) {
02725 snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
02726 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
02727 ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
02728 }
02729 } else if (!strcasecmp(results.tech, OSP_TECH_H323)) {
02730 if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
02731 osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
02732 } else {
02733 buffer[0] = '\0';
02734 }
02735 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
02736 snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.tech, results.called, results.dest);
02737 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02738 } else if (!strcasecmp(results.tech, OSP_TECH_IAX)) {
02739 snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.tech, results.dest, results.called);
02740 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02741 } else if (!strcasecmp(results.tech, OSP_TECH_SKYPE)) {
02742 snprintf(buffer, sizeof(buffer), "%s/%s", results.tech, results.called);
02743 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02744 }
02745
02746 if(res != OSP_OK) {
02747 res = OSP_AST_ERROR;
02748 } else {
02749 res = OSP_AST_OK;
02750 }
02751
02752 return res;
02753 }
02754
02755
02756
02757
02758
02759
02760
02761 static int ospfinished_exec(
02762 struct ast_channel* chan,
02763 const char * data)
02764 {
02765 int res = OSP_OK;
02766 int cause = 0;
02767 struct varshead* headp;
02768 struct ast_var_t* current;
02769 int inhandle = OSP_INVALID_HANDLE;
02770 int outhandle = OSP_INVALID_HANDLE;
02771 int recorded = 0;
02772 time_t start, connect, end;
02773 unsigned int release;
02774 char buffer[OSP_SIZE_INTSTR];
02775 char inqos[OSP_SIZE_QOSSTR] = { 0 };
02776 char outqos[OSP_SIZE_QOSSTR] = { 0 };
02777 const char* status;
02778 char* tmp;
02779
02780 AST_DECLARE_APP_ARGS(args,
02781 AST_APP_ARG(cause);
02782 AST_APP_ARG(options);
02783 );
02784
02785 tmp = ast_strdupa(data);
02786
02787 AST_STANDARD_APP_ARGS(args, tmp);
02788
02789 headp = &chan->varshead;
02790 AST_LIST_TRAVERSE(headp, current, entries) {
02791 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
02792 if (sscanf(ast_var_value(current), "%30d", &inhandle) != 1) {
02793 inhandle = OSP_INVALID_HANDLE;
02794 }
02795 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
02796 if (sscanf(ast_var_value(current), "%30d", &outhandle) != 1) {
02797 outhandle = OSP_INVALID_HANDLE;
02798 }
02799 } else if (!recorded &&
02800 (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") ||
02801 !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") ||
02802 !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS")))
02803 {
02804 if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) {
02805 recorded = 1;
02806 }
02807 } else if (!strcasecmp(ast_var_name(current), "OSPINAUDIOQOS")) {
02808 ast_copy_string(inqos, ast_var_value(current), sizeof(inqos));
02809 } else if (!strcasecmp(ast_var_name(current), "OSPOUTAUDIOQOS")) {
02810 ast_copy_string(outqos, ast_var_value(current), sizeof(outqos));
02811 }
02812 }
02813 ast_debug(1, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
02814 ast_debug(1, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
02815 ast_debug(1, "OSPFinish: recorded '%d'\n", recorded);
02816 ast_debug(1, "OSPFinish: OSPINAUDIOQOS '%s'\n", inqos);
02817 ast_debug(1, "OSPFinish: OSPOUTAUDIOQOS '%s'\n", outqos);
02818
02819 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
02820 cause = 0;
02821 }
02822 ast_debug(1, "OSPFinish: cause '%d'\n", cause);
02823
02824 if (chan->cdr) {
02825 start = chan->cdr->start.tv_sec;
02826 connect = chan->cdr->answer.tv_sec;
02827 if (connect) {
02828 end = time(NULL);
02829 } else {
02830 end = connect;
02831 }
02832 } else {
02833 start = 0;
02834 connect = 0;
02835 end = 0;
02836 }
02837 ast_debug(1, "OSPFinish: start '%ld'\n", start);
02838 ast_debug(1, "OSPFinish: connect '%ld'\n", connect);
02839 ast_debug(1, "OSPFinish: end '%ld'\n", end);
02840
02841 release = ast_check_hangup(chan) ? 0 : 1;
02842
02843 if (osp_finish(outhandle, recorded, cause, start, connect, end, release, inqos, outqos) <= 0) {
02844 ast_debug(1, "OSPFinish: Unable to report usage for outbound call\n");
02845 }
02846 switch (cause) {
02847 case AST_CAUSE_NORMAL_CLEARING:
02848 break;
02849 default:
02850 cause = AST_CAUSE_NO_ROUTE_DESTINATION;
02851 break;
02852 }
02853 if (osp_finish(inhandle, recorded, cause, start, connect, end, release, inqos, outqos) <= 0) {
02854 ast_debug(1, "OSPFinish: Unable to report usage for inbound call\n");
02855 }
02856 snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
02857 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
02858 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
02859
02860 if (res > 0) {
02861 status = AST_OSP_SUCCESS;
02862 } else if (!res) {
02863 status = AST_OSP_FAILED;
02864 } else {
02865 status = AST_OSP_ERROR;
02866 }
02867 pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
02868
02869 if(res != OSP_OK) {
02870 res = OSP_AST_ERROR;
02871 } else {
02872 res = OSP_AST_OK;
02873 }
02874
02875 return res;
02876 }
02877
02878
02879
02880 static int osp_unload(void)
02881 {
02882 struct osp_provider* provider;
02883 struct osp_provider* next;
02884
02885 if (osp_initialized) {
02886 ast_mutex_lock(&osp_lock);
02887 for (provider = osp_providers; provider; provider = next) {
02888 next = provider->next;
02889 OSPPProviderDelete(provider->handle, 0);
02890 ast_free(provider);
02891 }
02892 osp_providers = NULL;
02893 ast_mutex_unlock(&osp_lock);
02894
02895 OSPPCleanup();
02896
02897 osp_tokenformat = TOKEN_ALGO_SIGNED;
02898 osp_security = 0;
02899 osp_hardware = 0;
02900 osp_initialized = 0;
02901 }
02902
02903 return 0;
02904 }
02905
02906 static int osp_load(int reload)
02907 {
02908 const char* cvar;
02909 unsigned int ivar;
02910 struct ast_config* cfg;
02911 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02912 int error = OSPC_ERR_NO_ERROR;
02913
02914 if ((cfg = ast_config_load(OSP_CONFIG_FILE, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
02915 return 0;
02916 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02917 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", OSP_CONFIG_FILE);
02918 return 0;
02919 }
02920
02921 if (cfg) {
02922 if (reload) {
02923 osp_unload();
02924 }
02925
02926 if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate")) && ast_true(cvar)) {
02927 if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
02928 ast_log(LOG_WARNING, "OSP: Unable to enable hardware accelleration\n");
02929 OSPPInit(0);
02930 } else {
02931 osp_hardware = 1;
02932 }
02933 } else {
02934 OSPPInit(0);
02935 }
02936 ast_debug(1, "OSP: osp_hardware '%d'\n", osp_hardware);
02937
02938 if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "securityfeatures")) && ast_true(cvar)) {
02939 osp_security = 1;
02940 }
02941 ast_debug(1, "OSP: osp_security '%d'\n", osp_security);
02942
02943 if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat"))) {
02944 if ((sscanf(cvar, "%30d", &ivar) == 1) &&
02945 ((ivar == TOKEN_ALGO_SIGNED) || (ivar == TOKEN_ALGO_UNSIGNED) || (ivar == TOKEN_ALGO_BOTH)))
02946 {
02947 osp_tokenformat = ivar;
02948 } else {
02949 ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n",
02950 TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, cvar);
02951 }
02952 }
02953 ast_debug(1, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
02954
02955 for (cvar = ast_category_browse(cfg, NULL); cvar != NULL; cvar = ast_category_browse(cfg, cvar)) {
02956 if (strcasecmp(cvar, OSP_GENERAL_CAT)) {
02957 osp_create_provider(cfg, cvar);
02958 }
02959 }
02960
02961 osp_initialized = 1;
02962
02963 ast_config_destroy(cfg);
02964 } else {
02965 ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
02966 return 0;
02967 }
02968 ast_debug(1, "OSP: osp_initialized '%d'\n", osp_initialized);
02969
02970 return 1;
02971 }
02972
02973 static char *handle_cli_osp_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02974 {
02975 int i;
02976 int found = 0;
02977 struct osp_provider* provider;
02978 const char* name = NULL;
02979 const char* tokenalgo;
02980
02981 switch (cmd) {
02982 case CLI_INIT:
02983 e->command = "osp show";
02984 e->usage =
02985 "Usage: osp show\n"
02986 " Displays information on Open Settlement Protocol support\n";
02987 return NULL;
02988 case CLI_GENERATE:
02989 return NULL;
02990 }
02991
02992 if ((a->argc < 2) || (a->argc > 3)) {
02993 return CLI_SHOWUSAGE;
02994 }
02995
02996 if (a->argc > 2) {
02997 name = a->argv[2];
02998 }
02999
03000 if (!name) {
03001 switch (osp_tokenformat) {
03002 case TOKEN_ALGO_BOTH:
03003 tokenalgo = "Both";
03004 break;
03005 case TOKEN_ALGO_UNSIGNED:
03006 tokenalgo = "Unsigned";
03007 break;
03008 case TOKEN_ALGO_SIGNED:
03009 default:
03010 tokenalgo = "Signed";
03011 break;
03012 }
03013 ast_cli(a->fd, "OSP: %s/%s/%s/%s\n",
03014 osp_initialized ? "Initialized" : "Uninitialized",
03015 osp_hardware ? "Accelerated" : "Normal",
03016 osp_security ? "Enabled" : "Disabled",
03017 tokenalgo);
03018 }
03019
03020 ast_mutex_lock(&osp_lock);
03021 for (provider = osp_providers; provider; provider = provider->next) {
03022 if (!name || !strcasecmp(provider->name, name)) {
03023 if (found) {
03024 ast_cli(a->fd, "\n");
03025 }
03026 ast_cli(a->fd, " == OSP Provider '%s' == \n", provider->name);
03027 if (osp_security) {
03028 ast_cli(a->fd, "Local Private Key: %s\n", provider->privatekey);
03029 ast_cli(a->fd, "Local Certificate: %s\n", provider->localcert);
03030 for (i = 0; i < provider->canum; i++) {
03031 ast_cli(a->fd, "CA Certificate %d: %s\n", i + 1, provider->cacerts[i]);
03032 }
03033 }
03034 for (i = 0; i < provider->spnum; i++) {
03035 ast_cli(a->fd, "Service Point %d: %s\n", i + 1, provider->spoints[i]);
03036 }
03037 ast_cli(a->fd, "Max Connections: %d\n", provider->maxconnect);
03038 ast_cli(a->fd, "Retry Delay: %d seconds\n", provider->retrydelay);
03039 ast_cli(a->fd, "Retry Limit: %d\n", provider->retrylimit);
03040 ast_cli(a->fd, "Timeout: %d milliseconds\n", provider->timeout);
03041 ast_cli(a->fd, "Source: %s\n", strlen(provider->source) ? provider->source : "<unspecified>");
03042 ast_cli(a->fd, "Auth Policy %d\n", provider->authpolicy);
03043 ast_cli(a->fd, "Default protocol %s\n", provider->defprotocol);
03044 ast_cli(a->fd, "Work mode %d\n", provider->workmode);
03045 ast_cli(a->fd, "Service type %d\n", provider->srvtype);
03046 ast_cli(a->fd, "OSP Handle: %d\n", provider->handle);
03047 found++;
03048 }
03049 }
03050 ast_mutex_unlock(&osp_lock);
03051
03052 if (!found) {
03053 if (name) {
03054 ast_cli(a->fd, "Unable to find OSP provider '%s'\n", name);
03055 } else {
03056 ast_cli(a->fd, "No OSP providers configured\n");
03057 }
03058 }
03059
03060 return CLI_SUCCESS;
03061 }
03062
03063
03064 static const char app1[] = "OSPAuth";
03065
03066
03067 static const char app2[] = "OSPLookup";
03068
03069
03070 static const char app3[] = "OSPNext";
03071
03072
03073 static const char app4[] = "OSPFinish";
03074
03075 static struct ast_cli_entry cli_osp[] = {
03076 AST_CLI_DEFINE(handle_cli_osp_show, "Displays OSF information")
03077 };
03078
03079 static int load_module(void)
03080 {
03081 int res;
03082
03083 if (!osp_load(0))
03084 return AST_MODULE_LOAD_DECLINE;
03085
03086 ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
03087 res = ast_register_application_xml(app1, ospauth_exec);
03088 res |= ast_register_application_xml(app2, osplookup_exec);
03089 res |= ast_register_application_xml(app3, ospnext_exec);
03090 res |= ast_register_application_xml(app4, ospfinished_exec);
03091
03092 return res;
03093 }
03094
03095 static int unload_module(void)
03096 {
03097 int res;
03098
03099 res = ast_unregister_application(app4);
03100 res |= ast_unregister_application(app3);
03101 res |= ast_unregister_application(app2);
03102 res |= ast_unregister_application(app1);
03103 ast_cli_unregister_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
03104 osp_unload();
03105
03106 return res;
03107 }
03108
03109 static int reload(void)
03110 {
03111 osp_load(1);
03112
03113 return 0;
03114 }
03115
03116 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
03117 .load = load_module,
03118 .unload = unload_module,
03119 .reload = reload,
03120 );