cfgutils.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  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 "../../rpc_lookup.h"
  72. #include <stdio.h>
  73. #include <stdlib.h>
  74. #include <sys/types.h>
  75. #include <sys/stat.h>
  76. #include <unistd.h>
  77. #include "api.h"
  78. MODULE_VERSION
  79. static int set_prob(struct sip_msg*, char *, char *);
  80. static int reset_prob(struct sip_msg*, char *, char *);
  81. static int get_prob(struct sip_msg*, char *, char *);
  82. static int rand_event(struct sip_msg*, char *, char *);
  83. static int m_sleep(struct sip_msg*, char *, char *);
  84. static int m_usleep(struct sip_msg*, char *, char *);
  85. static int dbg_abort(struct sip_msg*, char*,char*);
  86. static int dbg_pkg_status(struct sip_msg*, char*,char*);
  87. static int dbg_shm_status(struct sip_msg*, char*,char*);
  88. static int dbg_pkg_summary(struct sip_msg*, char*,char*);
  89. static int dbg_shm_summary(struct sip_msg*, char*,char*);
  90. static int route_exists(struct sip_msg*, char*);
  91. static int check_route_exists(struct sip_msg*, char*);
  92. static int set_gflag(struct sip_msg*, char *, char *);
  93. static int reset_gflag(struct sip_msg*, char *, char *);
  94. static int is_gflag(struct sip_msg*, char *, char *);
  95. static int cfg_lock(struct sip_msg*, char *, char *);
  96. static int cfg_unlock(struct sip_msg*, char *, char *);
  97. static struct mi_root* mi_set_prob(struct mi_root* cmd, void* param );
  98. static struct mi_root* mi_reset_prob(struct mi_root* cmd, void* param );
  99. static struct mi_root* mi_get_prob(struct mi_root* cmd, void* param );
  100. static struct mi_root* mi_get_hash(struct mi_root* cmd, void* param );
  101. static struct mi_root* mi_check_hash(struct mi_root* cmd, void* param );
  102. static struct mi_root* mi_set_gflag(struct mi_root* cmd, void* param );
  103. static struct mi_root* mi_reset_gflag(struct mi_root* cmd, void* param );
  104. static struct mi_root* mi_is_gflag(struct mi_root* cmd, void* param );
  105. static struct mi_root* mi_get_gflags(struct mi_root* cmd, void* param );
  106. static int pv_get_random_val(struct sip_msg *msg, pv_param_t *param,
  107. pv_value_t *res);
  108. static int fixup_prob( void** param, int param_no);
  109. static int fixup_gflags( void** param, int param_no);
  110. static int fixup_core_hash(void **param, int param_no);
  111. static int w_core_hash(struct sip_msg *msg, char *p1, char *p2, char *p3);
  112. int bind_cfgutils(cfgutils_api_t *api);
  113. static int mod_init(void);
  114. static void mod_destroy(void);
  115. static int initial_prob = 10;
  116. static int *probability = NULL;
  117. static char config_hash[MD5_LEN];
  118. static char* hash_file = NULL;
  119. static int initial_gflags=0;
  120. static unsigned int *gflags=0;
  121. static gen_lock_t *gflags_lock = NULL;
  122. static gen_lock_set_t *_cfg_lock_set = NULL;
  123. static unsigned int _cfg_lock_size = 0;
  124. static cmd_export_t cmds[]={
  125. {"rand_set_prob", /* action name as in scripts */
  126. (cmd_function)set_prob, /* C function name */
  127. 1, /* number of parameters */
  128. fixup_prob, 0, /* */
  129. /* can be applied to original/failed requests and replies */
  130. ANY_ROUTE},
  131. {"rand_reset_prob", (cmd_function)reset_prob, 0, 0, 0,
  132. ANY_ROUTE},
  133. {"rand_get_prob", (cmd_function)get_prob, 0, 0, 0,
  134. ANY_ROUTE},
  135. {"rand_event", (cmd_function)rand_event, 0, 0, 0,
  136. ANY_ROUTE},
  137. {"sleep", (cmd_function)m_sleep, 1, fixup_uint_null, 0,
  138. ANY_ROUTE},
  139. {"usleep", (cmd_function)m_usleep, 1, fixup_uint_null, 0,
  140. ANY_ROUTE},
  141. {"abort", (cmd_function)dbg_abort, 0, 0, 0,
  142. ANY_ROUTE},
  143. {"pkg_status", (cmd_function)dbg_pkg_status, 0, 0, 0,
  144. ANY_ROUTE},
  145. {"shm_status", (cmd_function)dbg_shm_status, 0, 0, 0,
  146. ANY_ROUTE},
  147. {"pkg_summary", (cmd_function)dbg_pkg_summary, 0, 0, 0,
  148. ANY_ROUTE},
  149. {"shm_summary", (cmd_function)dbg_shm_summary, 0, 0, 0,
  150. ANY_ROUTE},
  151. {"set_gflag", (cmd_function)set_gflag, 1, fixup_gflags, 0,
  152. ANY_ROUTE},
  153. {"reset_gflag", (cmd_function)reset_gflag, 1, fixup_gflags, 0,
  154. ANY_ROUTE},
  155. {"is_gflag", (cmd_function)is_gflag, 1, fixup_gflags, 0,
  156. ANY_ROUTE},
  157. {"lock", (cmd_function)cfg_lock, 1, fixup_spve_null, 0,
  158. ANY_ROUTE},
  159. {"unlock", (cmd_function)cfg_unlock, 1, fixup_spve_null, 0,
  160. ANY_ROUTE},
  161. {"core_hash", (cmd_function)w_core_hash, 3, fixup_core_hash, 0,
  162. ANY_ROUTE},
  163. {"check_route_exists", (cmd_function)check_route_exists, 1, 0, 0,
  164. ANY_ROUTE},
  165. {"route_if_exists", (cmd_function)route_exists, 1, 0, 0,
  166. ANY_ROUTE},
  167. {"bind_cfgutils", (cmd_function)bind_cfgutils, 0,
  168. 0, 0, 0},
  169. {0, 0, 0, 0, 0, 0}
  170. };
  171. static param_export_t params[]={
  172. {"initial_probability", INT_PARAM, &initial_prob },
  173. {"initial_gflags", INT_PARAM, &initial_gflags },
  174. {"hash_file", PARAM_STRING, &hash_file },
  175. {"lock_set_size", INT_PARAM, &_cfg_lock_size },
  176. {0,0,0}
  177. };
  178. static mi_export_t mi_cmds[] = {
  179. { FIFO_SET_PROB, mi_set_prob, 0, 0, 0 },
  180. { FIFO_RESET_PROB, mi_reset_prob, MI_NO_INPUT_FLAG, 0, 0 },
  181. { FIFO_GET_PROB, mi_get_prob, MI_NO_INPUT_FLAG, 0, 0 },
  182. { FIFO_GET_HASH, mi_get_hash, MI_NO_INPUT_FLAG, 0, 0 },
  183. { FIFO_CHECK_HASH, mi_check_hash, MI_NO_INPUT_FLAG, 0, 0 },
  184. { FIFO_SET_GFLAG, mi_set_gflag, 0, 0, 0 },
  185. { FIFO_RESET_GFLAG, mi_reset_gflag, 0, 0, 0 },
  186. { FIFO_IS_GFLAG, mi_is_gflag, 0, 0, 0 },
  187. { FIFO_GET_GFLAGS, mi_get_gflags, MI_NO_INPUT_FLAG, 0, 0 },
  188. { 0, 0, 0, 0, 0}
  189. };
  190. static void rpc_is_gflag(rpc_t* rpc, void* c)
  191. {
  192. str flag_str;
  193. unsigned int flag;
  194. if (rpc->scan(c, "S", &flag_str) != 1) {
  195. rpc->fault(c, 400, "flag parameter error");
  196. return;
  197. }
  198. flag = 0;
  199. if ((strno2int(&flag_str, &flag) < 0) || !flag) {
  200. rpc->fault(c, 400, "incorrect flag parameter value");
  201. return;
  202. }
  203. if (((*gflags) & flag) == flag)
  204. rpc->add(c, "s", "TRUE");
  205. else
  206. rpc->add(c, "s", "FALSE");
  207. return;
  208. }
  209. static void rpc_set_gflag(rpc_t* rpc, void* c)
  210. {
  211. str flag_str;
  212. unsigned int flag;
  213. if (rpc->scan(c, "S", &flag_str) != 1) {
  214. rpc->fault(c, 400, "flag parameter error");
  215. return;
  216. }
  217. flag = 0;
  218. if ((strno2int(&flag_str, &flag) < 0) || !flag) {
  219. rpc->fault(c, 400, "incorrect flag parameter value '%.*s'",
  220. flag_str.len, flag_str.s);
  221. return;
  222. }
  223. lock_get(gflags_lock);
  224. (*gflags) |= flag;
  225. lock_release(gflags_lock);
  226. return;
  227. }
  228. static void rpc_reset_gflag(rpc_t* rpc, void* c)
  229. {
  230. str flag_str;
  231. unsigned int flag;
  232. if (rpc->scan(c, "S", &flag_str) != 1) {
  233. rpc->fault(c, 400, "flag parameter error");
  234. return;
  235. }
  236. flag = 0;
  237. if ((strno2int(&flag_str, &flag) < 0) || !flag) {
  238. rpc->fault(c, 400, "incorrect flag parameter value");
  239. return;
  240. }
  241. lock_get(gflags_lock);
  242. (*gflags) &= ~ flag;
  243. lock_release(gflags_lock);
  244. return;
  245. }
  246. static const char* is_gflag_doc[2] = {
  247. "Checks if the bits specified by the argument are all set.",
  248. 0
  249. };
  250. static const char* set_gflag_doc[2] = {
  251. "Sets the bits specified by the argument.",
  252. 0
  253. };
  254. static const char* reset_gflag_doc[2] = {
  255. "Resets the bits specified by the argument.",
  256. 0
  257. };
  258. static rpc_export_t rpc_cmds[] = {
  259. {"cfgutils.is_gflag", rpc_is_gflag, is_gflag_doc, 0},
  260. {"cfgutils.set_gflag", rpc_set_gflag, set_gflag_doc, 0},
  261. {"cfgutils.reset_gflag", rpc_reset_gflag, reset_gflag_doc, 0},
  262. {0, 0, 0, 0}
  263. };
  264. static pv_export_t mod_items[] = {
  265. { {"RANDOM", sizeof("RANDOM")-1}, PVT_OTHER, pv_get_random_val, 0,
  266. 0, 0, 0, 0 },
  267. { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
  268. };
  269. struct module_exports exports = {
  270. "cfgutils",
  271. DEFAULT_DLFLAGS, /* dlopen flags */
  272. cmds, /* exported functions */
  273. params, /* exported parameters */
  274. 0, /* exported statistics */
  275. mi_cmds, /* exported MI functions */
  276. mod_items, /* exported pseudo-variables */
  277. 0, /* extra processes */
  278. mod_init, /* module initialization function */
  279. 0, /* response function*/
  280. mod_destroy, /* destroy function */
  281. 0 /* per-child init function */
  282. };
  283. /**************************** fixup functions ******************************/
  284. static int fixup_prob( void** param, int param_no)
  285. {
  286. unsigned int myint;
  287. str param_str;
  288. /* we only fix the parameter #1 */
  289. if (param_no!=1)
  290. return 0;
  291. param_str.s=(char*) *param;
  292. param_str.len=strlen(param_str.s);
  293. str2int(&param_str, &myint);
  294. if (myint > 100) {
  295. LM_ERR("invalid probability <%d>\n", myint);
  296. return E_CFG;
  297. }
  298. pkg_free(*param);
  299. *param=(void *)(long)myint;
  300. return 0;
  301. }
  302. /**
  303. * convert char* to int and do bitwise right-shift
  304. * char* must be pkg_alloced and will be freed by the function
  305. */
  306. static int fixup_gflags( void** param, int param_no)
  307. {
  308. unsigned int myint;
  309. str param_str;
  310. /* we only fix the parameter #1 */
  311. if (param_no!=1)
  312. return 0;
  313. param_str.s=(char*) *param;
  314. param_str.len=strlen(param_str.s);
  315. if (str2int(&param_str, &myint )<0) {
  316. LM_ERR("bad number <%s>\n", (char *)(*param));
  317. return E_CFG;
  318. }
  319. if ( myint >= 8*sizeof(*gflags) ) {
  320. LM_ERR("flag <%d> out of "
  321. "range [0..%lu]\n", myint, ((unsigned long)8*sizeof(*gflags))-1 );
  322. return E_CFG;
  323. }
  324. /* convert from flag index to flag bitmap */
  325. myint = 1 << myint;
  326. /* success -- change to int */
  327. pkg_free(*param);
  328. *param=(void *)(long)myint;
  329. return 0;
  330. }
  331. /************************** module functions **********************************/
  332. static int set_gflag(struct sip_msg *bar, char *flag, char *foo)
  333. {
  334. lock_get(gflags_lock);
  335. (*gflags) |= (unsigned int)(long)flag;
  336. lock_release(gflags_lock);
  337. return 1;
  338. }
  339. static int reset_gflag(struct sip_msg *bar, char *flag, char *foo)
  340. {
  341. lock_get(gflags_lock);
  342. (*gflags) &= ~ ((unsigned int)(long)flag);
  343. lock_release(gflags_lock);
  344. return 1;
  345. }
  346. static int is_gflag(struct sip_msg *bar, char *flag, char *foo)
  347. {
  348. return ( (*gflags) & ((unsigned int)(long)flag)) ? 1 : -1;
  349. }
  350. static struct mi_root* mi_set_gflag(struct mi_root* cmd_tree, void* param )
  351. {
  352. unsigned int flag;
  353. struct mi_node* node;
  354. node = cmd_tree->node.kids;
  355. if(node == NULL)
  356. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  357. flag = 0;
  358. if( strno2int( &node->value, &flag) <0)
  359. goto error;
  360. if (!flag) {
  361. LM_ERR("incorrect flag\n");
  362. goto error;
  363. }
  364. lock_get(gflags_lock);
  365. (*gflags) |= flag;
  366. lock_release(gflags_lock);
  367. return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  368. error:
  369. return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
  370. }
  371. static struct mi_root* mi_reset_gflag(struct mi_root* cmd_tree, void* param )
  372. {
  373. unsigned int flag;
  374. struct mi_node* node = NULL;
  375. node = cmd_tree->node.kids;
  376. if(node == NULL)
  377. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  378. flag = 0;
  379. if( strno2int( &node->value, &flag) <0)
  380. goto error;
  381. if (!flag) {
  382. LM_ERR("incorrect flag\n");
  383. goto error;
  384. }
  385. lock_get(gflags_lock);
  386. (*gflags) &= ~ flag;
  387. lock_release(gflags_lock);
  388. return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  389. error:
  390. return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
  391. }
  392. static struct mi_root* mi_is_gflag(struct mi_root* cmd_tree, void* param )
  393. {
  394. unsigned int flag;
  395. struct mi_root* rpl_tree = NULL;
  396. struct mi_node* node = NULL;
  397. node = cmd_tree->node.kids;
  398. if(node == NULL)
  399. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  400. flag = 0;
  401. if( strno2int( &node->value, &flag) <0)
  402. goto error_param;
  403. if (!flag) {
  404. LM_ERR("incorrect flag\n");
  405. goto error_param;
  406. }
  407. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  408. if(rpl_tree ==0)
  409. return 0;
  410. if( ((*gflags) & flag)== flag )
  411. node = add_mi_node_child( &rpl_tree->node, 0, 0, 0, "TRUE", 4);
  412. else
  413. node = add_mi_node_child( &rpl_tree->node, 0, 0, 0, "FALSE", 5);
  414. if(node == NULL)
  415. {
  416. LM_ERR("failed to add node\n");
  417. free_mi_tree(rpl_tree);
  418. return 0;
  419. }
  420. return rpl_tree;
  421. error_param:
  422. return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
  423. }
  424. static struct mi_root* mi_get_gflags(struct mi_root* cmd_tree, void* param )
  425. {
  426. struct mi_root* rpl_tree= NULL;
  427. struct mi_node* node= NULL;
  428. static unsigned int flags;
  429. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
  430. if(rpl_tree == NULL)
  431. return 0;
  432. flags = *gflags;
  433. node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "0x%X",(flags));
  434. if(node == NULL)
  435. goto error;
  436. node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%u",(flags));
  437. if(node == NULL)
  438. goto error;
  439. return rpl_tree;
  440. error:
  441. free_mi_tree(rpl_tree);
  442. return 0;
  443. }
  444. static struct mi_root* mi_set_prob(struct mi_root* cmd, void* param )
  445. {
  446. unsigned int percent;
  447. struct mi_node* node;
  448. node = cmd->node.kids;
  449. if(node == NULL)
  450. return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
  451. if( str2int( &node->value, &percent) <0)
  452. goto error;
  453. if (percent > 100) {
  454. LM_ERR("incorrect probability <%u>\n", percent);
  455. goto error;
  456. }
  457. *probability = percent;
  458. return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
  459. error:
  460. return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
  461. }
  462. static struct mi_root* mi_reset_prob(struct mi_root* cmd, void* param )
  463. {
  464. *probability = initial_prob;
  465. return init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
  466. }
  467. static struct mi_root* mi_get_prob(struct mi_root* cmd, void* param )
  468. {
  469. struct mi_root* rpl_tree= NULL;
  470. struct mi_node* node= NULL;
  471. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
  472. if(rpl_tree == NULL)
  473. return 0;
  474. node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "actual probability: %u percent\n",(*probability));
  475. if(node == NULL)
  476. goto error;
  477. return rpl_tree;
  478. error:
  479. free_mi_tree(rpl_tree);
  480. return 0;
  481. }
  482. static struct mi_root* mi_get_hash(struct mi_root* cmd, void* param )
  483. {
  484. struct mi_root* rpl_tree= NULL;
  485. struct mi_node* node= NULL;
  486. if (!hash_file) {
  487. LM_INFO("no hash_file given, disable hash functionality\n");
  488. rpl_tree = init_mi_tree(404, "Functionality disabled\n", 23);
  489. } else {
  490. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
  491. if(rpl_tree == NULL)
  492. return 0;
  493. node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%.*s\n", MD5_LEN, config_hash);
  494. if(node == NULL)
  495. goto error;
  496. }
  497. return rpl_tree;
  498. error:
  499. free_mi_tree(rpl_tree);
  500. return 0;
  501. }
  502. /*! \brief
  503. * Calculate a MD5 digest over a file.
  504. * This function assumes 32 bytes in the destination buffer.
  505. * \param dest destination
  506. * \param file_name file for that the digest should be calculated
  507. * \return zero on success, negative on errors
  508. */
  509. static int MD5File(char *dest, const char *file_name)
  510. {
  511. MD5_CTX context;
  512. FILE *input;
  513. unsigned char buffer[32768];
  514. unsigned char hash[16];
  515. unsigned int counter, size;
  516. struct stat stats;
  517. if (!dest || !file_name) {
  518. LM_ERR("invalid parameter value\n");
  519. return -1;
  520. }
  521. if (stat(file_name, &stats) != 0) {
  522. LM_ERR("could not stat file %s\n", file_name);
  523. return -1;
  524. }
  525. size = stats.st_size;
  526. MD5Init(&context);
  527. if((input = fopen(file_name, "rb")) == NULL) {
  528. LM_ERR("could not open file %s\n", file_name);
  529. return -1;
  530. }
  531. while(size) {
  532. counter = (size > sizeof(buffer)) ? sizeof(buffer) : size;
  533. if ((counter = fread(buffer, 1, counter, input)) <= 0) {
  534. fclose(input);
  535. return -1;
  536. }
  537. U_MD5Update(&context, buffer, counter);
  538. size -= counter;
  539. }
  540. fclose(input);
  541. U_MD5Final(hash, &context);
  542. string2hex(hash, 16, dest);
  543. LM_DBG("MD5 calculated: %.*s for file %s\n", MD5_LEN, dest, file_name);
  544. return 0;
  545. }
  546. static struct mi_root* mi_check_hash(struct mi_root* cmd, void* param )
  547. {
  548. struct mi_root* rpl_tree= NULL;
  549. struct mi_node* node= NULL;
  550. char tmp[MD5_LEN];
  551. memset(tmp, 0, MD5_LEN);
  552. if (!hash_file) {
  553. LM_INFO("no hash_file given, disable hash functionality\n");
  554. rpl_tree = init_mi_tree(404, "Functionality disabled\n", 23);
  555. } else {
  556. if (MD5File(tmp, hash_file) != 0) {
  557. LM_ERR("could not hash the config file");
  558. rpl_tree = init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN );
  559. return rpl_tree;
  560. }
  561. if (strncmp(config_hash, tmp, MD5_LEN) == 0) {
  562. rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
  563. if(rpl_tree == NULL)
  564. return 0;
  565. node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "The actual config file hash is identical to the stored one.\n");
  566. } else {
  567. rpl_tree = init_mi_tree( 400, "Error", 5 );
  568. if(rpl_tree == NULL)
  569. return 0;
  570. node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "The actual config file hash is not identical to the stored one.\n");
  571. }
  572. if(node == NULL)
  573. goto error;
  574. }
  575. return rpl_tree;
  576. error:
  577. free_mi_tree(rpl_tree);
  578. return 0;
  579. }
  580. static int set_prob(struct sip_msg *bar, char *percent_par, char *foo)
  581. {
  582. *probability=(int)(long)percent_par;
  583. return 1;
  584. }
  585. static int reset_prob(struct sip_msg *bar, char *percent_par, char *foo)
  586. {
  587. *probability=initial_prob;
  588. return 1;
  589. }
  590. static int get_prob(struct sip_msg *bar, char *foo1, char *foo2)
  591. {
  592. return *probability;
  593. }
  594. static int rand_event(struct sip_msg *bar, char *foo1, char *foo2)
  595. {
  596. double tmp;
  597. /* most of the time this will be disabled completly. Tis will also fix the
  598. * problem with the corner cases if rand() returned zero or RAND_MAX */
  599. if ((*probability) == 0) return -1;
  600. if ((*probability) == 100) return 1;
  601. tmp = ((double) rand() / RAND_MAX);
  602. LM_DBG("generated random %f\n", tmp);
  603. if (tmp < ((double) (*probability) / 100)) {
  604. LM_DBG("return true\n");
  605. return 1;
  606. }
  607. else {
  608. LM_DBG("return false\n");
  609. return -1;
  610. }
  611. }
  612. static int pv_get_random_val(struct sip_msg *msg, pv_param_t *param,
  613. pv_value_t *res)
  614. {
  615. int n;
  616. int l = 0;
  617. char *ch;
  618. if(msg==NULL || res==NULL)
  619. return -1;
  620. n = rand();
  621. ch = int2str(n , &l);
  622. res->rs.s = ch;
  623. res->rs.len = l;
  624. res->ri = n;
  625. res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
  626. return 0;
  627. }
  628. static int m_sleep(struct sip_msg *msg, char *time, char *str2)
  629. {
  630. LM_DBG("sleep %lu seconds\n", (unsigned long)time);
  631. sleep((unsigned int)(unsigned long)time);
  632. return 1;
  633. }
  634. static int m_usleep(struct sip_msg *msg, char *time, char *str2)
  635. {
  636. LM_DBG("sleep %lu microseconds\n", (unsigned long)time);
  637. sleep_us((unsigned int)(unsigned long)time);
  638. return 1;
  639. }
  640. static int dbg_abort(struct sip_msg* msg, char* foo, char* bar)
  641. {
  642. LM_CRIT("abort called\n");
  643. abort();
  644. return 0;
  645. }
  646. static int dbg_pkg_status(struct sip_msg* msg, char* foo, char* bar)
  647. {
  648. pkg_status();
  649. return 1;
  650. }
  651. static int dbg_shm_status(struct sip_msg* msg, char* foo, char* bar)
  652. {
  653. shm_status();
  654. return 1;
  655. }
  656. static int dbg_pkg_summary(struct sip_msg* msg, char* foo, char* bar)
  657. {
  658. pkg_sums();
  659. return 1;
  660. }
  661. static int dbg_shm_summary(struct sip_msg* msg, char* foo, char* bar)
  662. {
  663. shm_sums();
  664. return 1;
  665. }
  666. int cfg_lock_helper(str *lkey, int mode)
  667. {
  668. unsigned int pos;
  669. pos = core_case_hash(lkey, 0, _cfg_lock_size);
  670. LM_DBG("cfg_lock mode %d on %u\n", mode, pos);
  671. if(mode==0)
  672. lock_set_get(_cfg_lock_set, pos);
  673. else
  674. lock_set_release(_cfg_lock_set, pos);
  675. return 1;
  676. }
  677. int cfg_lock_wrapper(struct sip_msg *msg, gparam_p key, int mode)
  678. {
  679. str s;
  680. if(fixup_get_svalue(msg, key, &s)!=0)
  681. {
  682. LM_ERR("cannot get first parameter\n");
  683. return -1;
  684. }
  685. return cfg_lock_helper(&s, mode);
  686. }
  687. static int cfg_lock(struct sip_msg *msg, char *key, char *s2)
  688. {
  689. if(_cfg_lock_set==NULL || key==NULL)
  690. return -1;
  691. return cfg_lock_wrapper(msg, (gparam_p)key, 0);
  692. }
  693. static int cfg_unlock(struct sip_msg *msg, char *key, char *s2)
  694. {
  695. if(_cfg_lock_set==NULL || key==NULL)
  696. return -1;
  697. return cfg_lock_wrapper(msg, (gparam_p)key, 1);
  698. }
  699. /*! Check if a route block exists - only request routes
  700. */
  701. static int check_route_exists(struct sip_msg *msg, char *route)
  702. {
  703. if (route_lookup(&main_rt, route))
  704. return 1;
  705. return 0;
  706. }
  707. /*! Run a request route block if it exists
  708. */
  709. static int route_exists(struct sip_msg *msg, char *route)
  710. {
  711. struct run_act_ctx ctx;
  712. int newroute, backup_rt;
  713. if (!(newroute = route_lookup(&main_rt, route))) {
  714. return 0;
  715. }
  716. backup_rt = get_route_type();
  717. set_route_type(REQUEST_ROUTE);
  718. init_run_actions_ctx(&ctx);
  719. run_top_route(main_rt.rlist[newroute], msg, 0);
  720. set_route_type(backup_rt);
  721. return 0;
  722. }
  723. static int mod_init(void)
  724. {
  725. /* Register RPC commands */
  726. if (rpc_register_array(rpc_cmds)!=0) {
  727. LM_ERR("failed to register RPC commands\n");
  728. return -1;
  729. }
  730. if(register_mi_mod(exports.name, mi_cmds)!=0)
  731. {
  732. LM_ERR("failed to register MI commands\n");
  733. return -1;
  734. }
  735. if (!hash_file) {
  736. LM_INFO("no hash_file given, disable hash functionality\n");
  737. } else {
  738. if (MD5File(config_hash, hash_file) != 0) {
  739. LM_ERR("could not hash the config file");
  740. return -1;
  741. }
  742. LM_DBG("config file hash is %.*s", MD5_LEN, config_hash);
  743. }
  744. if (initial_prob > 100) {
  745. LM_ERR("invalid probability <%d>\n", initial_prob);
  746. return -1;
  747. }
  748. LM_DBG("initial probability %d percent\n", initial_prob);
  749. probability=(int *) shm_malloc(sizeof(int));
  750. if (!probability) {
  751. LM_ERR("no shmem available\n");
  752. return -1;
  753. }
  754. *probability = initial_prob;
  755. gflags=(unsigned int *) shm_malloc(sizeof(unsigned int));
  756. if (!gflags) {
  757. LM_ERR(" no shmem available\n");
  758. return -1;
  759. }
  760. *gflags=initial_gflags;
  761. gflags_lock = lock_alloc();
  762. if (gflags_lock==0) {
  763. LM_ERR("cannot allocate gflgas lock\n");
  764. return -1;
  765. }
  766. if (lock_init(gflags_lock)==NULL) {
  767. LM_ERR("cannot initiate gflags lock\n");
  768. lock_dealloc(gflags_lock);
  769. return -1;
  770. }
  771. if(_cfg_lock_size>0 && _cfg_lock_size<=10)
  772. {
  773. _cfg_lock_size = 1<<_cfg_lock_size;
  774. _cfg_lock_set = lock_set_alloc(_cfg_lock_size);
  775. if(_cfg_lock_set==NULL || lock_set_init(_cfg_lock_set)==NULL)
  776. {
  777. LM_ERR("cannot initiate lock set\n");
  778. return -1;
  779. }
  780. }
  781. return 0;
  782. }
  783. static void mod_destroy(void)
  784. {
  785. if (probability)
  786. shm_free(probability);
  787. if (gflags)
  788. shm_free(gflags);
  789. if (gflags_lock) {
  790. lock_destroy(gflags_lock);
  791. lock_dealloc(gflags_lock);
  792. }
  793. if(_cfg_lock_set!=NULL)
  794. {
  795. lock_set_destroy(_cfg_lock_set);
  796. lock_set_dealloc(_cfg_lock_set);
  797. }
  798. }
  799. /**
  800. *
  801. */
  802. int cfgutils_lock(str *lkey)
  803. {
  804. return cfg_lock_helper(lkey, 0);
  805. }
  806. /**
  807. *
  808. */
  809. int cfgutils_unlock(str *lkey)
  810. {
  811. return cfg_lock_helper(lkey, 1);
  812. }
  813. static int fixup_core_hash(void **param, int param_no)
  814. {
  815. if (param_no == 1)
  816. return fixup_spve_null(param, 1);
  817. else if (param_no == 2)
  818. return fixup_spve_null(param, 1);
  819. else if (param_no == 3)
  820. return fixup_igp_null(param, 1);
  821. else
  822. return 0;
  823. }
  824. static int w_core_hash(struct sip_msg *msg, char *p1, char *p2, char *p3)
  825. {
  826. str s1, s2;
  827. int size;
  828. if (fixup_get_svalue(msg, (gparam_p) p1, &s1) != 0)
  829. {
  830. LM_ERR("invalid s1 paramerer\n");
  831. return -1;
  832. }
  833. if (fixup_get_svalue(msg, (gparam_p) p2, &s2) != 0)
  834. {
  835. LM_ERR("invalid s2 paramerer\n");
  836. return -1;
  837. }
  838. if (fixup_get_ivalue(msg, (gparam_p) p3, &size) != 0)
  839. {
  840. LM_ERR("invalid size paramerer\n");
  841. return -1;
  842. }
  843. if (size <= 0) size = 2;
  844. else size = 1 << size;
  845. /* Return value _MUST_ be > 0 */
  846. return core_hash(&s1, s2.len ? &s2 : NULL, size) + 1;
  847. }
  848. /**
  849. * @brief bind functions to CFGUTILS API structure
  850. */
  851. int bind_cfgutils(cfgutils_api_t *api)
  852. {
  853. if (!api) {
  854. ERR("Invalid parameter value\n");
  855. return -1;
  856. }
  857. api->mlock = cfgutils_lock;
  858. api->munlock = cfgutils_unlock;
  859. return 0;
  860. }