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
00044 #include <string.h>
00045 #include <stdlib.h>
00046 #include <stdio.h>
00047 #include <math.h>
00048 #include "../../sr_module.h"
00049 #include "../../lib/srdb1/db.h"
00050 #include "../../dprint.h"
00051 #include "../../error.h"
00052 #include "../../ut.h"
00053 #include "../../action.h"
00054 #include "../../pvar.h"
00055 #include "../../dset.h"
00056 #include "../../mem/mem.h"
00057 #include "../../lib/kmi/mi.h"
00058 #include "../../parser/parse_to.h"
00059 #include "../../rpc.h"
00060 #include "../../rpc_lookup.h"
00061 #include "../../lvalue.h"
00062 #include "dialplan.h"
00063 #include "dp_db.h"
00064
00065 MODULE_VERSION
00066
00067 #define DEFAULT_PARAM "$ruri.user"
00068
00069 static int mod_init(void);
00070 static int child_init(int rank);
00071 static void mod_destroy();
00072 static int mi_child_init();
00073
00074 static int dialplan_init_rpc(void);
00075
00076 static struct mi_root * mi_reload_rules(struct mi_root *cmd_tree,void *param);
00077 static struct mi_root * mi_translate(struct mi_root *cmd_tree, void *param);
00078 static int dp_translate_f(struct sip_msg* msg, char* str1, char* str2);
00079 static int dp_trans_fixup(void ** param, int param_no);
00080
00081 str attr_pvar_s = {NULL,0};
00082 pv_spec_t * attr_pvar = NULL;
00083
00084 str default_param_s = str_init(DEFAULT_PARAM);
00085 dp_param_p default_par2 = NULL;
00086
00087 int dp_fetch_rows = 1000;
00088
00089 static param_export_t mod_params[]={
00090 { "db_url", STR_PARAM, &dp_db_url.s },
00091 { "table_name", STR_PARAM, &dp_table_name.s },
00092 { "dpid_col", STR_PARAM, &dpid_column.s },
00093 { "pr_col", STR_PARAM, &pr_column.s },
00094 { "match_op_col", STR_PARAM, &match_op_column.s },
00095 { "match_exp_col", STR_PARAM, &match_exp_column.s },
00096 { "match_len_col", STR_PARAM, &match_len_column.s },
00097 { "subst_exp_col", STR_PARAM, &subst_exp_column.s },
00098 { "repl_exp_col", STR_PARAM, &repl_exp_column.s },
00099 { "attrs_col", STR_PARAM, &attrs_column.s },
00100 { "attrs_pvar", STR_PARAM, &attr_pvar_s.s},
00101 { "attribute_pvar", STR_PARAM, &attr_pvar_s.s},
00102 { "fetch_rows", INT_PARAM, &dp_fetch_rows},
00103 {0,0,0}
00104 };
00105
00106 static mi_export_t mi_cmds[] = {
00107 { "dp_reload", mi_reload_rules, MI_NO_INPUT_FLAG, 0, mi_child_init},
00108 { "dp_translate", mi_translate, 0, 0, 0},
00109 { 0, 0, 0, 0, 0}
00110 };
00111
00112 static cmd_export_t cmds[]={
00113 {"dp_translate",(cmd_function)dp_translate_f, 2, dp_trans_fixup, 0,
00114 ANY_ROUTE},
00115 {"dp_translate",(cmd_function)dp_translate_f, 1, dp_trans_fixup, 0,
00116 ANY_ROUTE},
00117 {0,0,0,0,0,0}
00118 };
00119
00120 struct module_exports exports= {
00121 "dialplan",
00122 DEFAULT_DLFLAGS,
00123 cmds,
00124 mod_params,
00125 0,
00126 mi_cmds,
00127 0,
00128 0,
00129 mod_init,
00130 0,
00131 mod_destroy,
00132 child_init
00133 };
00134
00135
00136 static int mod_init(void)
00137 {
00138 if(register_mi_mod(exports.name, mi_cmds)!=0)
00139 {
00140 LM_ERR("failed to register MI commands\n");
00141 return -1;
00142 }
00143 if(dialplan_init_rpc()!=0)
00144 {
00145 LM_ERR("failed to register RPC commands\n");
00146 return -1;
00147 }
00148
00149
00150 dp_db_url.len = dp_db_url.s ? strlen(dp_db_url.s) : 0;
00151 LM_DBG("db_url=%s/%d/%p\n", ZSW(dp_db_url.s), dp_db_url.len,dp_db_url.s);
00152 dp_table_name.len = strlen(dp_table_name.s);
00153 dpid_column.len = strlen( dpid_column.s);
00154 pr_column.len = strlen(pr_column.s);
00155 match_op_column.len = strlen(match_op_column.s);
00156 match_exp_column.len= strlen(match_exp_column.s);
00157 match_len_column.len= strlen(match_len_column.s);
00158 subst_exp_column.len= strlen(subst_exp_column.s);
00159 repl_exp_column.len = strlen(repl_exp_column.s);
00160 attrs_column.len = strlen(attrs_column.s);
00161
00162 if(attr_pvar_s.s) {
00163 attr_pvar = (pv_spec_t *)shm_malloc(sizeof(pv_spec_t));
00164 if(!attr_pvar){
00165 LM_ERR("out of shm memory\n");
00166 return -1;
00167 }
00168
00169 attr_pvar_s.len = strlen(attr_pvar_s.s);
00170 if( (pv_parse_spec(&attr_pvar_s, attr_pvar)==NULL) ||
00171 ((attr_pvar->type != PVT_AVP) && (attr_pvar->type!=PVT_SCRIPTVAR))) {
00172 LM_ERR("invalid pvar name\n");
00173 return -1;
00174 }
00175 }
00176
00177 default_par2 = (dp_param_p)shm_malloc(sizeof(dp_param_t));
00178 if(default_par2 == NULL){
00179 LM_ERR("no shm more memory\n");
00180 return -1;
00181 }
00182 memset(default_par2, 0, sizeof(dp_param_t));
00183
00184 default_param_s.len = strlen(default_param_s.s);
00185 if (pv_parse_spec( &default_param_s, &default_par2->v.sp[0])==NULL) {
00186 LM_ERR("input pv is invalid\n");
00187 return -1;
00188 }
00189
00190 default_param_s.len = strlen(default_param_s.s);
00191 if (pv_parse_spec( &default_param_s, &default_par2->v.sp[1])==NULL) {
00192 LM_ERR("output pv is invalid\n");
00193 return -1;
00194 }
00195
00196 if(dp_fetch_rows<=0)
00197 dp_fetch_rows = 1000;
00198
00199 if(init_data() != 0) {
00200 LM_ERR("could not initialize data\n");
00201 return -1;
00202 }
00203
00204 return 0;
00205 }
00206
00207
00208 static int child_init(int rank)
00209 {
00210 return 0;
00211 }
00212
00213
00214 static void mod_destroy(void)
00215 {
00216
00217 if(default_par2){
00218 shm_free(default_par2);
00219 default_par2 = NULL;
00220 }
00221 if(attr_pvar){
00222 shm_free(attr_pvar);
00223 attr_pvar = NULL;
00224 }
00225 destroy_data();
00226 }
00227
00228
00229 static int mi_child_init(void)
00230 {
00231 return 0;
00232 }
00233
00234
00235 static int dp_get_ivalue(struct sip_msg* msg, dp_param_p dp, int *val)
00236 {
00237 pv_value_t value;
00238
00239 if(dp->type==DP_VAL_INT) {
00240 LM_DBG("integer value\n");
00241 *val = dp->v.id;
00242 return 0;
00243 }
00244
00245 LM_DBG("searching %d\n",dp->v.sp[0].type);
00246
00247 if( pv_get_spec_value( msg, &dp->v.sp[0], &value)!=0
00248 || value.flags&(PV_VAL_NULL|PV_VAL_EMPTY) || !(value.flags&PV_VAL_INT)) {
00249 LM_ERR("no AVP or SCRIPTVAR found (error in scripts)\n");
00250 return -1;
00251 }
00252 *val = value.ri;
00253 return 0;
00254 }
00255
00256
00257 static int dp_get_svalue(struct sip_msg * msg, pv_spec_t spec, str* val)
00258 {
00259 pv_value_t value;
00260
00261 LM_DBG("searching %d \n", spec.type);
00262
00263 if ( pv_get_spec_value(msg,&spec,&value)!=0 || value.flags&PV_VAL_NULL
00264 || value.flags&PV_VAL_EMPTY || !(value.flags&PV_VAL_STR)){
00265 LM_ERR("no AVP or SCRIPTVAR found (error in scripts)\n");
00266 return -1;
00267 }
00268
00269 *val = value.rs;
00270 return 0;
00271 }
00272
00273
00274 static int dp_update(struct sip_msg * msg, pv_spec_t * src, pv_spec_t * dest,
00275 str * repl, str * attrs)
00276 {
00277 int no_change;
00278 pv_value_t val;
00279
00280 no_change = (dest->type == PVT_NONE) || (!repl->s) || (!repl->len);
00281
00282 if (no_change)
00283 goto set_attr_pvar;
00284
00285 memset(&val, 0, sizeof(pv_value_t));
00286 val.flags = PV_VAL_STR;
00287 val.rs = *repl;
00288
00289 if(dest->setf(msg, &dest->pvp, (int)EQ_T, &val)<0)
00290 {
00291 LM_ERR("setting dst pseudo-variable failed\n");
00292 return -1;
00293 }
00294
00295 if(is_route_type(FAILURE_ROUTE)
00296 && (dest->type==PVT_RURI || dest->type==PVT_RURI_USERNAME)) {
00297 if (append_branch(msg, 0, 0, 0, Q_UNSPECIFIED, 0, 0)!=1 ){
00298 LM_ERR("append_branch action failed\n");
00299 return -1;
00300 }
00301 }
00302
00303 set_attr_pvar:
00304
00305 if(!attr_pvar)
00306 return 0;
00307
00308 val.rs = *attrs;
00309 if(attr_pvar->setf(msg, &attr_pvar->pvp, (int)EQ_T, &val)<0)
00310 {
00311 LM_ERR("setting attr pseudo-variable failed\n");
00312 return -1;
00313 }
00314
00315 return 0;
00316 }
00317
00318
00319 static int dp_translate_f(struct sip_msg* msg, char* str1, char* str2)
00320 {
00321 int dpid;
00322 str input, output;
00323 dpl_id_p idp;
00324 dp_param_p id_par, repl_par;
00325 str attrs, * attrs_par;
00326
00327 if(!msg)
00328 return -1;
00329
00330
00331 id_par = (dp_param_p) str1;
00332 if (dp_get_ivalue(msg, id_par, &dpid) != 0){
00333 LM_ERR("no dpid value\n");
00334 return -1;
00335 }
00336
00337 if ((idp = select_dpid(dpid)) ==0 ){
00338 LM_DBG("no information available for dpid %i\n", dpid);
00339 return -2;
00340 }
00341
00342 repl_par = (str2!=NULL)? ((dp_param_p)str2):default_par2;
00343 if (dp_get_svalue(msg, repl_par->v.sp[0], &input)!=0){
00344 LM_ERR("invalid param 2\n");
00345 return -1;
00346 }
00347
00348 LM_DBG("input is %.*s\n", input.len, input.s);
00349
00350 attrs_par = (!attr_pvar)?NULL:&attrs;
00351 if (translate(msg, input, &output, idp, attrs_par)!=0){
00352 LM_DBG("could not translate %.*s "
00353 "with dpid %i\n", input.len, input.s, idp->dp_id);
00354 return -1;
00355 }
00356 LM_DBG("input %.*s with dpid %i => output %.*s\n",
00357 input.len, input.s, idp->dp_id, output.len, output.s);
00358
00359
00360 if (dp_update(msg, &repl_par->v.sp[0], &repl_par->v.sp[1],
00361 &output, attrs_par) !=0){
00362 LM_ERR("cannot set the output\n");
00363 return -1;
00364 }
00365
00366 return 1;
00367
00368 }
00369
00370 #define verify_par_type(_par_no, _spec)\
00371 do{\
00372 if( ((_par_no == 1) \
00373 && ((_spec).type != PVT_AVP) && ((_spec).type!=PVT_SCRIPTVAR) )\
00374 ||((_par_no == 2) \
00375 && ((_spec).type != PVT_AVP) && ((_spec).type!=PVT_SCRIPTVAR) \
00376 && ((_spec).type!=PVT_RURI) && (_spec.type!=PVT_RURI_USERNAME))){\
00377 \
00378 LM_ERR("Unsupported Parameter TYPE\n");\
00379 return E_UNSPEC;\
00380 }\
00381 }while(0);
00382
00383
00384
00385
00386
00387
00388
00389 static int dp_trans_fixup(void ** param, int param_no){
00390
00391 int dpid;
00392 dp_param_p dp_par= NULL;
00393 char *p, *s=NULL;
00394 str lstr;
00395
00396 if(param_no!=1 && param_no!=2)
00397 return 0;
00398
00399 p = (char*)*param;
00400 if(!p || (*p == '\0')){
00401 LM_DBG("null param %i\n", param_no);
00402 return E_CFG;
00403 }
00404
00405 LM_DBG("param_no is %i\n", param_no);
00406
00407 dp_par = (dp_param_p)pkg_malloc(sizeof(dp_param_t));
00408 if(dp_par == NULL){
00409 LM_ERR("no more pkg memory\n");
00410 return E_OUT_OF_MEM;
00411 }
00412 memset(dp_par, 0, sizeof(dp_param_t));
00413
00414 if(param_no == 1) {
00415 if(*p != '$') {
00416 dp_par->type = DP_VAL_INT;
00417 lstr.s = *param; lstr.len = strlen(*param);
00418 if(str2sint(&lstr, &dpid) != 0) {
00419 LM_ERR("bad number <%s>\n",(char *)(*param));
00420 pkg_free(dp_par);
00421 return E_CFG;
00422 }
00423
00424 dp_par->type = DP_VAL_INT;
00425 dp_par->v.id = dpid;
00426 }else{
00427 lstr.s = p; lstr.len = strlen(p);
00428 if (pv_parse_spec( &lstr, &dp_par->v.sp[0])==NULL)
00429 goto error;
00430
00431 verify_par_type(param_no, dp_par->v.sp[0]);
00432 dp_par->type = DP_VAL_SPEC;
00433 }
00434 } else {
00435
00436 if (((s = strchr(p, '/')) != 0) && (*(s+1)=='\0'))
00437 goto error;
00438
00439 if (s != 0) {
00440 *s = '\0'; s++;
00441 }
00442
00443 lstr.s = p; lstr.len = strlen(p);
00444 if(pv_parse_spec( &lstr, &dp_par->v.sp[0])==NULL)
00445 goto error;
00446
00447 if (s != 0) {
00448 lstr.s = s; lstr.len = strlen(s);
00449 if (pv_parse_spec( &lstr, &dp_par->v.sp[1] )==NULL)
00450 goto error;
00451 verify_par_type(param_no, dp_par->v.sp[1]);
00452 } else {
00453 dp_par->v.sp[1].type = PVT_NONE;
00454 }
00455
00456 dp_par->type = DP_VAL_SPEC;
00457
00458 }
00459
00460 *param = (void *)dp_par;
00461
00462 return 0;
00463
00464 error:
00465 LM_ERR("failed to parse param %i\n", param_no);
00466 return E_INVALID_PARAMS;
00467 }
00468
00469
00470 static struct mi_root * mi_reload_rules(struct mi_root *cmd_tree, void *param)
00471 {
00472 struct mi_root* rpl_tree= NULL;
00473
00474 if (dp_connect_db() < 0) {
00475 LM_ERR("failed to reload rules fron database (db connect)\n");
00476 return 0;
00477 }
00478
00479 if(dp_load_db() != 0){
00480 LM_ERR("failed to reload rules fron database (db load)\n");
00481 dp_disconnect_db();
00482 return 0;
00483 }
00484
00485 dp_disconnect_db();
00486
00487 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00488 if (rpl_tree==0)
00489 return 0;
00490
00491 return rpl_tree;
00492 }
00493
00494
00495
00496
00497
00498
00499
00500 static struct mi_root * mi_translate(struct mi_root *cmd, void *param)
00501 {
00502
00503 struct mi_root* rpl= NULL;
00504 struct mi_node* root, *node;
00505 dpl_id_p idp;
00506 str dpid_str;
00507 str input;
00508 int dpid;
00509 str attrs;
00510 str output= {0, 0};
00511
00512 node = cmd->node.kids;
00513 if(node == NULL)
00514 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00515
00516
00517 dpid_str = node->value;
00518 if(dpid_str.s == NULL || dpid_str.len== 0) {
00519 LM_ERR( "empty idp parameter\n");
00520 return init_mi_tree(404, "Empty id parameter", 18);
00521 }
00522 if(str2sint(&dpid_str, &dpid) != 0) {
00523 LM_ERR("Wrong id parameter - should be an integer\n");
00524 return init_mi_tree(404, "Wrong id parameter", 18);
00525 }
00526
00527 if ((idp = select_dpid(dpid)) ==0 ){
00528 LM_ERR("no information available for dpid %i\n", dpid);
00529 return init_mi_tree(404, "No information available for dpid", 33);
00530 }
00531
00532 node = node->next;
00533 if(node == NULL)
00534 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00535
00536 if(node->next!= NULL)
00537 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00538
00539 input= node->value;
00540 if(input.s == NULL || input.len== 0) {
00541 LM_ERR( "empty input parameter\n");
00542 return init_mi_tree(404, "Empty input parameter", 21);
00543 }
00544
00545 LM_DBG("trying to translate %.*s with dpid %i\n",
00546 input.len, input.s, idp->dp_id);
00547 if (translate(NULL, input, &output, idp, &attrs)!=0){
00548 LM_DBG("could not translate %.*s with dpid %i\n",
00549 input.len, input.s, idp->dp_id);
00550 return init_mi_tree(404, "No translation", 14);
00551 }
00552 LM_DBG("input %.*s with dpid %i => output %.*s\n",
00553 input.len, input.s, idp->dp_id, output.len, output.s);
00554
00555 rpl = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00556 if (rpl==0)
00557 goto error;
00558
00559 root= &rpl->node;
00560
00561 node = add_mi_node_child(root, 0, "Output", 6, output.s, output.len );
00562 if( node == NULL)
00563 goto error;
00564
00565 node = add_mi_node_child(root, 0, "ATTRIBUTES", 10, attrs.s, attrs.len);
00566 if( node == NULL)
00567 goto error;
00568
00569 return rpl;
00570
00571 error:
00572 if(rpl)
00573 free_mi_tree(rpl);
00574 return 0;
00575 }
00576
00577 static const char* dialplan_rpc_reload_doc[2] = {
00578 "Reload dialplan table from database",
00579 0
00580 };
00581
00582
00583
00584
00585
00586 static void dialplan_rpc_reload(rpc_t* rpc, void* ctx)
00587 {
00588 if (dp_connect_db() < 0) {
00589 LM_ERR("failed to reload rules fron database (db connect)\n");
00590 rpc->fault(ctx, 500, "DB Connection Error");
00591 return;
00592 }
00593
00594 if(dp_load_db() != 0){
00595 LM_ERR("failed to reload rules fron database (db load)\n");
00596 dp_disconnect_db();
00597 rpc->fault(ctx, 500, "Dialplan Reload Failed");
00598 return;
00599 }
00600
00601 dp_disconnect_db();
00602 return;
00603 }
00604
00605
00606
00607 static const char* dialplan_rpc_translate_doc[2] = {
00608 "Perform dialplan translation",
00609 0
00610 };
00611
00612
00613
00614
00615
00616 static void dialplan_rpc_translate(rpc_t* rpc, void* ctx)
00617 {
00618 dpl_id_p idp;
00619 str input;
00620 int dpid;
00621 str attrs = {"", 0};
00622 str output = {0, 0};
00623 void* th;
00624
00625 if (rpc->scan(ctx, "dS", &dpid, &input) < 2)
00626 {
00627 rpc->fault(ctx, 500, "Invalid parameters");
00628 return;
00629 }
00630
00631 if ((idp = select_dpid(dpid)) == 0 ){
00632 LM_ERR("no information available for dpid %i\n", dpid);
00633 rpc->fault(ctx, 500, "Dialplan ID not matched");
00634 return;
00635 }
00636
00637 if(input.s == NULL || input.len== 0) {
00638 LM_ERR("empty input parameter\n");
00639 rpc->fault(ctx, 500, "Empty input parameter");
00640 return;
00641 }
00642
00643 LM_DBG("trying to translate %.*s with dpid %i\n",
00644 input.len, input.s, idp->dp_id);
00645 if (translate(NULL, input, &output, idp, &attrs)!=0){
00646 LM_DBG("could not translate %.*s with dpid %i\n",
00647 input.len, input.s, idp->dp_id);
00648 rpc->fault(ctx, 500, "No translation");
00649 return;
00650 }
00651 LM_DBG("input %.*s with dpid %i => output %.*s\n",
00652 input.len, input.s, idp->dp_id, output.len, output.s);
00653
00654 if (rpc->add(ctx, "{", &th) < 0)
00655 {
00656 rpc->fault(ctx, 500, "Internal error creating rpc");
00657 return;
00658 }
00659 if(rpc->struct_add(th, "SS",
00660 "Output", &output,
00661 "Attributes", &attrs)<0)
00662 {
00663 rpc->fault(ctx, 500, "Internal error creating rpc");
00664 return;
00665 }
00666
00667 return;
00668 }
00669
00670
00671 rpc_export_t dialplan_rpc_list[] = {
00672 {"dialplan.reload", dialplan_rpc_reload,
00673 dialplan_rpc_reload_doc, 0},
00674 {"dialplan.dump", dialplan_rpc_translate,
00675 dialplan_rpc_translate_doc, 0},
00676 {0, 0, 0, 0}
00677 };
00678
00679 static int dialplan_init_rpc(void)
00680 {
00681 if (rpc_register_array(dialplan_rpc_list)!=0)
00682 {
00683 LM_ERR("failed to register RPC commands\n");
00684 return -1;
00685 }
00686 return 0;
00687 }