utils.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. /*
  2. * utils Module
  3. *
  4. * Copyright (C) 2008 Juha Heinanen
  5. * Copyright (C) 2009 1&1 Internet AG
  6. *
  7. * This file is part of Kamailio, a free SIP server.
  8. *
  9. * Kamailio is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version
  13. *
  14. * Kamailio is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. *
  23. * History:
  24. * -------
  25. * 2008-11-24: Introduced utils module and its first function: http_query.
  26. *
  27. */
  28. /*! \file
  29. * \brief SIP-router utils :: Module core
  30. * \ingroup utils
  31. */
  32. /*! \defgroup Utils SIP-router :: Various utilities
  33. *
  34. */
  35. #include <curl/curl.h>
  36. #include "../../mod_fix.h"
  37. #include "../../sr_module.h"
  38. #include "../../ut.h"
  39. #include "../../forward.h"
  40. #include "../../resolve.h"
  41. #include "../../locking.h"
  42. #include "../../script_cb.h"
  43. #include "../../mem/shm_mem.h"
  44. #include "../../lib/srdb1/db.h"
  45. #include "functions.h"
  46. #include "conf.h"
  47. #include "xcap_auth.h"
  48. MODULE_VERSION
  49. #define XCAP_TABLE_VERSION 3
  50. /* Module parameter variables */
  51. int http_query_timeout = 4;
  52. static int forward_active = 0;
  53. static int mp_max_id = 0;
  54. static char* mp_switch = "";
  55. static char* mp_filter = "";
  56. static char* mp_proxy = "";
  57. str xcap_table= str_init("xcap");
  58. str pres_db_url = {0, 0};
  59. /* lock for configuration access */
  60. static gen_lock_t *conf_lock = NULL;
  61. /* FIFO interface functions */
  62. static struct mi_root* forward_fifo_list(struct mi_root* cmd_tree, void *param);
  63. static struct mi_root* forward_fifo_switch(struct mi_root* cmd_tree, void* param);
  64. static struct mi_root* forward_fifo_filter(struct mi_root* cmd_tree, void* param);
  65. static struct mi_root* forward_fifo_proxy(struct mi_root* cmd_tree, void* param);
  66. /* Database connection */
  67. db1_con_t *pres_dbh = NULL;
  68. db_func_t pres_dbf;
  69. /* Module management function prototypes */
  70. static int mod_init(void);
  71. static int child_init(int);
  72. static void destroy(void);
  73. /* Fixup functions to be defined later */
  74. static int fixup_http_query(void** param, int param_no);
  75. static int fixup_free_http_query(void** param, int param_no);
  76. /* forward function */
  77. int utils_forward(struct sip_msg *msg, int id, int proto);
  78. /* Exported functions */
  79. static cmd_export_t cmds[] = {
  80. {"http_query", (cmd_function)http_query, 2, fixup_http_query,
  81. fixup_free_http_query,
  82. REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
  83. {"xcap_auth_status", (cmd_function)xcap_auth_status, 2, fixup_pvar_pvar,
  84. fixup_free_pvar_pvar, REQUEST_ROUTE},
  85. {"is_int", (cmd_function)is_int, 1, fixup_pvar_null, fixup_free_pvar_null,
  86. REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
  87. {0, 0, 0, 0, 0, 0}
  88. };
  89. /* Exported parameters */
  90. static param_export_t params[] = {
  91. {"pres_db_url", STR_PARAM, &pres_db_url.s},
  92. {"xcap_table", STR_PARAM, &xcap_table.s},
  93. {"http_query_timeout", INT_PARAM, &http_query_timeout},
  94. {"forward_active", INT_PARAM, &forward_active},
  95. {0, 0, 0}
  96. };
  97. static mi_export_t mi_cmds[] = {
  98. { "forward_list", forward_fifo_list, MI_NO_INPUT_FLAG, 0, 0 },
  99. { "forward_switch", forward_fifo_switch, 0, 0, 0 },
  100. { "forward_filter", forward_fifo_filter, 0, 0, 0 },
  101. { "forward_proxy", forward_fifo_proxy, 0, 0, 0 },
  102. { 0, 0, 0, 0, 0}
  103. };
  104. /* Module interface */
  105. struct module_exports exports = {
  106. "utils",
  107. DEFAULT_DLFLAGS, /* dlopen flags */
  108. cmds, /* Exported functions */
  109. params, /* Exported parameters */
  110. 0, /* exported statistics */
  111. mi_cmds, /* exported MI functions */
  112. 0, /* exported pseudo-variables */
  113. 0, /* extra processes */
  114. mod_init, /* module initialization function */
  115. 0, /* response function*/
  116. destroy, /* destroy function */
  117. child_init /* per-child init function */
  118. };
  119. static int init_shmlock(void)
  120. {
  121. conf_lock = lock_alloc();
  122. if (conf_lock == NULL) {
  123. LM_CRIT("cannot allocate memory for lock.\n");
  124. return -1;
  125. }
  126. if (lock_init(conf_lock) == 0) {
  127. LM_CRIT("cannot initialize lock.\n");
  128. return -1;
  129. }
  130. return 0;
  131. }
  132. static int pre_script_filter(struct sip_msg *msg, unsigned int flags, void *unused)
  133. {
  134. /* use id 0 for pre script callback */
  135. utils_forward(msg, 0, PROTO_UDP);
  136. /* always return 1 so that routing skript is called for msg */
  137. return 1;
  138. }
  139. static void destroy_shmlock(void)
  140. {
  141. if (conf_lock) {
  142. lock_destroy(conf_lock);
  143. lock_dealloc((void *)conf_lock);
  144. conf_lock = NULL;
  145. }
  146. }
  147. static void pres_db_close(void) {
  148. if (pres_dbh) {
  149. pres_dbf.close(pres_dbh);
  150. pres_dbh = NULL;
  151. }
  152. }
  153. static int pres_db_init(void) {
  154. if (!pres_db_url.s || !pres_db_url.len) {
  155. LM_INFO("xcap_auth_status function is disabled\n");
  156. return 0;
  157. }
  158. if (db_bind_mod(&pres_db_url, &pres_dbf) < 0) {
  159. LM_ERR("can't bind database module\n");
  160. return -1;
  161. }
  162. if ((pres_dbh = pres_dbf.init(&pres_db_url)) == NULL) {
  163. LM_ERR("can't connect to database\n");
  164. return -1;
  165. }
  166. if (db_check_table_version(&pres_dbf, pres_dbh, &xcap_table,
  167. XCAP_TABLE_VERSION) < 0) {
  168. LM_ERR("during table version check\n");
  169. pres_db_close();
  170. return -1;
  171. }
  172. pres_db_close();
  173. return 0;
  174. }
  175. static int pres_db_open(void) {
  176. if (!pres_db_url.s || !pres_db_url.len) {
  177. return 0;
  178. }
  179. if (pres_dbh) {
  180. pres_dbf.close(pres_dbh);
  181. }
  182. if ((pres_dbh = pres_dbf.init(&pres_db_url)) == NULL) {
  183. LM_ERR("can't connect to database\n");
  184. return -1;
  185. }
  186. if (pres_dbf.use_table(pres_dbh, &xcap_table) < 0) {
  187. LM_ERR("in use_table: %.*s\n", xcap_table.len, xcap_table.s);
  188. return -1;
  189. }
  190. return 0;
  191. }
  192. /* Module initialization function */
  193. static int mod_init(void)
  194. {
  195. if(register_mi_mod(exports.name, mi_cmds)!=0)
  196. {
  197. LM_ERR("failed to register MI commands\n");
  198. return -1;
  199. }
  200. /* Initialize curl */
  201. if (curl_global_init(CURL_GLOBAL_ALL)) {
  202. LM_ERR("curl_global_init failed\n");
  203. return -1;
  204. }
  205. if (init_shmlock() != 0) {
  206. LM_CRIT("cannot initialize shmlock.\n");
  207. return -1;
  208. }
  209. if (conf_init(mp_max_id) < 0) {
  210. LM_CRIT("cannot initialize configuration.\n");
  211. return -1;
  212. }
  213. /* read module parameters and update configuration structure */
  214. if (conf_parse_proxy(mp_proxy) < 0) {
  215. LM_CRIT("cannot parse proxy module parameter.\n");
  216. return -1;
  217. }
  218. if (conf_parse_filter(mp_filter) < 0) {
  219. LM_CRIT("cannot parse filter module parameter.\n");
  220. return -1;
  221. }
  222. if (conf_parse_switch(mp_switch) < 0) {
  223. LM_CRIT("cannot parse switch module parameter.\n");
  224. return -1;
  225. }
  226. if (forward_active == 1) {
  227. /* register callback for id 0 */
  228. if (register_script_cb(pre_script_filter, PRE_SCRIPT_CB|ONREPLY_CB, 0) < 0) {
  229. LM_CRIT("cannot register script callback for requests.\n");
  230. return -1;
  231. }
  232. if (register_script_cb(pre_script_filter, PRE_SCRIPT_CB|ONREPLY_CB, 0) < 0) {
  233. LM_CRIT("cannot register script callback for replies.\n");
  234. return -1;
  235. }
  236. } else {
  237. LM_INFO("forward functionality disabled");
  238. }
  239. /* presence database */
  240. pres_db_url.len = pres_db_url.s ? strlen(pres_db_url.s) : 0;
  241. LM_DBG("pres_db_url=%s/%d/%p\n", ZSW(pres_db_url.s), pres_db_url.len,
  242. pres_db_url.s);
  243. xcap_table.len = xcap_table.s ? strlen(xcap_table.s) : 0;
  244. if(pres_db_init() < 0) {
  245. return -1;
  246. }
  247. return 0;
  248. }
  249. /* Child initialization function */
  250. static int child_init(int rank)
  251. {
  252. if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
  253. return 0; /* do nothing for the main process */
  254. return pres_db_open();
  255. }
  256. static void destroy(void)
  257. {
  258. /* Cleanup curl */
  259. curl_global_cleanup();
  260. /* Cleanup forward */
  261. conf_destroy();
  262. destroy_shmlock();
  263. /* Close pres db */
  264. pres_db_close();
  265. }
  266. /* Fixup functions */
  267. /*
  268. * Fix http_query params: url (string that may contain pvars) and
  269. * result (writable pvar).
  270. */
  271. static int fixup_http_query(void** param, int param_no)
  272. {
  273. if (param_no == 1) {
  274. return fixup_spve_null(param, 1);
  275. }
  276. if (param_no == 2) {
  277. if (fixup_pvar_null(param, 1) != 0) {
  278. LM_ERR("failed to fixup result pvar\n");
  279. return -1;
  280. }
  281. if (((pv_spec_t *)(*param))->setf == NULL) {
  282. LM_ERR("result pvar is not writeble\n");
  283. return -1;
  284. }
  285. return 0;
  286. }
  287. LM_ERR("invalid parameter number <%d>\n", param_no);
  288. return -1;
  289. }
  290. /*
  291. * Free http_query params.
  292. */
  293. static int fixup_free_http_query(void** param, int param_no)
  294. {
  295. if (param_no == 1) {
  296. LM_WARN("free function has not been defined for spve\n");
  297. return 0;
  298. }
  299. if (param_no == 2) {
  300. return fixup_free_pvar_null(param, 1);
  301. }
  302. LM_ERR("invalid parameter number <%d>\n", param_no);
  303. return -1;
  304. }
  305. /*!
  306. * \brief checks precondition, switch, filter and forwards msg if necessary
  307. * \param msg the message to be forwarded
  308. * \param id use configuration with this ID when checking switch, filter, proxy.
  309. * \param proto protocol to be used. Should be PROTO_UDP.
  310. * \return 0 on success, -1 otherwise
  311. */
  312. int utils_forward(struct sip_msg *msg, int id, int proto)
  313. {
  314. int ret = -1;
  315. struct dest_info dst;
  316. init_dest_info(&dst);
  317. dst.proto = proto;
  318. // critical section start:
  319. // avoids dirty reads when updating configuration.
  320. lock_get(conf_lock);
  321. struct proxy_l *proxy = conf_needs_forward(msg, id);
  322. if (proxy != NULL) {
  323. proxy2su(&dst.to, proxy);
  324. if (forward_request(msg, NULL, 0, &dst) < 0){
  325. LM_ERR("could not forward message\n");
  326. }
  327. ret = 0;
  328. }
  329. // critical section end
  330. lock_release(conf_lock);
  331. return ret;
  332. }
  333. /* FIFO functions */
  334. /*!
  335. * \brief fifo command for listing configuration
  336. * \return pointer to the mi_root on success, 0 otherwise
  337. */
  338. static struct mi_root* forward_fifo_list(struct mi_root* cmd_tree, void *param)
  339. {
  340. struct mi_node *node = NULL;
  341. struct mi_root * ret = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
  342. if(ret == NULL)
  343. return 0;
  344. node = addf_mi_node_child( &ret->node, 0, 0, 0, "Printing forwarding information:");
  345. if(node == NULL)
  346. goto error;
  347. // critical section start:
  348. // avoids dirty reads when updating configuration.
  349. lock_get(conf_lock);
  350. conf_show(ret);
  351. // critical section end
  352. lock_release(conf_lock);
  353. return ret;
  354. error:
  355. free_mi_tree(ret);
  356. return 0;
  357. }
  358. /*!
  359. * \brief fifo command for configuring switch
  360. * \return pointer to the mi_root on success, 0 otherwise
  361. */
  362. static struct mi_root* forward_fifo_switch(struct mi_root* cmd_tree, void* param)
  363. {
  364. struct mi_node *node = NULL;
  365. int result;
  366. node = cmd_tree->node.kids;
  367. if (node==NULL || node->next!=NULL || node->value.s==NULL)
  368. return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  369. // critical section start:
  370. // avoids dirty reads when updating configuration.
  371. lock_get(conf_lock);
  372. result = conf_parse_switch(node->value.s);
  373. // critical section end
  374. lock_release(conf_lock);
  375. if (result < 0) {
  376. LM_ERR("cannot parse parameter\n");
  377. return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
  378. }
  379. return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
  380. }
  381. /*!
  382. * \brief fifo command for configuring filter
  383. * \return pointer to the mi_root on success, 0 otherwise
  384. */
  385. static struct mi_root* forward_fifo_filter(struct mi_root* cmd_tree, void* param)
  386. {
  387. struct mi_node *node = NULL;
  388. int result;
  389. node = cmd_tree->node.kids;
  390. if (node==NULL || node->next!=NULL || node->value.s==NULL)
  391. return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  392. // critical section start:
  393. // avoids dirty reads when updating configuration.
  394. lock_get(conf_lock);
  395. result = conf_parse_filter(node->value.s);
  396. // critical section end
  397. lock_release(conf_lock);
  398. if (result < 0) {
  399. LM_ERR("cannot parse parameter\n");
  400. return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
  401. }
  402. return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
  403. }
  404. /*!
  405. * \brief fifo command for configuring proxy
  406. * \return pointer to the mi_root on success, 0 otherwise
  407. */
  408. static struct mi_root* forward_fifo_proxy(struct mi_root* cmd_tree, void* param)
  409. {
  410. struct mi_node *node = NULL;
  411. int result;
  412. node = cmd_tree->node.kids;
  413. if (node==NULL || node->next!=NULL || node->value.s==NULL)
  414. return init_mi_tree(400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  415. // critical section start:
  416. // avoids dirty reads when updating configuration.
  417. lock_get(conf_lock);
  418. result = conf_parse_proxy(node->value.s);
  419. // critical section end
  420. lock_release(conf_lock);
  421. if (result < 0) {
  422. LM_ERR("cannot parse parameter\n");
  423. return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
  424. }
  425. return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
  426. }