dialplan.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2007-2008 Voice Sistem SRL
  5. *
  6. * Copyright (C) 2008 Juha Heinanen
  7. *
  8. * This file is part of SIP-router, a free SIP server.
  9. *
  10. * SIP-router is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version
  14. *
  15. * SIP-router is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * History:
  25. * --------
  26. * 2007-08-01 initial version (ancuta onofrei)
  27. * 2008-10-09 module is now using pcre regexp lib (juha heinanen)
  28. */
  29. /*!
  30. * \file
  31. * \brief SIP-router dialplan :: Module interface
  32. * \ingroup dialplan
  33. * Module: \ref dialplan
  34. */
  35. /*! \defgroup dialplan SIP-router dialplan transformations module
  36. *
  37. */
  38. #include <string.h>
  39. #include <stdlib.h>
  40. #include <stdio.h>
  41. #include <math.h>
  42. #include "../../sr_module.h"
  43. #include "../../lib/srdb1/db.h"
  44. #include "../../dprint.h"
  45. #include "../../error.h"
  46. #include "../../ut.h"
  47. #include "../../action.h"
  48. #include "../../pvar.h"
  49. #include "../../dset.h"
  50. #include "../../mem/mem.h"
  51. #include "../../lib/kmi/mi.h"
  52. #include "../../parser/parse_to.h"
  53. #include "../../rpc.h"
  54. #include "../../rpc_lookup.h"
  55. #include "../../lvalue.h"
  56. #include "dialplan.h"
  57. #include "dp_db.h"
  58. MODULE_VERSION
  59. #define DEFAULT_PARAM "$ruri.user"
  60. static int mod_init(void);
  61. static int child_init(int rank);
  62. static void mod_destroy();
  63. static int mi_child_init();
  64. static int dialplan_init_rpc(void);
  65. static struct mi_root * mi_reload_rules(struct mi_root *cmd_tree,void *param);
  66. static struct mi_root * mi_translate(struct mi_root *cmd_tree, void *param);
  67. static int dp_translate_f(struct sip_msg* msg, char* str1, char* str2);
  68. static int dp_trans_fixup(void ** param, int param_no);
  69. str attr_pvar_s = STR_NULL;
  70. pv_spec_t * attr_pvar = NULL;
  71. str default_param_s = str_init(DEFAULT_PARAM);
  72. dp_param_p default_par2 = NULL;
  73. int dp_fetch_rows = 1000;
  74. static param_export_t mod_params[]={
  75. { "db_url", PARAM_STR, &dp_db_url },
  76. { "table_name", PARAM_STR, &dp_table_name },
  77. { "dpid_col", PARAM_STR, &dpid_column },
  78. { "pr_col", PARAM_STR, &pr_column },
  79. { "match_op_col", PARAM_STR, &match_op_column },
  80. { "match_exp_col", PARAM_STR, &match_exp_column },
  81. { "match_len_col", PARAM_STR, &match_len_column },
  82. { "subst_exp_col", PARAM_STR, &subst_exp_column },
  83. { "repl_exp_col", PARAM_STR, &repl_exp_column },
  84. { "attrs_col", PARAM_STR, &attrs_column },
  85. { "attrs_pvar", PARAM_STR, &attr_pvar_s},
  86. { "fetch_rows", INT_PARAM, &dp_fetch_rows},
  87. {0,0,0}
  88. };
  89. static mi_export_t mi_cmds[] = {
  90. { "dp_reload", mi_reload_rules, MI_NO_INPUT_FLAG, 0, mi_child_init},
  91. { "dp_translate", mi_translate, 0, 0, 0},
  92. { 0, 0, 0, 0, 0}
  93. };
  94. static cmd_export_t cmds[]={
  95. {"dp_translate",(cmd_function)dp_translate_f, 2, dp_trans_fixup, 0,
  96. ANY_ROUTE},
  97. {"dp_translate",(cmd_function)dp_translate_f, 1, dp_trans_fixup, 0,
  98. ANY_ROUTE},
  99. {0,0,0,0,0,0}
  100. };
  101. struct module_exports exports= {
  102. "dialplan", /* module's name */
  103. DEFAULT_DLFLAGS, /* dlopen flags */
  104. cmds, /* exported functions */
  105. mod_params, /* param exports */
  106. 0, /* exported statistics */
  107. mi_cmds, /* exported MI functions */
  108. 0, /* exported pseudo-variables */
  109. 0, /* additional processes */
  110. mod_init, /* module initialization function */
  111. 0, /* reply processing function */
  112. mod_destroy,
  113. child_init /* per-child init function */
  114. };
  115. static int mod_init(void)
  116. {
  117. if(register_mi_mod(exports.name, mi_cmds)!=0)
  118. {
  119. LM_ERR("failed to register MI commands\n");
  120. return -1;
  121. }
  122. if(dialplan_init_rpc()!=0)
  123. {
  124. LM_ERR("failed to register RPC commands\n");
  125. return -1;
  126. }
  127. LM_DBG("db_url=%s/%d/%p\n", ZSW(dp_db_url.s), dp_db_url.len,dp_db_url.s);
  128. if(attr_pvar_s.s && attr_pvar_s.len>0) {
  129. attr_pvar = pv_cache_get(&attr_pvar_s);
  130. if( (attr_pvar==NULL) ||
  131. ((attr_pvar->type != PVT_AVP) &&
  132. (attr_pvar->type != PVT_XAVP) &&
  133. (attr_pvar->type!=PVT_SCRIPTVAR))) {
  134. LM_ERR("invalid pvar name\n");
  135. return -1;
  136. }
  137. }
  138. default_par2 = (dp_param_p)shm_malloc(sizeof(dp_param_t));
  139. if(default_par2 == NULL){
  140. LM_ERR("no shm more memory\n");
  141. return -1;
  142. }
  143. memset(default_par2, 0, sizeof(dp_param_t));
  144. /* A.Spiridonov: Some weird sections with default_param processing */
  145. default_param_s.len = strlen(default_param_s.s);
  146. default_par2->v.sp[0] = pv_cache_get(&default_param_s);
  147. if (default_par2->v.sp[0]==NULL) {
  148. LM_ERR("input pv is invalid\n");
  149. return -1;
  150. }
  151. default_param_s.len = strlen(default_param_s.s);
  152. default_par2->v.sp[1] = pv_cache_get(&default_param_s);
  153. if (default_par2->v.sp[1]==NULL) {
  154. LM_ERR("output pv is invalid\n");
  155. return -1;
  156. }
  157. /* End of weird sections */
  158. if(dp_fetch_rows<=0)
  159. dp_fetch_rows = 1000;
  160. if(init_data() != 0) {
  161. LM_ERR("could not initialize data\n");
  162. return -1;
  163. }
  164. return 0;
  165. }
  166. static int child_init(int rank)
  167. {
  168. return 0;
  169. }
  170. static void mod_destroy(void)
  171. {
  172. /*destroy shared memory*/
  173. if(default_par2){
  174. shm_free(default_par2);
  175. default_par2 = NULL;
  176. }
  177. destroy_data();
  178. }
  179. static int mi_child_init(void)
  180. {
  181. return 0;
  182. }
  183. static int dp_get_ivalue(struct sip_msg* msg, dp_param_p dp, int *val)
  184. {
  185. pv_value_t value;
  186. if(dp->type==DP_VAL_INT) {
  187. *val = dp->v.id;
  188. LM_DBG("dpid is %d from constant argument\n", *val);
  189. return 0;
  190. }
  191. LM_DBG("searching %d\n",dp->v.sp[0]->type);
  192. if( pv_get_spec_value( msg, dp->v.sp[0], &value)!=0
  193. || value.flags&(PV_VAL_NULL|PV_VAL_EMPTY) || !(value.flags&PV_VAL_INT)) {
  194. LM_ERR("no AVP, XAVP or SCRIPTVAR found (error in scripts)\n");
  195. return -1;
  196. }
  197. *val = value.ri;
  198. LM_DBG("dpid is %d from pv argument\n", *val);
  199. return 0;
  200. }
  201. static int dp_get_svalue(struct sip_msg * msg, pv_spec_t *spec, str* val)
  202. {
  203. pv_value_t value;
  204. LM_DBG("searching %d \n", spec->type);
  205. if ( pv_get_spec_value(msg,spec,&value)!=0 || value.flags&PV_VAL_NULL
  206. || value.flags&PV_VAL_EMPTY || !(value.flags&PV_VAL_STR)){
  207. LM_ERR("no AVP, XAVP or SCRIPTVAR found (error in scripts)\n");
  208. return -1;
  209. }
  210. *val = value.rs;
  211. return 0;
  212. }
  213. static int dp_update(struct sip_msg * msg, pv_spec_t * src, pv_spec_t * dest,
  214. str * repl, str * attrs)
  215. {
  216. int no_change;
  217. pv_value_t val;
  218. memset(&val, 0, sizeof(pv_value_t));
  219. val.flags = PV_VAL_STR;
  220. no_change = (dest==NULL) || (dest->type == PVT_NONE) || (!repl->s) || (!repl->len);
  221. if (no_change)
  222. goto set_attr_pvar;
  223. val.rs = *repl;
  224. if(dest->setf(msg, &dest->pvp, (int)EQ_T, &val)<0)
  225. {
  226. LM_ERR("setting dst pseudo-variable failed\n");
  227. return -1;
  228. }
  229. if(is_route_type(FAILURE_ROUTE)
  230. && (dest->type==PVT_RURI || dest->type==PVT_RURI_USERNAME)) {
  231. if (append_branch(msg, 0, 0, 0, Q_UNSPECIFIED, 0, 0, 0, 0, 0, 0) != 1) {
  232. LM_ERR("append_branch action failed\n");
  233. return -1;
  234. }
  235. }
  236. set_attr_pvar:
  237. if(!attr_pvar)
  238. return 0;
  239. val.rs = *attrs;
  240. if(attr_pvar->setf(msg, &attr_pvar->pvp, (int)EQ_T, &val)<0)
  241. {
  242. LM_ERR("setting attr pseudo-variable failed\n");
  243. return -1;
  244. }
  245. return 0;
  246. }
  247. static int dp_translate_f(struct sip_msg* msg, char* str1, char* str2)
  248. {
  249. int dpid;
  250. str input, output;
  251. dpl_id_p idp;
  252. dp_param_p id_par, repl_par;
  253. str attrs, * attrs_par;
  254. if(!msg)
  255. return -1;
  256. /*verify first param's value*/
  257. id_par = (dp_param_p) str1;
  258. if (dp_get_ivalue(msg, id_par, &dpid) != 0){
  259. LM_ERR("no dpid value\n");
  260. return -1;
  261. }
  262. if ((idp = select_dpid(dpid)) ==0 ){
  263. LM_DBG("no information available for dpid %i\n", dpid);
  264. return -2;
  265. }
  266. repl_par = (str2!=NULL)? ((dp_param_p)str2):default_par2;
  267. if (dp_get_svalue(msg, repl_par->v.sp[0], &input)!=0){
  268. LM_ERR("invalid param 2\n");
  269. return -1;
  270. }
  271. LM_DBG("input is %.*s\n", input.len, input.s);
  272. attrs_par = (!attr_pvar)?NULL:&attrs;
  273. if (translate(msg, input, &output, idp, attrs_par)!=0){
  274. LM_DBG("could not translate %.*s "
  275. "with dpid %i\n", input.len, input.s, idp->dp_id);
  276. return -1;
  277. }
  278. LM_DBG("input %.*s with dpid %i => output %.*s\n",
  279. input.len, input.s, idp->dp_id, output.len, output.s);
  280. /*set the output*/
  281. if (dp_update(msg, repl_par->v.sp[0], repl_par->v.sp[1],
  282. &output, attrs_par) !=0){
  283. LM_ERR("cannot set the output\n");
  284. return -1;
  285. }
  286. return 1;
  287. }
  288. #define verify_par_type(_par_no, _spec)\
  289. do{\
  290. if( ((_par_no == 1) \
  291. && (_spec->type != PVT_AVP) && (_spec->type != PVT_XAVP) && \
  292. (_spec->type!=PVT_SCRIPTVAR) )\
  293. ||((_par_no == 2) \
  294. && (_spec->type != PVT_AVP) && (_spec->type != PVT_XAVP) && \
  295. (_spec->type!=PVT_SCRIPTVAR) \
  296. && (_spec->type!=PVT_RURI) && (_spec->type!=PVT_RURI_USERNAME))){\
  297. \
  298. LM_ERR("Unsupported Parameter TYPE[%d]\n", _spec->type);\
  299. return E_UNSPEC;\
  300. }\
  301. }while(0);
  302. /* first param: DPID: type: INT, AVP, XAVP, SVAR
  303. * second param: SRC type: any psedo variable type
  304. * second param: DST type: RURI, RURI_USERNAME, AVP, XAVP, SVAR, N/A
  305. * default value for the second param: $ru.user/$ru.user
  306. */
  307. static int dp_trans_fixup(void ** param, int param_no){
  308. int dpid;
  309. dp_param_p dp_par= NULL;
  310. char *p, *s=NULL;
  311. str lstr;
  312. if(param_no!=1 && param_no!=2)
  313. return 0;
  314. p = (char*)*param;
  315. if(!p || (*p == '\0')){
  316. LM_DBG("null param %i\n", param_no);
  317. return E_CFG;
  318. }
  319. LM_DBG("param_no is %i\n", param_no);
  320. dp_par = (dp_param_p)pkg_malloc(sizeof(dp_param_t));
  321. if(dp_par == NULL){
  322. LM_ERR("no more pkg memory\n");
  323. return E_OUT_OF_MEM;
  324. }
  325. memset(dp_par, 0, sizeof(dp_param_t));
  326. if(param_no == 1) {
  327. if(*p != '$') {
  328. dp_par->type = DP_VAL_INT;
  329. lstr.s = *param; lstr.len = strlen(*param);
  330. if(str2sint(&lstr, &dpid) != 0) {
  331. LM_ERR("bad number <%s>\n",(char *)(*param));
  332. pkg_free(dp_par);
  333. return E_CFG;
  334. }
  335. dp_par->type = DP_VAL_INT;
  336. dp_par->v.id = dpid;
  337. }else{
  338. lstr.s = p; lstr.len = strlen(p);
  339. dp_par->v.sp[0] = pv_cache_get(&lstr);
  340. if (dp_par->v.sp[0]==NULL)
  341. goto error;
  342. verify_par_type(param_no, dp_par->v.sp[0]);
  343. dp_par->type = DP_VAL_SPEC;
  344. }
  345. } else {
  346. if (((s = strchr(p, '/')) != 0) && (*(s+1)=='\0'))
  347. goto error;
  348. if (s != 0) {
  349. *s = '\0'; s++;
  350. }
  351. lstr.s = p; lstr.len = strlen(p);
  352. dp_par->v.sp[0] = pv_cache_get(&lstr);
  353. if(dp_par->v.sp[0]==NULL)
  354. goto error;
  355. if (s != 0) {
  356. lstr.s = s; lstr.len = strlen(s);
  357. dp_par->v.sp[1] = pv_cache_get(&lstr);
  358. if (dp_par->v.sp[1]==NULL)
  359. goto error;
  360. verify_par_type(param_no, dp_par->v.sp[1]);
  361. }
  362. dp_par->type = DP_VAL_SPEC;
  363. }
  364. *param = (void *)dp_par;
  365. return 0;
  366. error:
  367. LM_ERR("failed to parse param %i\n", param_no);
  368. return E_INVALID_PARAMS;
  369. }
  370. static struct mi_root * mi_reload_rules(struct mi_root *cmd_tree, void *param)
  371. {
  372. struct mi_root* rpl_tree= NULL;
  373. if (dp_connect_db() < 0) {
  374. LM_ERR("failed to reload rules fron database (db connect)\n");
  375. return 0;
  376. }
  377. if(dp_load_db() != 0){
  378. LM_ERR("failed to reload rules fron database (db load)\n");
  379. dp_disconnect_db();
  380. return 0;
  381. }
  382. dp_disconnect_db();
  383. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  384. if (rpl_tree==0)
  385. return 0;
  386. return rpl_tree;
  387. }
  388. /*
  389. * mi cmd: dp_translate
  390. * <dialplan id>
  391. * <input>
  392. * * */
  393. static struct mi_root * mi_translate(struct mi_root *cmd, void *param)
  394. {
  395. struct mi_root* rpl= NULL;
  396. struct mi_node* root, *node;
  397. dpl_id_p idp;
  398. str dpid_str;
  399. str input;
  400. int dpid;
  401. str attrs;
  402. str output= {0, 0};
  403. node = cmd->node.kids;
  404. if(node == NULL)
  405. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  406. /* Get the id parameter */
  407. dpid_str = node->value;
  408. if(dpid_str.s == NULL || dpid_str.len== 0) {
  409. LM_ERR( "empty idp parameter\n");
  410. return init_mi_tree(404, "Empty id parameter", 18);
  411. }
  412. if(str2sint(&dpid_str, &dpid) != 0) {
  413. LM_ERR("Wrong id parameter - should be an integer\n");
  414. return init_mi_tree(404, "Wrong id parameter", 18);
  415. }
  416. if ((idp = select_dpid(dpid)) ==0 ){
  417. LM_ERR("no information available for dpid %i\n", dpid);
  418. return init_mi_tree(404, "No information available for dpid", 33);
  419. }
  420. node = node->next;
  421. if(node == NULL)
  422. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  423. if(node->next!= NULL)
  424. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  425. input= node->value;
  426. if(input.s == NULL || input.len== 0) {
  427. LM_ERR( "empty input parameter\n");
  428. return init_mi_tree(404, "Empty input parameter", 21);
  429. }
  430. LM_DBG("trying to translate %.*s with dpid %i\n",
  431. input.len, input.s, idp->dp_id);
  432. if (translate(NULL, input, &output, idp, &attrs)!=0){
  433. LM_DBG("could not translate %.*s with dpid %i\n",
  434. input.len, input.s, idp->dp_id);
  435. return init_mi_tree(404, "No translation", 14);
  436. }
  437. LM_DBG("input %.*s with dpid %i => output %.*s\n",
  438. input.len, input.s, idp->dp_id, output.len, output.s);
  439. rpl = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  440. if (rpl==0)
  441. goto error;
  442. root= &rpl->node;
  443. node = add_mi_node_child(root, 0, "Output", 6, output.s, output.len );
  444. if( node == NULL)
  445. goto error;
  446. node = add_mi_node_child(root, 0, "ATTRIBUTES", 10, attrs.s, attrs.len);
  447. if( node == NULL)
  448. goto error;
  449. return rpl;
  450. error:
  451. if(rpl)
  452. free_mi_tree(rpl);
  453. return 0;
  454. }
  455. static const char* dialplan_rpc_reload_doc[2] = {
  456. "Reload dialplan table from database",
  457. 0
  458. };
  459. /*
  460. * RPC command to reload dialplan table
  461. */
  462. static void dialplan_rpc_reload(rpc_t* rpc, void* ctx)
  463. {
  464. if (dp_connect_db() < 0) {
  465. LM_ERR("failed to reload rules fron database (db connect)\n");
  466. rpc->fault(ctx, 500, "DB Connection Error");
  467. return;
  468. }
  469. if(dp_load_db() != 0){
  470. LM_ERR("failed to reload rules fron database (db load)\n");
  471. dp_disconnect_db();
  472. rpc->fault(ctx, 500, "Dialplan Reload Failed");
  473. return;
  474. }
  475. dp_disconnect_db();
  476. return;
  477. }
  478. static const char* dialplan_rpc_translate_doc[2] = {
  479. "Perform dialplan translation",
  480. 0
  481. };
  482. /*
  483. * RPC command to perform dialplan translation
  484. */
  485. static void dialplan_rpc_translate(rpc_t* rpc, void* ctx)
  486. {
  487. dpl_id_p idp;
  488. str input;
  489. int dpid;
  490. str attrs = {"", 0};
  491. str output = {0, 0};
  492. void* th;
  493. if (rpc->scan(ctx, "dS", &dpid, &input) < 2)
  494. {
  495. rpc->fault(ctx, 500, "Invalid parameters");
  496. return;
  497. }
  498. if ((idp = select_dpid(dpid)) == 0 ){
  499. LM_ERR("no information available for dpid %i\n", dpid);
  500. rpc->fault(ctx, 500, "Dialplan ID not matched");
  501. return;
  502. }
  503. if(input.s == NULL || input.len== 0) {
  504. LM_ERR("empty input parameter\n");
  505. rpc->fault(ctx, 500, "Empty input parameter");
  506. return;
  507. }
  508. LM_DBG("trying to translate %.*s with dpid %i\n",
  509. input.len, input.s, idp->dp_id);
  510. if (translate(NULL, input, &output, idp, &attrs)!=0){
  511. LM_DBG("could not translate %.*s with dpid %i\n",
  512. input.len, input.s, idp->dp_id);
  513. rpc->fault(ctx, 500, "No translation");
  514. return;
  515. }
  516. LM_DBG("input %.*s with dpid %i => output %.*s\n",
  517. input.len, input.s, idp->dp_id, output.len, output.s);
  518. if (rpc->add(ctx, "{", &th) < 0)
  519. {
  520. rpc->fault(ctx, 500, "Internal error creating rpc");
  521. return;
  522. }
  523. if(rpc->struct_add(th, "SS",
  524. "Output", &output,
  525. "Attributes", &attrs)<0)
  526. {
  527. rpc->fault(ctx, 500, "Internal error creating rpc");
  528. return;
  529. }
  530. return;
  531. }
  532. rpc_export_t dialplan_rpc_list[] = {
  533. {"dialplan.reload", dialplan_rpc_reload,
  534. dialplan_rpc_reload_doc, 0},
  535. {"dialplan.translate", dialplan_rpc_translate,
  536. dialplan_rpc_translate_doc, 0},
  537. {0, 0, 0, 0}
  538. };
  539. static int dialplan_init_rpc(void)
  540. {
  541. if (rpc_register_array(dialplan_rpc_list)!=0)
  542. {
  543. LM_ERR("failed to register RPC commands\n");
  544. return -1;
  545. }
  546. return 0;
  547. }