cfgutils.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2012 Edvina AB
  5. * Copyright (C) 2007 1&1 Internet AG
  6. * Copyright (C) 2007 BASIS AudioNet GmbH
  7. * Copyright (C) 2004 FhG
  8. * Copyright (C) 2005-2006 Voice Sistem S.R.L.
  9. *
  10. * This file is part of Kamailio, a free SIP server.
  11. *
  12. * Kamailio is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2 of the License, or
  15. * (at your option) any later version
  16. *
  17. * Kamailio is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  25. *
  26. * cfgutils module: random probability functions for Kamailio;
  27. * it provide functions to make a decision in the script
  28. * of the server based on a probability function.
  29. * The benefit of this module is the value of the probability function
  30. * can be manipulated by external applications such as web interface
  31. * or command line tools.
  32. * Furthermore it provides some functions to let the server wait a
  33. * specific time interval.
  34. *
  35. * gflags module: global flags; it keeps a bitmap of flags
  36. * in shared memory and may be used to change behaviour
  37. * of server based on value of the flags. E.g.,
  38. * if (is_gflag("1")) { t_relay_to_udp("10.0.0.1","5060"); }
  39. * else { t_relay_to_udp("10.0.0.2","5060"); }
  40. * The benefit of this module is the value of the switch flags
  41. * can be manipulated by external applications such as web interface
  42. * or command line tools.
  43. */
  44. /* FIFO action protocol names */
  45. #define FIFO_SET_PROB "rand_set_prob"
  46. #define FIFO_RESET_PROB "rand_reset_prob"
  47. #define FIFO_GET_PROB "rand_get_prob"
  48. #define FIFO_GET_HASH "get_config_hash"
  49. #define FIFO_CHECK_HASH "check_config_hash"
  50. /* flag buffer size for FIFO protocool */
  51. #define MAX_FLAG_LEN 12
  52. /* FIFO action protocol names for gflag functionality */
  53. #define FIFO_SET_GFLAG "set_gflag"
  54. #define FIFO_IS_GFLAG "is_gflag"
  55. #define FIFO_RESET_GFLAG "reset_gflag"
  56. #define FIFO_GET_GFLAGS "get_gflags"
  57. #include "../../sr_module.h"
  58. #include "../../error.h"
  59. #include "../../pvar.h"
  60. #include "../../ut.h"
  61. #include "../../mem/mem.h"
  62. #include "../../mem/shm_mem.h"
  63. #include "../../lib/kmi/mi.h"
  64. #include "../../mod_fix.h"
  65. #include "../../md5.h"
  66. #include "../../md5utils.h"
  67. #include "../../globals.h"
  68. #include "../../hashes.h"
  69. #include "../../locking.h"
  70. #include "../../route.h"
  71. #include <stdio.h>
  72. #include <stdlib.h>
  73. #include <sys/types.h>
  74. #include <sys/stat.h>
  75. #include <unistd.h>
  76. #include "api.h"
  77. MODULE_VERSION
  78. static int set_prob(struct sip_msg*, char *, char *);
  79. static int reset_prob(struct sip_msg*, char *, char *);
  80. static int get_prob(struct sip_msg*, char *, char *);
  81. static int rand_event(struct sip_msg*, char *, char *);
  82. static int m_sleep(struct sip_msg*, char *, char *);
  83. static int m_usleep(struct sip_msg*, char *, char *);
  84. static int dbg_abort(struct sip_msg*, char*,char*);
  85. static int dbg_pkg_status(struct sip_msg*, char*,char*);
  86. static int dbg_shm_status(struct sip_msg*, char*,char*);
  87. static int dbg_pkg_summary(struct sip_msg*, char*,char*);
  88. static int dbg_shm_summary(struct sip_msg*, char*,char*);
  89. static int w_route_exists(struct sip_msg*, char*);
  90. static int w_check_route_exists(struct sip_msg*, char*);
  91. static int set_gflag(struct sip_msg*, char *, char *);
  92. static int reset_gflag(struct sip_msg*, char *, char *);
  93. static int is_gflag(struct sip_msg*, char *, char *);
  94. static int cfg_lock(struct sip_msg*, char *, char *);
  95. static int cfg_unlock(struct sip_msg*, char *, char *);
  96. static struct mi_root* mi_set_prob(struct mi_root* cmd, void* param );
  97. static struct mi_root* mi_reset_prob(struct mi_root* cmd, void* param );
  98. static struct mi_root* mi_get_prob(struct mi_root* cmd, void* param );
  99. static struct mi_root* mi_get_hash(struct mi_root* cmd, void* param );
  100. static struct mi_root* mi_check_hash(struct mi_root* cmd, void* param );
  101. static struct mi_root* mi_set_gflag(struct mi_root* cmd, void* param );
  102. static struct mi_root* mi_reset_gflag(struct mi_root* cmd, void* param );
  103. static struct mi_root* mi_is_gflag(struct mi_root* cmd, void* param );
  104. static struct mi_root* mi_get_gflags(struct mi_root* cmd, void* param );
  105. static int pv_get_random_val(struct sip_msg *msg, pv_param_t *param,
  106. pv_value_t *res);
  107. static int fixup_prob( void** param, int param_no);
  108. static int fixup_gflags( void** param, int param_no);
  109. static int fixup_core_hash(void **param, int param_no);
  110. static int w_core_hash(struct sip_msg *msg, char *p1, char *p2, char *p3);
  111. int bind_cfgutils(cfgutils_api_t *api);
  112. static int mod_init(void);
  113. static void mod_destroy(void);
  114. static int initial_prob = 10;
  115. static int *probability = NULL;
  116. static char config_hash[MD5_LEN];
  117. static char* hash_file = NULL;
  118. static int initial_gflags=0;
  119. static unsigned int *gflags=0;
  120. static gen_lock_t *gflags_lock = NULL;
  121. static gen_lock_set_t *_cfg_lock_set = NULL;
  122. static unsigned int _cfg_lock_size = 0;
  123. static cmd_export_t cmds[]={
  124. {"rand_set_prob", /* action name as in scripts */
  125. (cmd_function)set_prob, /* C function name */
  126. 1, /* number of parameters */
  127. fixup_prob, 0, /* */
  128. /* can be applied to original/failed requests and replies */
  129. ANY_ROUTE},
  130. {"rand_reset_prob", (cmd_function)reset_prob, 0, 0, 0,
  131. ANY_ROUTE},
  132. {"rand_get_prob", (cmd_function)get_prob, 0, 0, 0,
  133. ANY_ROUTE},
  134. {"rand_event", (cmd_function)rand_event, 0, 0, 0,
  135. ANY_ROUTE},
  136. {"sleep", (cmd_function)m_sleep, 1, fixup_uint_null, 0,
  137. ANY_ROUTE},
  138. {"usleep", (cmd_function)m_usleep, 1, fixup_uint_null, 0,
  139. ANY_ROUTE},
  140. {"abort", (cmd_function)dbg_abort, 0, 0, 0,
  141. ANY_ROUTE},
  142. {"pkg_status", (cmd_function)dbg_pkg_status, 0, 0, 0,
  143. ANY_ROUTE},
  144. {"shm_status", (cmd_function)dbg_shm_status, 0, 0, 0,
  145. ANY_ROUTE},
  146. {"pkg_summary", (cmd_function)dbg_pkg_summary, 0, 0, 0,
  147. ANY_ROUTE},
  148. {"shm_summary", (cmd_function)dbg_shm_summary, 0, 0, 0,
  149. ANY_ROUTE},
  150. {"set_gflag", (cmd_function)set_gflag, 1, fixup_gflags, 0,
  151. ANY_ROUTE},
  152. {"reset_gflag", (cmd_function)reset_gflag, 1, fixup_gflags, 0,
  153. ANY_ROUTE},
  154. {"is_gflag", (cmd_function)is_gflag, 1, fixup_gflags, 0,
  155. ANY_ROUTE},
  156. {"lock", (cmd_function)cfg_lock, 1, fixup_spve_null, 0,
  157. ANY_ROUTE},
  158. {"unlock", (cmd_function)cfg_unlock, 1, fixup_spve_null, 0,
  159. ANY_ROUTE},
  160. {"core_hash", (cmd_function)w_core_hash, 3, fixup_core_hash, 0,
  161. ANY_ROUTE},
  162. {"check_route_exists", (cmd_function)w_check_route_exists, 1, 0, 0,
  163. ANY_ROUTE},
  164. {"route_if_exists", (cmd_function)w_route_exists, 1, 0, 0,
  165. ANY_ROUTE},
  166. {"bind_cfgutils", (cmd_function)bind_cfgutils, 0,
  167. 0, 0, 0},
  168. {0, 0, 0, 0, 0, 0}
  169. };
  170. static param_export_t params[]={
  171. {"initial_probability", INT_PARAM, &initial_prob },
  172. {"initial_gflags", INT_PARAM, &initial_gflags },
  173. {"hash_file", PARAM_STRING, &hash_file },
  174. {"lock_set_size", INT_PARAM, &_cfg_lock_size },
  175. {0,0,0}
  176. };
  177. static mi_export_t mi_cmds[] = {
  178. { FIFO_SET_PROB, mi_set_prob, 0, 0, 0 },
  179. { FIFO_RESET_PROB, mi_reset_prob, MI_NO_INPUT_FLAG, 0, 0 },
  180. { FIFO_GET_PROB, mi_get_prob, MI_NO_INPUT_FLAG, 0, 0 },
  181. { FIFO_GET_HASH, mi_get_hash, MI_NO_INPUT_FLAG, 0, 0 },
  182. { FIFO_CHECK_HASH, mi_check_hash, MI_NO_INPUT_FLAG, 0, 0 },
  183. { FIFO_SET_GFLAG, mi_set_gflag, 0, 0, 0 },
  184. { FIFO_RESET_GFLAG, mi_reset_gflag, 0, 0, 0 },
  185. { FIFO_IS_GFLAG, mi_is_gflag, 0, 0, 0 },
  186. { FIFO_GET_GFLAGS, mi_get_gflags, MI_NO_INPUT_FLAG, 0, 0 },
  187. { 0, 0, 0, 0, 0}
  188. };
  189. static pv_export_t mod_items[] = {
  190. { {"RANDOM", sizeof("RANDOM")-1}, PVT_OTHER, pv_get_random_val, 0,
  191. 0, 0, 0, 0 },
  192. { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
  193. };
  194. struct module_exports exports = {
  195. "cfgutils",
  196. DEFAULT_DLFLAGS, /* dlopen flags */
  197. cmds, /* exported functions */
  198. params, /* exported parameters */
  199. 0, /* exported statistics */
  200. mi_cmds, /* exported MI functions */
  201. mod_items, /* exported pseudo-variables */
  202. 0, /* extra processes */
  203. mod_init, /* module initialization function */
  204. 0, /* response function*/
  205. mod_destroy, /* destroy function */
  206. 0 /* per-child init function */
  207. };
  208. /**************************** fixup functions ******************************/
  209. static int fixup_prob( void** param, int param_no)
  210. {
  211. unsigned int myint;
  212. str param_str;
  213. /* we only fix the parameter #1 */
  214. if (param_no!=1)
  215. return 0;
  216. param_str.s=(char*) *param;
  217. param_str.len=strlen(param_str.s);
  218. str2int(&param_str, &myint);
  219. if (myint > 100) {
  220. LM_ERR("invalid probability <%d>\n", myint);
  221. return E_CFG;
  222. }
  223. pkg_free(*param);
  224. *param=(void *)(long)myint;
  225. return 0;
  226. }
  227. /**
  228. * convert char* to int and do bitwise right-shift
  229. * char* must be pkg_alloced and will be freed by the function
  230. */
  231. static int fixup_gflags( void** param, int param_no)
  232. {
  233. unsigned int myint;
  234. str param_str;
  235. /* we only fix the parameter #1 */
  236. if (param_no!=1)
  237. return 0;
  238. param_str.s=(char*) *param;
  239. param_str.len=strlen(param_str.s);
  240. if (str2int(&param_str, &myint )<0) {
  241. LM_ERR("bad number <%s>\n", (char *)(*param));
  242. return E_CFG;
  243. }
  244. if ( myint >= 8*sizeof(*gflags) ) {
  245. LM_ERR("flag <%d> out of "
  246. "range [0..%lu]\n", myint, ((unsigned long)8*sizeof(*gflags))-1 );
  247. return E_CFG;
  248. }
  249. /* convert from flag index to flag bitmap */
  250. myint = 1 << myint;
  251. /* success -- change to int */
  252. pkg_free(*param);
  253. *param=(void *)(long)myint;
  254. return 0;
  255. }
  256. /************************** module functions **********************************/
  257. static int set_gflag(struct sip_msg *bar, char *flag, char *foo)
  258. {
  259. lock_get(gflags_lock);
  260. (*gflags) |= (unsigned int)(long)flag;
  261. lock_release(gflags_lock);
  262. return 1;
  263. }
  264. static int reset_gflag(struct sip_msg *bar, char *flag, char *foo)
  265. {
  266. lock_get(gflags_lock);
  267. (*gflags) &= ~ ((unsigned int)(long)flag);
  268. lock_release(gflags_lock);
  269. return 1;
  270. }
  271. static int is_gflag(struct sip_msg *bar, char *flag, char *foo)
  272. {
  273. return ( (*gflags) & ((unsigned int)(long)flag)) ? 1 : -1;
  274. }
  275. static struct mi_root* mi_set_gflag(struct mi_root* cmd_tree, void* param )
  276. {
  277. unsigned int flag;
  278. struct mi_node* node;
  279. node = cmd_tree->node.kids;
  280. if(node == NULL)
  281. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  282. flag = 0;
  283. if( strno2int( &node->value, &flag) <0)
  284. goto error;
  285. if (!flag) {
  286. LM_ERR("incorrect flag\n");
  287. goto error;
  288. }
  289. lock_get(gflags_lock);
  290. (*gflags) |= flag;
  291. lock_release(gflags_lock);
  292. return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  293. error:
  294. return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
  295. }
  296. static struct mi_root* mi_reset_gflag(struct mi_root* cmd_tree, void* param )
  297. {
  298. unsigned int flag;
  299. struct mi_node* node = NULL;
  300. node = cmd_tree->node.kids;
  301. if(node == NULL)
  302. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  303. flag = 0;
  304. if( strno2int( &node->value, &flag) <0)
  305. goto error;
  306. if (!flag) {
  307. LM_ERR("incorrect flag\n");
  308. goto error;
  309. }
  310. lock_get(gflags_lock);
  311. (*gflags) &= ~ flag;
  312. lock_release(gflags_lock);
  313. return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  314. error:
  315. return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
  316. }
  317. static struct mi_root* mi_is_gflag(struct mi_root* cmd_tree, void* param )
  318. {
  319. unsigned int flag;
  320. struct mi_root* rpl_tree = NULL;
  321. struct mi_node* node = NULL;
  322. node = cmd_tree->node.kids;
  323. if(node == NULL)
  324. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  325. flag = 0;
  326. if( strno2int( &node->value, &flag) <0)
  327. goto error_param;
  328. if (!flag) {
  329. LM_ERR("incorrect flag\n");
  330. goto error_param;
  331. }
  332. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  333. if(rpl_tree ==0)
  334. return 0;
  335. if( ((*gflags) & flag)== flag )
  336. node = add_mi_node_child( &rpl_tree->node, 0, 0, 0, "TRUE", 4);
  337. else
  338. node = add_mi_node_child( &rpl_tree->node, 0, 0, 0, "FALSE", 5);
  339. if(node == NULL)
  340. {
  341. LM_ERR("failed to add node\n");
  342. free_mi_tree(rpl_tree);
  343. return 0;
  344. }
  345. return rpl_tree;
  346. error_param:
  347. return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
  348. }
  349. static struct mi_root* mi_get_gflags(struct mi_root* cmd_tree, void* param )
  350. {
  351. struct mi_root* rpl_tree= NULL;
  352. struct mi_node* node= NULL;
  353. static unsigned int flags;
  354. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
  355. if(rpl_tree == NULL)
  356. return 0;
  357. flags = *gflags;
  358. node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "0x%X",(flags));
  359. if(node == NULL)
  360. goto error;
  361. node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%u",(flags));
  362. if(node == NULL)
  363. goto error;
  364. return rpl_tree;
  365. error:
  366. free_mi_tree(rpl_tree);
  367. return 0;
  368. }
  369. static struct mi_root* mi_set_prob(struct mi_root* cmd, void* param )
  370. {
  371. unsigned int percent;
  372. struct mi_node* node;
  373. node = cmd->node.kids;
  374. if(node == NULL)
  375. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  376. if( str2int( &node->value, &percent) <0)
  377. goto error;
  378. if (percent > 100) {
  379. LM_ERR("incorrect probability <%u>\n", percent);
  380. goto error;
  381. }
  382. *probability = percent;
  383. return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  384. error:
  385. return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
  386. }
  387. static struct mi_root* mi_reset_prob(struct mi_root* cmd, void* param )
  388. {
  389. *probability = initial_prob;
  390. return init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
  391. }
  392. static struct mi_root* mi_get_prob(struct mi_root* cmd, void* param )
  393. {
  394. struct mi_root* rpl_tree= NULL;
  395. struct mi_node* node= NULL;
  396. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
  397. if(rpl_tree == NULL)
  398. return 0;
  399. node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "actual probability: %u percent\n",(*probability));
  400. if(node == NULL)
  401. goto error;
  402. return rpl_tree;
  403. error:
  404. free_mi_tree(rpl_tree);
  405. return 0;
  406. }
  407. static struct mi_root* mi_get_hash(struct mi_root* cmd, void* param )
  408. {
  409. struct mi_root* rpl_tree= NULL;
  410. struct mi_node* node= NULL;
  411. if (!hash_file) {
  412. LM_INFO("no hash_file given, disable hash functionality\n");
  413. rpl_tree = init_mi_tree(404, "Functionality disabled\n", 23);
  414. } else {
  415. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
  416. if(rpl_tree == NULL)
  417. return 0;
  418. node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%.*s\n", MD5_LEN, config_hash);
  419. if(node == NULL)
  420. goto error;
  421. }
  422. return rpl_tree;
  423. error:
  424. free_mi_tree(rpl_tree);
  425. return 0;
  426. }
  427. /*! \brief
  428. * Calculate a MD5 digest over a file.
  429. * This function assumes 32 bytes in the destination buffer.
  430. * \param dest destination
  431. * \param file_name file for that the digest should be calculated
  432. * \return zero on success, negative on errors
  433. */
  434. static int MD5File(char *dest, const char *file_name)
  435. {
  436. MD5_CTX context;
  437. FILE *input;
  438. unsigned char buffer[32768];
  439. unsigned char hash[16];
  440. unsigned int counter, size;
  441. struct stat stats;
  442. if (!dest || !file_name) {
  443. LM_ERR("invalid parameter value\n");
  444. return -1;
  445. }
  446. if (stat(file_name, &stats) != 0) {
  447. LM_ERR("could not stat file %s\n", file_name);
  448. return -1;
  449. }
  450. size = stats.st_size;
  451. MD5Init(&context);
  452. if((input = fopen(file_name, "rb")) == NULL) {
  453. LM_ERR("could not open file %s\n", file_name);
  454. return -1;
  455. }
  456. while(size) {
  457. counter = (size > sizeof(buffer)) ? sizeof(buffer) : size;
  458. if ((counter = fread(buffer, 1, counter, input)) <= 0) {
  459. fclose(input);
  460. return -1;
  461. }
  462. U_MD5Update(&context, buffer, counter);
  463. size -= counter;
  464. }
  465. fclose(input);
  466. U_MD5Final(hash, &context);
  467. string2hex(hash, 16, dest);
  468. LM_DBG("MD5 calculated: %.*s for file %s\n", MD5_LEN, dest, file_name);
  469. return 0;
  470. }
  471. static struct mi_root* mi_check_hash(struct mi_root* cmd, void* param )
  472. {
  473. struct mi_root* rpl_tree= NULL;
  474. struct mi_node* node= NULL;
  475. char tmp[MD5_LEN];
  476. memset(tmp, 0, MD5_LEN);
  477. if (!hash_file) {
  478. LM_INFO("no hash_file given, disable hash functionality\n");
  479. rpl_tree = init_mi_tree(404, "Functionality disabled\n", 23);
  480. } else {
  481. if (MD5File(tmp, hash_file) != 0) {
  482. LM_ERR("could not hash the config file");
  483. rpl_tree = init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN );
  484. return rpl_tree;
  485. }
  486. if (strncmp(config_hash, tmp, MD5_LEN) == 0) {
  487. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
  488. if(rpl_tree == NULL)
  489. return 0;
  490. node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "The actual config file hash is identical to the stored one.\n");
  491. } else {
  492. rpl_tree = init_mi_tree( 400, "Error", 5 );
  493. if(rpl_tree == NULL)
  494. return 0;
  495. node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "The actual config file hash is not identical to the stored one.\n");
  496. }
  497. if(node == NULL)
  498. goto error;
  499. }
  500. return rpl_tree;
  501. error:
  502. free_mi_tree(rpl_tree);
  503. return 0;
  504. }
  505. static int set_prob(struct sip_msg *bar, char *percent_par, char *foo)
  506. {
  507. *probability=(int)(long)percent_par;
  508. return 1;
  509. }
  510. static int reset_prob(struct sip_msg *bar, char *percent_par, char *foo)
  511. {
  512. *probability=initial_prob;
  513. return 1;
  514. }
  515. static int get_prob(struct sip_msg *bar, char *foo1, char *foo2)
  516. {
  517. return *probability;
  518. }
  519. static int rand_event(struct sip_msg *bar, char *foo1, char *foo2)
  520. {
  521. double tmp;
  522. /* most of the time this will be disabled completly. Tis will also fix the
  523. * problem with the corner cases if rand() returned zero or RAND_MAX */
  524. if ((*probability) == 0) return -1;
  525. if ((*probability) == 100) return 1;
  526. tmp = ((double) rand() / RAND_MAX);
  527. LM_DBG("generated random %f\n", tmp);
  528. if (tmp < ((double) (*probability) / 100)) {
  529. LM_DBG("return true\n");
  530. return 1;
  531. }
  532. else {
  533. LM_DBG("return false\n");
  534. return -1;
  535. }
  536. }
  537. static int pv_get_random_val(struct sip_msg *msg, pv_param_t *param,
  538. pv_value_t *res)
  539. {
  540. int n;
  541. int l = 0;
  542. char *ch;
  543. if(msg==NULL || res==NULL)
  544. return -1;
  545. n = rand();
  546. ch = int2str(n , &l);
  547. res->rs.s = ch;
  548. res->rs.len = l;
  549. res->ri = n;
  550. res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
  551. return 0;
  552. }
  553. static int m_sleep(struct sip_msg *msg, char *time, char *str2)
  554. {
  555. LM_DBG("sleep %lu seconds\n", (unsigned long)time);
  556. sleep((unsigned int)(unsigned long)time);
  557. return 1;
  558. }
  559. static int m_usleep(struct sip_msg *msg, char *time, char *str2)
  560. {
  561. LM_DBG("sleep %lu microseconds\n", (unsigned long)time);
  562. sleep_us((unsigned int)(unsigned long)time);
  563. return 1;
  564. }
  565. static int dbg_abort(struct sip_msg* msg, char* foo, char* bar)
  566. {
  567. LM_CRIT("abort called\n");
  568. abort();
  569. return 0;
  570. }
  571. static int dbg_pkg_status(struct sip_msg* msg, char* foo, char* bar)
  572. {
  573. pkg_status();
  574. return 1;
  575. }
  576. static int dbg_shm_status(struct sip_msg* msg, char* foo, char* bar)
  577. {
  578. shm_status();
  579. return 1;
  580. }
  581. static int dbg_pkg_summary(struct sip_msg* msg, char* foo, char* bar)
  582. {
  583. pkg_sums();
  584. return 1;
  585. }
  586. static int dbg_shm_summary(struct sip_msg* msg, char* foo, char* bar)
  587. {
  588. shm_sums();
  589. return 1;
  590. }
  591. int cfg_lock_helper(str *lkey, int mode)
  592. {
  593. unsigned int pos;
  594. pos = core_case_hash(lkey, 0, _cfg_lock_size);
  595. LM_DBG("cfg_lock mode %d on %u\n", mode, pos);
  596. if(mode==0)
  597. lock_set_get(_cfg_lock_set, pos);
  598. else
  599. lock_set_release(_cfg_lock_set, pos);
  600. return 1;
  601. }
  602. int cfg_lock_wrapper(struct sip_msg *msg, gparam_p key, int mode)
  603. {
  604. str s;
  605. if(fixup_get_svalue(msg, key, &s)!=0)
  606. {
  607. LM_ERR("cannot get first parameter\n");
  608. return -1;
  609. }
  610. return cfg_lock_helper(&s, mode);
  611. }
  612. static int cfg_lock(struct sip_msg *msg, char *key, char *s2)
  613. {
  614. if(_cfg_lock_set==NULL || key==NULL)
  615. return -1;
  616. return cfg_lock_wrapper(msg, (gparam_p)key, 0);
  617. }
  618. static int cfg_unlock(struct sip_msg *msg, char *key, char *s2)
  619. {
  620. if(_cfg_lock_set==NULL || key==NULL)
  621. return -1;
  622. return cfg_lock_wrapper(msg, (gparam_p)key, 1);
  623. }
  624. /*! Check if a route block exists - only request routes
  625. */
  626. static int w_check_route_exists(struct sip_msg *msg, char *route)
  627. {
  628. if (route_lookup(&main_rt, route)<0) {
  629. /* not found */
  630. return -1;
  631. }
  632. return 1;
  633. }
  634. /*! Run a request route block if it exists
  635. */
  636. static int w_route_exists(struct sip_msg *msg, char *route)
  637. {
  638. struct run_act_ctx ctx;
  639. int newroute, backup_rt, ret;
  640. newroute = route_lookup(&main_rt, route);
  641. if (newroute<0) {
  642. return -1;
  643. }
  644. backup_rt = get_route_type();
  645. set_route_type(REQUEST_ROUTE);
  646. init_run_actions_ctx(&ctx);
  647. ret = run_top_route(main_rt.rlist[newroute], msg, &ctx);
  648. set_route_type(backup_rt);
  649. return ret;
  650. }
  651. static int mod_init(void)
  652. {
  653. if(register_mi_mod(exports.name, mi_cmds)!=0)
  654. {
  655. LM_ERR("failed to register MI commands\n");
  656. return -1;
  657. }
  658. if (!hash_file) {
  659. LM_INFO("no hash_file given, disable hash functionality\n");
  660. } else {
  661. if (MD5File(config_hash, hash_file) != 0) {
  662. LM_ERR("could not hash the config file");
  663. return -1;
  664. }
  665. LM_DBG("config file hash is %.*s", MD5_LEN, config_hash);
  666. }
  667. if (initial_prob > 100) {
  668. LM_ERR("invalid probability <%d>\n", initial_prob);
  669. return -1;
  670. }
  671. LM_DBG("initial probability %d percent\n", initial_prob);
  672. probability=(int *) shm_malloc(sizeof(int));
  673. if (!probability) {
  674. LM_ERR("no shmem available\n");
  675. return -1;
  676. }
  677. *probability = initial_prob;
  678. gflags=(unsigned int *) shm_malloc(sizeof(unsigned int));
  679. if (!gflags) {
  680. LM_ERR(" no shmem available\n");
  681. return -1;
  682. }
  683. *gflags=initial_gflags;
  684. gflags_lock = lock_alloc();
  685. if (gflags_lock==0) {
  686. LM_ERR("cannot allocate gflgas lock\n");
  687. return -1;
  688. }
  689. if (lock_init(gflags_lock)==NULL) {
  690. LM_ERR("cannot initiate gflags lock\n");
  691. lock_dealloc(gflags_lock);
  692. return -1;
  693. }
  694. if(_cfg_lock_size>0 && _cfg_lock_size<=10)
  695. {
  696. _cfg_lock_size = 1<<_cfg_lock_size;
  697. _cfg_lock_set = lock_set_alloc(_cfg_lock_size);
  698. if(_cfg_lock_set==NULL || lock_set_init(_cfg_lock_set)==NULL)
  699. {
  700. LM_ERR("cannot initiate lock set\n");
  701. return -1;
  702. }
  703. }
  704. return 0;
  705. }
  706. static void mod_destroy(void)
  707. {
  708. if (probability)
  709. shm_free(probability);
  710. if (gflags)
  711. shm_free(gflags);
  712. if (gflags_lock) {
  713. lock_destroy(gflags_lock);
  714. lock_dealloc(gflags_lock);
  715. }
  716. if(_cfg_lock_set!=NULL)
  717. {
  718. lock_set_destroy(_cfg_lock_set);
  719. lock_set_dealloc(_cfg_lock_set);
  720. }
  721. }
  722. /**
  723. *
  724. */
  725. int cfgutils_lock(str *lkey)
  726. {
  727. return cfg_lock_helper(lkey, 0);
  728. }
  729. /**
  730. *
  731. */
  732. int cfgutils_unlock(str *lkey)
  733. {
  734. return cfg_lock_helper(lkey, 1);
  735. }
  736. static int fixup_core_hash(void **param, int param_no)
  737. {
  738. if (param_no == 1)
  739. return fixup_spve_null(param, 1);
  740. else if (param_no == 2)
  741. return fixup_spve_null(param, 1);
  742. else if (param_no == 3)
  743. return fixup_igp_null(param, 1);
  744. else
  745. return 0;
  746. }
  747. static int w_core_hash(struct sip_msg *msg, char *p1, char *p2, char *p3)
  748. {
  749. str s1, s2;
  750. int size;
  751. if (fixup_get_svalue(msg, (gparam_p) p1, &s1) != 0)
  752. {
  753. LM_ERR("invalid s1 paramerer\n");
  754. return -1;
  755. }
  756. if (fixup_get_svalue(msg, (gparam_p) p2, &s2) != 0)
  757. {
  758. LM_ERR("invalid s2 paramerer\n");
  759. return -1;
  760. }
  761. if (fixup_get_ivalue(msg, (gparam_p) p3, &size) != 0)
  762. {
  763. LM_ERR("invalid size paramerer\n");
  764. return -1;
  765. }
  766. if (size <= 0) size = 2;
  767. else size = 1 << size;
  768. /* Return value _MUST_ be > 0 */
  769. return core_hash(&s1, s2.len ? &s2 : NULL, size) + 1;
  770. }
  771. /**
  772. * @brief bind functions to CFGUTILS API structure
  773. */
  774. int bind_cfgutils(cfgutils_api_t *api)
  775. {
  776. if (!api) {
  777. ERR("Invalid parameter value\n");
  778. return -1;
  779. }
  780. api->mlock = cfgutils_lock;
  781. api->munlock = cfgutils_unlock;
  782. return 0;
  783. }