2 * Copyright (C) 2012 Edvina AB
3 * Copyright (C) 2007 1&1 Internet AG
4 * Copyright (C) 2007 BASIS AudioNet GmbH
5 * Copyright (C) 2004 FhG
6 * Copyright (C) 2005-2006 Voice Sistem S.R.L.
8 * This file is part of Kamailio, a free SIP server.
10 * Kamailio 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
15 * Kamailio 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.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Softwar
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 * cfgutils module: various config 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.
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.
46 #include "../../core/sr_module.h"
47 #include "../../core/error.h"
48 #include "../../core/pvar.h"
49 #include "../../core/ut.h"
50 #include "../../core/mem/mem.h"
51 #include "../../core/mem/shm_mem.h"
52 #include "../../core/mod_fix.h"
53 #include "../../core/crypto/md5.h"
54 #include "../../core/crypto/md5utils.h"
55 #include "../../core/globals.h"
56 #include "../../core/hashes.h"
57 #include "../../core/locking.h"
58 #include "../../core/route.h"
59 #include "../../core/kemi.h"
60 #include "../../core/rand/kam_rand.h"
61 #include "../../core/rpc.h"
62 #include "../../core/rpc_lookup.h"
65 #include <sys/types.h>
73 static int set_prob(struct sip_msg*, char *, char *);
74 static int reset_prob(struct sip_msg*, char *, char *);
75 static int get_prob(struct sip_msg*, char *, char *);
76 static int rand_event(struct sip_msg*, char *, char *);
77 static int m_sleep(struct sip_msg*, char *, char *);
78 static int m_usleep(struct sip_msg*, char *, char *);
79 static int dbg_abort(struct sip_msg*, char*,char*);
80 static int dbg_pkg_status(struct sip_msg*, char*,char*);
81 static int dbg_shm_status(struct sip_msg*, char*,char*);
82 static int dbg_pkg_summary(struct sip_msg*, char*,char*);
83 static int dbg_shm_summary(struct sip_msg*, char*,char*);
84 static int w_route_exists(struct sip_msg*, char*);
85 static int w_check_route_exists(struct sip_msg*, char*);
87 static int set_gflag(struct sip_msg*, char *, char *);
88 static int reset_gflag(struct sip_msg*, char *, char *);
89 static int is_gflag(struct sip_msg*, char *, char *);
91 static int w_cfg_lock(struct sip_msg*, char *, char *);
92 static int w_cfg_unlock(struct sip_msg*, char *, char *);
93 static int w_cfg_trylock(struct sip_msg*, char *, char *);
96 static int pv_get_random_val(struct sip_msg *msg, pv_param_t *param,
100 static int fixup_prob( void** param, int param_no);
101 static int fixup_gflags( void** param, int param_no);
103 static int fixup_core_hash(void **param, int param_no);
104 static int w_core_hash(struct sip_msg *msg, char *p1, char *p2, char *p3);
106 int bind_cfgutils(cfgutils_api_t *api);
108 static int mod_init(void);
109 static void mod_destroy(void);
111 static int initial_prob = 10;
112 static int *probability = NULL;
114 static char config_hash[MD5_LEN];
115 static char* hash_file = NULL;
117 static int initial_gflags=0;
118 static unsigned int *gflags=0;
119 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;
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 */
129 /* can be applied to original/failed requests and replies */
131 {"rand_reset_prob", (cmd_function)reset_prob, 0, 0, 0,
133 {"rand_get_prob", (cmd_function)get_prob, 0, 0, 0,
135 {"rand_event", (cmd_function)rand_event, 0, 0, 0,
137 {"sleep", (cmd_function)m_sleep, 1, fixup_igp_null, fixup_free_igp_null,
139 {"usleep", (cmd_function)m_usleep, 1, fixup_igp_null, fixup_free_igp_null,
141 {"abort", (cmd_function)dbg_abort, 0, 0, 0,
143 {"pkg_status", (cmd_function)dbg_pkg_status, 0, 0, 0,
145 {"shm_status", (cmd_function)dbg_shm_status, 0, 0, 0,
147 {"pkg_summary", (cmd_function)dbg_pkg_summary, 0, 0, 0,
149 {"shm_summary", (cmd_function)dbg_shm_summary, 0, 0, 0,
151 {"set_gflag", (cmd_function)set_gflag, 1, fixup_gflags, 0,
153 {"reset_gflag", (cmd_function)reset_gflag, 1, fixup_gflags, 0,
155 {"is_gflag", (cmd_function)is_gflag, 1, fixup_gflags, 0,
157 {"lock", (cmd_function)w_cfg_lock, 1, fixup_spve_null, 0,
159 {"unlock", (cmd_function)w_cfg_unlock, 1, fixup_spve_null, 0,
161 {"trylock", (cmd_function)w_cfg_trylock, 1, fixup_spve_null, 0,
163 {"core_hash", (cmd_function)w_core_hash, 3, fixup_core_hash, 0,
165 {"check_route_exists", (cmd_function)w_check_route_exists, 1, fixup_spve_null, fixup_free_spve_null,
167 {"route_if_exists", (cmd_function)w_route_exists, 1, fixup_spve_null, fixup_free_spve_null,
169 {"bind_cfgutils", (cmd_function)bind_cfgutils, 0,
175 static param_export_t params[]={
176 {"initial_probability", INT_PARAM, &initial_prob },
177 {"initial_gflags", INT_PARAM, &initial_gflags },
178 {"hash_file", PARAM_STRING, &hash_file },
179 {"lock_set_size", INT_PARAM, &_cfg_lock_size },
185 static pv_export_t mod_items[] = {
186 { {"RANDOM", sizeof("RANDOM")-1}, PVT_OTHER, pv_get_random_val, 0,
188 { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
192 struct module_exports exports = {
193 "cfgutils", /* module name */
194 DEFAULT_DLFLAGS, /* dlopen flags */
195 cmds, /* cmd (cfg function) exports */
196 params, /* param exports */
197 0, /* RPC method exports */
198 mod_items, /* pseudo-variables exports */
199 0, /* response handling function */
200 mod_init, /* module init function */
201 0, /* per-child init function */
202 mod_destroy /* module destroy function */
205 /**************************** fixup functions ******************************/
206 static int fixup_prob( void** param, int param_no)
208 unsigned int myint = 1000; /* stop if str2int later fail */
211 /* we only fix the parameter #1 */
215 param_str.s=(char*) *param;
216 param_str.len=strlen(param_str.s);
217 str2int(¶m_str, &myint);
220 LM_ERR("invalid probability <%d>\n", myint);
225 *param=(void *)(long)myint;
230 * convert char* to int and do bitwise right-shift
231 * char* must be pkg_alloced and will be freed by the function
233 static int fixup_gflags( void** param, int param_no)
238 /* we only fix the parameter #1 */
242 param_str.s=(char*) *param;
243 param_str.len=strlen(param_str.s);
245 if (str2int(¶m_str, &myint )<0) {
246 LM_ERR("bad number <%s>\n", (char *)(*param));
249 if ( myint >= 8*sizeof(*gflags) ) {
250 LM_ERR("flag <%d> out of "
251 "range [0..%lu]\n", myint, ((unsigned long)8*sizeof(*gflags))-1 );
254 /* convert from flag index to flag bitmap */
256 /* success -- change to int */
258 *param=(void *)(long)myint;
263 /************************** module functions **********************************/
265 static int set_gflag(struct sip_msg *bar, char *flag, char *foo)
267 lock_get(gflags_lock);
268 (*gflags) |= (unsigned int)(long)flag;
269 lock_release(gflags_lock);
274 static int reset_gflag(struct sip_msg *bar, char *flag, char *foo)
276 lock_get(gflags_lock);
277 (*gflags) &= ~ ((unsigned int)(long)flag);
278 lock_release(gflags_lock);
283 static int is_gflag(struct sip_msg *bar, char *flag, char *foo)
285 return ( (*gflags) & ((unsigned int)(long)flag)) ? 1 : -1;
289 void cfgutils_rpc_set_gflag(rpc_t* rpc, void* ctx)
292 if(rpc->scan(ctx, "d", (int*)(&flag))<1) {
293 LM_WARN("no parameters\n");
294 rpc->fault(ctx, 500, "Invalid Parameters");
297 lock_get(gflags_lock);
299 lock_release(gflags_lock);
302 void cfgutils_rpc_reset_gflag(rpc_t* rpc, void* ctx)
305 if(rpc->scan(ctx, "d", (int*)(&flag))<1) {
306 LM_WARN("no parameters\n");
307 rpc->fault(ctx, 500, "Invalid Parameters");
310 lock_get(gflags_lock);
312 lock_release(gflags_lock);
315 void cfgutils_rpc_is_gflag(rpc_t* rpc, void* ctx)
318 if(rpc->scan(ctx, "d", (int*)(&flag))<1) {
319 LM_WARN("no parameters\n");
320 rpc->fault(ctx, 500, "Invalid Parameters");
323 if (((*gflags) & flag) == flag)
324 rpc->add(ctx, "s", "TRUE");
326 rpc->add(ctx, "s", "FALSE");
329 void cfgutils_rpc_get_gflags(rpc_t* rpc, void* ctx)
335 if (rpc->rpl_printf(ctx, "0x%X (%u)", flags, flags) < 0) {
336 rpc->fault(ctx, 500, "Faiure building the response");
341 void cfgutils_rpc_set_prob(rpc_t* rpc, void* ctx)
343 unsigned int percent;
345 if(rpc->scan(ctx, "d", (int*)(&percent))<1) {
346 LM_WARN("no parameters\n");
347 rpc->fault(ctx, 500, "Invalid Parameters");
351 LM_ERR("incorrect probability <%u>\n", percent);
352 rpc->fault(ctx, 500, "Invalid Percent");
355 *probability = percent;
359 void cfgutils_rpc_reset_prob(rpc_t* rpc, void* ctx)
361 *probability = initial_prob;
364 void cfgutils_rpc_get_prob(rpc_t* rpc, void* ctx)
366 if (rpc->rpl_printf(ctx, "actual probability: %u percent",
367 (*probability)) < 0) {
368 rpc->fault(ctx, 500, "Faiure building the response");
373 void cfgutils_rpc_get_hash(rpc_t* rpc, void* ctx)
375 if (rpc->rpl_printf(ctx, "%.*s",
376 MD5_LEN, config_hash) < 0) {
377 rpc->fault(ctx, 500, "Faiure building the response");
384 * Calculate a MD5 digest over a file.
385 * This function assumes 32 bytes in the destination buffer.
386 * \param dest destination
387 * \param file_name file for that the digest should be calculated
388 * \return zero on success, negative on errors
390 static int MD5File(char *dest, const char *file_name)
394 unsigned char buffer[32768];
395 unsigned char hash[16];
396 unsigned int counter, size;
400 if (!dest || !file_name) {
401 LM_ERR("invalid parameter value\n");
405 if (stat(file_name, &stats) != 0) {
406 LM_ERR("could not stat file %s\n", file_name);
409 size = stats.st_size;
412 if((input = fopen(file_name, "rb")) == NULL) {
413 LM_ERR("could not open file %s\n", file_name);
418 counter = (size > sizeof(buffer)) ? sizeof(buffer) : size;
419 if ((counter = fread(buffer, 1, counter, input)) <= 0) {
423 U_MD5Update(&context, buffer, counter);
427 U_MD5Final(hash, &context);
429 string2hex(hash, 16, dest);
430 LM_DBG("MD5 calculated: %.*s for file %s\n", MD5_LEN, dest, file_name);
436 void cfgutils_rpc_check_hash(rpc_t* rpc, void* ctx)
439 memset(tmp, 0, MD5_LEN);
442 rpc->fault(ctx, 500, "No hash file");
446 if (MD5File(tmp, hash_file) != 0) {
447 LM_ERR("could not hash the config file");
448 rpc->fault(ctx, 500, "Failed to hash the file");
452 if (strncmp(config_hash, tmp, MD5_LEN) == 0) {
453 if (rpc->rpl_printf(ctx, "Identical hash") < 0) {
454 rpc->fault(ctx, 500, "Faiure building the response");
458 if (rpc->rpl_printf(ctx, "Different hash") < 0) {
459 rpc->fault(ctx, 500, "Faiure building the response");
465 static const char* cfgutils_rpc_is_gflag_doc[2] = {
466 "Checks if the bits specified by the argument are all set.",
471 static const char* cfgutils_rpc_set_gflag_doc[2] = {
472 "Sets the bits specified by the argument.",
477 static const char* cfgutils_rpc_get_gflags_doc[2] = {
478 "Return the value for global flags.",
483 static const char* cfgutils_rpc_reset_gflag_doc[2] = {
484 "Resets the bits specified by the argument.",
488 static const char* cfgutils_rpc_set_prob_doc[2] = {
489 "Set the random probability.",
492 static const char* cfgutils_rpc_reset_prob_doc[2] = {
493 "Reset the random probability.",
497 static const char* cfgutils_rpc_get_prob_doc[2] = {
498 "Get the random probability.",
502 static const char* cfgutils_rpc_get_hash_doc[2] = {
503 "Get config hash value.",
507 static const char* cfgutils_rpc_check_hash_doc[2] = {
508 "Check config hash value.",
512 static rpc_export_t rpc_cmds[] = {
513 {"cfgutils.is_gflag", cfgutils_rpc_is_gflag,
514 cfgutils_rpc_is_gflag_doc, 0},
515 {"cfgutils.set_gflag", cfgutils_rpc_set_gflag,
516 cfgutils_rpc_set_gflag_doc, 0},
517 {"cfgutils.get_gflags", cfgutils_rpc_get_gflags,
518 cfgutils_rpc_get_gflags_doc, 0},
519 {"cfgutils.reset_gflag", cfgutils_rpc_reset_gflag,
520 cfgutils_rpc_reset_gflag_doc, 0},
521 {"cfgutils.rand_set_prob", cfgutils_rpc_set_prob,
522 cfgutils_rpc_set_prob_doc, 0},
523 {"cfgutils.rand_reset_prob", cfgutils_rpc_reset_prob,
524 cfgutils_rpc_reset_prob_doc, 0},
525 {"cfgutils.rand_get_prob", cfgutils_rpc_get_prob,
526 cfgutils_rpc_get_prob_doc, 0},
527 {"cfgutils.get_config_hash", cfgutils_rpc_get_hash,
528 cfgutils_rpc_get_hash_doc, 0},
529 {"cfgutils.check_config_hash", cfgutils_rpc_check_hash,
530 cfgutils_rpc_check_hash_doc, 0},
535 static int set_prob(struct sip_msg *bar, char *percent_par, char *foo)
537 *probability=(int)(long)percent_par;
541 static int ki_rand_set_prob(sip_msg_t *msg, int percent_par)
543 *probability=percent_par;
547 static int reset_prob(struct sip_msg *bar, char *percent_par, char *foo)
549 *probability=initial_prob;
553 static int ki_rand_reset_prob(sip_msg_t *msg)
555 *probability=initial_prob;
559 static int get_prob(struct sip_msg *bar, char *foo1, char *foo2)
564 static int ki_rand_get_prob(sip_msg_t *bar)
569 static int ki_rand_event(sip_msg_t *msg)
572 /* most of the time this will be disabled completly. Tis will also fix the
573 * problem with the corner cases if rand() returned zero or RAND_MAX */
574 if ((*probability) == 0) return -1;
575 if ((*probability) == 100) return 1;
577 tmp = ((double) kam_rand() / KAM_RAND_MAX);
578 LM_DBG("generated random %f\n", tmp);
579 if (tmp < ((double) (*probability) / 100)) {
580 LM_DBG("return true\n");
584 LM_DBG("return false\n");
589 static int rand_event(struct sip_msg *bar, char *foo1, char *foo2)
591 return ki_rand_event(bar);
594 static int pv_get_random_val(struct sip_msg *msg, pv_param_t *param,
601 if(msg==NULL || res==NULL)
605 ch = int2str(n , &l);
609 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
614 static int m_sleep(struct sip_msg *msg, char *time, char *str2)
617 if(fixup_get_ivalue(msg, (gparam_t*)time, &s)!=0)
619 LM_ERR("cannot get time interval value\n");
622 sleep((unsigned int)s);
626 static int ki_sleep(sip_msg_t* msg, int v)
628 sleep((unsigned int)v);
632 static int m_usleep(struct sip_msg *msg, char *time, char *str2)
635 if(fixup_get_ivalue(msg, (gparam_t*)time, &s)!=0)
637 LM_ERR("cannot get time interval value\n");
640 sleep_us((unsigned int)s);
644 static int ki_usleep(sip_msg_t* msg, int v)
646 sleep_us((unsigned int)v);
650 static int dbg_abort(struct sip_msg* msg, char* foo, char* bar)
652 LM_CRIT("abort called\n");
657 static int ki_abort(sip_msg_t* msg)
659 LM_CRIT("abort called\n");
664 static int dbg_pkg_status(struct sip_msg* msg, char* foo, char* bar)
670 static int ki_pkg_status(sip_msg_t* msg)
676 static int dbg_shm_status(struct sip_msg* msg, char* foo, char* bar)
682 static int ki_shm_status(sip_msg_t* msg)
688 static int dbg_pkg_summary(struct sip_msg* msg, char* foo, char* bar)
694 static int ki_pkg_summary(sip_msg_t* msg)
700 static int dbg_shm_summary(struct sip_msg* msg, char* foo, char* bar)
706 static int ki_shm_summary(sip_msg_t* msg)
712 static int cfg_lock_helper(str *lkey, int mode)
716 if(_cfg_lock_set==NULL) {
717 LM_ERR("lock set not initialized (attempt to do op: %d on: %.*s) -"
718 " see param lock_set_size\n",
719 mode, lkey->len, lkey->s);
722 pos = core_case_hash(lkey, 0, _cfg_lock_size);
724 LM_DBG("cfg_lock mode %d on %u (%.*s)\n", mode, pos, lkey->len, lkey->s);
728 lock_set_get(_cfg_lock_set, pos);
729 } else if (mode == 1) {
731 lock_set_release(_cfg_lock_set, pos);
735 res = lock_set_try(_cfg_lock_set, pos);
737 LM_DBG("Failed to trylock \n");
741 LM_DBG("Succeeded with trylock \n");
742 /* Succeeded in locking */
748 static int cfg_lock(sip_msg_t *msg, str *lkey)
750 return cfg_lock_helper(lkey, 0);
753 static int cfg_unlock(sip_msg_t *msg, str *lkey)
755 return cfg_lock_helper(lkey, 1);
758 static int cfg_trylock(sip_msg_t *msg, str *lkey)
760 return cfg_lock_helper(lkey, 2);
763 static int w_cfg_lock_wrapper(struct sip_msg *msg, gparam_p key, int mode)
769 if(fixup_get_svalue(msg, key, &s)!=0) {
770 LM_ERR("cannot get first parameter\n");
773 return cfg_lock_helper(&s, mode);
776 static int w_cfg_lock(struct sip_msg *msg, char *key, char *s2)
778 return w_cfg_lock_wrapper(msg, (gparam_p)key, 0);
781 static int w_cfg_unlock(struct sip_msg *msg, char *key, char *s2)
783 return w_cfg_lock_wrapper(msg, (gparam_p)key, 1);
786 static int w_cfg_trylock(struct sip_msg *msg, char *key, char *s2)
788 return w_cfg_lock_wrapper(msg, (gparam_p)key, 2);
791 /*! Check if a route block exists - only request routes
793 static int w_check_route_exists(struct sip_msg *msg, char *route)
797 if (fixup_get_svalue(msg, (gparam_p) route, &s) != 0)
799 LM_ERR("invalid route parameter\n");
802 if (route_lookup(&main_rt, s.s)<0) {
809 /*! Run a request route block if it exists
811 static int w_route_exists(struct sip_msg *msg, char *route)
813 struct run_act_ctx ctx;
817 if (fixup_get_svalue(msg, (gparam_p) route, &s) != 0) {
818 LM_ERR("invalid route parameter\n");
822 newroute = route_lookup(&main_rt, s.s);
826 init_run_actions_ctx(&ctx);
827 ret=run_actions(&ctx, main_rt.rlist[newroute], msg);
828 if (ctx.run_flags & EXIT_R_F) {
834 static int mod_init(void)
836 /* Register RPC commands */
837 if (rpc_register_array(rpc_cmds)!=0) {
838 LM_ERR("failed to register RPC commands\n");
843 LM_INFO("no hash_file given, disable hash functionality\n");
845 if (MD5File(config_hash, hash_file) != 0) {
846 LM_ERR("could not hash the config file");
849 LM_DBG("config file hash is %.*s", MD5_LEN, config_hash);
852 if (initial_prob > 100) {
853 LM_ERR("invalid probability <%d>\n", initial_prob);
856 LM_DBG("initial probability %d percent\n", initial_prob);
858 probability=(int *) shm_malloc(sizeof(int));
861 LM_ERR("no shmem available\n");
864 *probability = initial_prob;
866 gflags=(unsigned int *) shm_malloc(sizeof(unsigned int));
868 LM_ERR(" no shmem available\n");
871 *gflags=initial_gflags;
872 gflags_lock = lock_alloc();
873 if (gflags_lock==0) {
874 LM_ERR("cannot allocate gflgas lock\n");
877 if (lock_init(gflags_lock)==NULL) {
878 LM_ERR("cannot initiate gflags lock\n");
879 lock_dealloc(gflags_lock);
882 if(_cfg_lock_size>0) {
883 if(_cfg_lock_size>14) {
884 LM_WARN("lock set size too large (%d), making it 14\n",
888 _cfg_lock_size = 1<<_cfg_lock_size;
889 _cfg_lock_set = lock_set_alloc(_cfg_lock_size);
890 if(_cfg_lock_set==NULL || lock_set_init(_cfg_lock_set)==NULL) {
891 LM_ERR("cannot initiate lock set\n");
899 static void mod_destroy(void)
902 shm_free(probability);
906 lock_destroy(gflags_lock);
907 lock_dealloc(gflags_lock);
909 if(_cfg_lock_set!=NULL)
911 lock_set_destroy(_cfg_lock_set);
912 lock_set_dealloc(_cfg_lock_set);
913 _cfg_lock_set = NULL;
920 int cfgutils_lock(str *lkey)
922 return cfg_lock_helper(lkey, 0);
928 int cfgutils_unlock(str *lkey)
930 return cfg_lock_helper(lkey, 1);
933 static int fixup_core_hash(void **param, int param_no)
936 return fixup_spve_null(param, 1);
937 else if (param_no == 2)
938 return fixup_spve_null(param, 1);
939 else if (param_no == 3)
940 return fixup_igp_null(param, 1);
945 static int w_core_hash(struct sip_msg *msg, char *p1, char *p2, char *p3)
950 if (fixup_get_svalue(msg, (gparam_p) p1, &s1) != 0)
952 LM_ERR("invalid s1 paramerer\n");
955 if (fixup_get_svalue(msg, (gparam_p) p2, &s2) != 0)
957 LM_ERR("invalid s2 paramerer\n");
960 if (fixup_get_ivalue(msg, (gparam_p) p3, &size) != 0)
962 LM_ERR("invalid size paramerer\n");
966 if (size <= 0) size = 2;
967 else size = 1 << size;
969 /* Return value _MUST_ be > 0 */
970 return core_hash(&s1, s2.len ? &s2 : NULL, size) + 1;
973 static int ki_core_hash(sip_msg_t *msg, str *s1, str *s2, int sz)
979 if (size <= 0) size = 2;
980 else size = 1 << size;
982 return core_hash(s1, (s2 && s2->len>0)?s2:NULL, size) + 1;
986 * @brief bind functions to CFGUTILS API structure
988 int bind_cfgutils(cfgutils_api_t *api)
991 ERR("Invalid parameter value\n");
994 api->mlock = cfgutils_lock;
995 api->munlock = cfgutils_unlock;
1004 /* clang-format off */
1005 static sr_kemi_t sr_kemi_cfgutils_exports[] = {
1006 { str_init("cfgutils"), str_init("lock"),
1007 SR_KEMIP_INT, cfg_lock,
1008 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1009 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1011 { str_init("cfgutils"), str_init("unlock"),
1012 SR_KEMIP_INT, cfg_unlock,
1013 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1014 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1016 { str_init("cfgutils"), str_init("trylock"),
1017 SR_KEMIP_INT, cfg_trylock,
1018 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1019 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1021 { str_init("cfgutils"), str_init("rand_set_prob"),
1022 SR_KEMIP_INT, ki_rand_set_prob,
1023 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1024 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1026 { str_init("cfgutils"), str_init("rand_reset_prob"),
1027 SR_KEMIP_INT, ki_rand_reset_prob,
1028 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1029 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1031 { str_init("cfgutils"), str_init("rand_get_prob"),
1032 SR_KEMIP_INT, ki_rand_get_prob,
1033 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1034 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1036 { str_init("cfgutils"), str_init("rand_event"),
1037 SR_KEMIP_INT, ki_rand_event,
1038 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1039 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1041 { str_init("cfgutils"), str_init("abort"),
1042 SR_KEMIP_INT, ki_abort,
1043 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1044 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1046 { str_init("cfgutils"), str_init("pkg_status"),
1047 SR_KEMIP_INT, ki_pkg_status,
1048 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1049 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1051 { str_init("cfgutils"), str_init("shm_status"),
1052 SR_KEMIP_INT, ki_shm_status,
1053 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1054 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1056 { str_init("cfgutils"), str_init("pkg_summary"),
1057 SR_KEMIP_INT, ki_pkg_summary,
1058 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1059 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1061 { str_init("cfgutils"), str_init("shm_summary"),
1062 SR_KEMIP_INT, ki_shm_summary,
1063 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1064 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1066 { str_init("cfgutils"), str_init("core_hash"),
1067 SR_KEMIP_INT, ki_core_hash,
1068 { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_INT,
1069 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1071 { str_init("cfgutils"), str_init("sleep"),
1072 SR_KEMIP_INT, ki_sleep,
1073 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1074 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1076 { str_init("cfgutils"), str_init("usleep"),
1077 SR_KEMIP_INT, ki_usleep,
1078 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1079 SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1082 { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
1084 /* clang-format on */
1089 int mod_register(char *path, int *dlflags, void *p1, void *p2)
1091 sr_kemi_modules_add(sr_kemi_cfgutils_exports);