00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #define FIFO_SET_PROB "rand_set_prob"
00047 #define FIFO_RESET_PROB "rand_reset_prob"
00048 #define FIFO_GET_PROB "rand_get_prob"
00049 #define FIFO_GET_HASH "get_config_hash"
00050 #define FIFO_CHECK_HASH "check_config_hash"
00051
00052
00053 #define MAX_FLAG_LEN 12
00054
00055 #define FIFO_SET_GFLAG "set_gflag"
00056 #define FIFO_IS_GFLAG "is_gflag"
00057 #define FIFO_RESET_GFLAG "reset_gflag"
00058 #define FIFO_GET_GFLAGS "get_gflags"
00059
00060 #include "../../sr_module.h"
00061 #include "../../error.h"
00062 #include "../../pvar.h"
00063 #include "../../ut.h"
00064 #include "../../mem/mem.h"
00065 #include "../../mem/shm_mem.h"
00066 #include "../../lib/kmi/mi.h"
00067 #include "../../mod_fix.h"
00068 #include "../../md5.h"
00069 #include "../../md5utils.h"
00070 #include "../../globals.h"
00071 #include "../../hashes.h"
00072 #include "../../locking.h"
00073 #include <stdio.h>
00074 #include <stdlib.h>
00075 #include <sys/types.h>
00076 #include <sys/stat.h>
00077 #include <unistd.h>
00078
00079 #include "api.h"
00080
00081 MODULE_VERSION
00082
00083 static int set_prob(struct sip_msg*, char *, char *);
00084 static int reset_prob(struct sip_msg*, char *, char *);
00085 static int get_prob(struct sip_msg*, char *, char *);
00086 static int rand_event(struct sip_msg*, char *, char *);
00087 static int m_sleep(struct sip_msg*, char *, char *);
00088 static int m_usleep(struct sip_msg*, char *, char *);
00089 static int dbg_abort(struct sip_msg*, char*,char*);
00090 static int dbg_pkg_status(struct sip_msg*, char*,char*);
00091 static int dbg_shm_status(struct sip_msg*, char*,char*);
00092 static int dbg_pkg_summary(struct sip_msg*, char*,char*);
00093 static int dbg_shm_summary(struct sip_msg*, char*,char*);
00094
00095 static int set_gflag(struct sip_msg*, char *, char *);
00096 static int reset_gflag(struct sip_msg*, char *, char *);
00097 static int is_gflag(struct sip_msg*, char *, char *);
00098
00099 static int cfg_lock(struct sip_msg*, char *, char *);
00100 static int cfg_unlock(struct sip_msg*, char *, char *);
00101
00102 static struct mi_root* mi_set_prob(struct mi_root* cmd, void* param );
00103 static struct mi_root* mi_reset_prob(struct mi_root* cmd, void* param );
00104 static struct mi_root* mi_get_prob(struct mi_root* cmd, void* param );
00105 static struct mi_root* mi_get_hash(struct mi_root* cmd, void* param );
00106 static struct mi_root* mi_check_hash(struct mi_root* cmd, void* param );
00107
00108 static struct mi_root* mi_set_gflag(struct mi_root* cmd, void* param );
00109 static struct mi_root* mi_reset_gflag(struct mi_root* cmd, void* param );
00110 static struct mi_root* mi_is_gflag(struct mi_root* cmd, void* param );
00111 static struct mi_root* mi_get_gflags(struct mi_root* cmd, void* param );
00112
00113
00114 static int pv_get_random_val(struct sip_msg *msg, pv_param_t *param,
00115 pv_value_t *res);
00116
00117
00118 static int fixup_prob( void** param, int param_no);
00119 static int fixup_gflags( void** param, int param_no);
00120
00121 static int fixup_core_hash(void **param, int param_no);
00122 static int w_core_hash(struct sip_msg *msg, char *p1, char *p2, char *p3);
00123
00124 int bind_cfgutils(cfgutils_api_t *api);
00125
00126 static int mod_init(void);
00127 static void mod_destroy(void);
00128
00129 static int initial_prob = 10;
00130 static int *probability;
00131
00132 static char config_hash[MD5_LEN];
00133 static char* hash_file = NULL;
00134
00135 static int initial_gflags=0;
00136 static unsigned int *gflags=0;
00137
00138 static gen_lock_set_t *_cfg_lock_set = NULL;
00139 static unsigned int _cfg_lock_size = 0;
00140
00141 static cmd_export_t cmds[]={
00142 {"rand_set_prob",
00143 (cmd_function)set_prob,
00144 1,
00145 fixup_prob, 0,
00146
00147 ANY_ROUTE},
00148 {"rand_reset_prob", (cmd_function)reset_prob, 0, 0, 0,
00149 ANY_ROUTE},
00150 {"rand_get_prob", (cmd_function)get_prob, 0, 0, 0,
00151 ANY_ROUTE},
00152 {"rand_event", (cmd_function)rand_event, 0, 0, 0,
00153 ANY_ROUTE},
00154 {"sleep", (cmd_function)m_sleep, 1, fixup_uint_null, 0,
00155 ANY_ROUTE},
00156 {"usleep", (cmd_function)m_usleep, 1, fixup_uint_null, 0,
00157 ANY_ROUTE},
00158 {"abort", (cmd_function)dbg_abort, 0, 0, 0,
00159 ANY_ROUTE},
00160 {"pkg_status", (cmd_function)dbg_pkg_status, 0, 0, 0,
00161 ANY_ROUTE},
00162 {"shm_status", (cmd_function)dbg_shm_status, 0, 0, 0,
00163 ANY_ROUTE},
00164 {"pkg_summary", (cmd_function)dbg_pkg_summary, 0, 0, 0,
00165 ANY_ROUTE},
00166 {"shm_summary", (cmd_function)dbg_shm_summary, 0, 0, 0,
00167 ANY_ROUTE},
00168 {"set_gflag", (cmd_function)set_gflag, 1, fixup_gflags, 0,
00169 ANY_ROUTE},
00170 {"reset_gflag", (cmd_function)reset_gflag, 1, fixup_gflags, 0,
00171 ANY_ROUTE},
00172 {"is_gflag", (cmd_function)is_gflag, 1, fixup_gflags, 0,
00173 ANY_ROUTE},
00174 {"lock", (cmd_function)cfg_lock, 1, fixup_spve_null, 0,
00175 ANY_ROUTE},
00176 {"unlock", (cmd_function)cfg_unlock, 1, fixup_spve_null, 0,
00177 ANY_ROUTE},
00178 {"core_hash", (cmd_function)w_core_hash, 3, fixup_core_hash, 0,
00179 ANY_ROUTE},
00180 {"bind_cfgutils", (cmd_function)bind_cfgutils, 0,
00181 0, 0, 0},
00182 {0, 0, 0, 0, 0, 0}
00183 };
00184
00185
00186 static param_export_t params[]={
00187 {"initial_probability", INT_PARAM, &initial_prob },
00188 {"initial_gflags", INT_PARAM, &initial_gflags },
00189 {"hash_file", STR_PARAM, &hash_file },
00190 {"lock_set_size", INT_PARAM, &_cfg_lock_size },
00191 {0,0,0}
00192 };
00193
00194
00195 static mi_export_t mi_cmds[] = {
00196 { FIFO_SET_PROB, mi_set_prob, 0, 0, 0 },
00197 { FIFO_RESET_PROB, mi_reset_prob, MI_NO_INPUT_FLAG, 0, 0 },
00198 { FIFO_GET_PROB, mi_get_prob, MI_NO_INPUT_FLAG, 0, 0 },
00199 { FIFO_GET_HASH, mi_get_hash, MI_NO_INPUT_FLAG, 0, 0 },
00200 { FIFO_CHECK_HASH, mi_check_hash, MI_NO_INPUT_FLAG, 0, 0 },
00201 { FIFO_SET_GFLAG, mi_set_gflag, 0, 0, 0 },
00202 { FIFO_RESET_GFLAG, mi_reset_gflag, 0, 0, 0 },
00203 { FIFO_IS_GFLAG, mi_is_gflag, 0, 0, 0 },
00204 { FIFO_GET_GFLAGS, mi_get_gflags, MI_NO_INPUT_FLAG, 0, 0 },
00205 { 0, 0, 0, 0, 0}
00206 };
00207
00208
00209 static pv_export_t mod_items[] = {
00210 { {"RANDOM", sizeof("RANDOM")-1}, PVT_OTHER, pv_get_random_val, 0,
00211 0, 0, 0, 0 },
00212 { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
00213 };
00214
00215
00216 struct module_exports exports = {
00217 "cfgutils",
00218 DEFAULT_DLFLAGS,
00219 cmds,
00220 params,
00221 0,
00222 mi_cmds,
00223 mod_items,
00224 0,
00225 mod_init,
00226 0,
00227 mod_destroy,
00228 0
00229 };
00230
00231
00232
00233 static int fixup_prob( void** param, int param_no)
00234 {
00235 unsigned int myint;
00236 str param_str;
00237
00238
00239 if (param_no!=1)
00240 return 0;
00241
00242 param_str.s=(char*) *param;
00243 param_str.len=strlen(param_str.s);
00244 str2int(¶m_str, &myint);
00245
00246 if (myint > 100) {
00247 LM_ERR("invalid probability <%d>\n", myint);
00248 return E_CFG;
00249 }
00250
00251 pkg_free(*param);
00252 *param=(void *)(long)myint;
00253 return 0;
00254 }
00255
00260 static int fixup_gflags( void** param, int param_no)
00261 {
00262 unsigned int myint;
00263 str param_str;
00264
00265
00266 if (param_no!=1)
00267 return 0;
00268
00269 param_str.s=(char*) *param;
00270 param_str.len=strlen(param_str.s);
00271
00272 if (str2int(¶m_str, &myint )<0) {
00273 LM_ERR("bad number <%s>\n", (char *)(*param));
00274 return E_CFG;
00275 }
00276 if ( myint >= 8*sizeof(*gflags) ) {
00277 LM_ERR("flag <%d> out of "
00278 "range [0..%lu]\n", myint, ((unsigned long)8*sizeof(*gflags))-1 );
00279 return E_CFG;
00280 }
00281
00282 myint = 1 << myint;
00283
00284 pkg_free(*param);
00285 *param=(void *)(long)myint;
00286 return 0;
00287 }
00288
00289
00290
00291
00292 static int set_gflag(struct sip_msg *bar, char *flag, char *foo)
00293 {
00294 (*gflags) |= (unsigned int)(long)flag;
00295 return 1;
00296 }
00297
00298
00299 static int reset_gflag(struct sip_msg *bar, char *flag, char *foo)
00300 {
00301 (*gflags) &= ~ ((unsigned int)(long)flag);
00302 return 1;
00303 }
00304
00305
00306 static int is_gflag(struct sip_msg *bar, char *flag, char *foo)
00307 {
00308 return ( (*gflags) & ((unsigned int)(long)flag)) ? 1 : -1;
00309 }
00310
00311
00312 static struct mi_root* mi_set_gflag(struct mi_root* cmd_tree, void* param )
00313 {
00314 unsigned int flag;
00315 struct mi_node* node;
00316
00317 node = cmd_tree->node.kids;
00318 if(node == NULL)
00319 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00320
00321 flag = 0;
00322 if( strno2int( &node->value, &flag) <0)
00323 goto error;
00324 if (!flag) {
00325 LM_ERR("incorrect flag\n");
00326 goto error;
00327 }
00328
00329 (*gflags) |= flag;
00330
00331 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00332 error:
00333 return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00334 }
00335
00336
00337 static struct mi_root* mi_reset_gflag(struct mi_root* cmd_tree, void* param )
00338 {
00339 unsigned int flag;
00340 struct mi_node* node = NULL;
00341
00342 node = cmd_tree->node.kids;
00343 if(node == NULL)
00344 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00345
00346 flag = 0;
00347 if( strno2int( &node->value, &flag) <0)
00348 goto error;
00349 if (!flag) {
00350 LM_ERR("incorrect flag\n");
00351 goto error;
00352 }
00353
00354 (*gflags) &= ~ flag;
00355
00356 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00357 error:
00358 return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00359 }
00360
00361
00362 static struct mi_root* mi_is_gflag(struct mi_root* cmd_tree, void* param )
00363 {
00364 unsigned int flag;
00365 struct mi_root* rpl_tree = NULL;
00366 struct mi_node* node = NULL;
00367
00368 node = cmd_tree->node.kids;
00369 if(node == NULL)
00370 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00371
00372 flag = 0;
00373 if( strno2int( &node->value, &flag) <0)
00374 goto error_param;
00375 if (!flag) {
00376 LM_ERR("incorrect flag\n");
00377 goto error_param;
00378 }
00379
00380 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00381 if(rpl_tree ==0)
00382 return 0;
00383
00384 if( ((*gflags) & flag)== flag )
00385 node = add_mi_node_child( &rpl_tree->node, 0, 0, 0, "TRUE", 4);
00386 else
00387 node = add_mi_node_child( &rpl_tree->node, 0, 0, 0, "FALSE", 5);
00388
00389 if(node == NULL)
00390 {
00391 LM_ERR("failed to add node\n");
00392 free_mi_tree(rpl_tree);
00393 return 0;
00394 }
00395
00396 return rpl_tree;
00397 error_param:
00398 return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00399 }
00400
00401
00402 static struct mi_root* mi_get_gflags(struct mi_root* cmd_tree, void* param )
00403 {
00404 struct mi_root* rpl_tree= NULL;
00405 struct mi_node* node= NULL;
00406
00407 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
00408 if(rpl_tree == NULL)
00409 return 0;
00410
00411 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "0x%X",(*gflags));
00412 if(node == NULL)
00413 goto error;
00414
00415 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%u",(*gflags));
00416 if(node == NULL)
00417 goto error;
00418
00419 return rpl_tree;
00420 error:
00421 free_mi_tree(rpl_tree);
00422 return 0;
00423 }
00424
00425
00426 static struct mi_root* mi_set_prob(struct mi_root* cmd, void* param )
00427 {
00428 unsigned int percent;
00429 struct mi_node* node;
00430
00431 node = cmd->node.kids;
00432 if(node == NULL)
00433 return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
00434
00435 if( str2int( &node->value, &percent) <0)
00436 goto error;
00437 if (percent > 100) {
00438 LM_ERR("incorrect probability <%u>\n", percent);
00439 goto error;
00440 }
00441 *probability = percent;
00442 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
00443
00444 error:
00445 return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
00446 }
00447
00448 static struct mi_root* mi_reset_prob(struct mi_root* cmd, void* param )
00449 {
00450
00451 *probability = initial_prob;
00452 return init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
00453 }
00454
00455 static struct mi_root* mi_get_prob(struct mi_root* cmd, void* param )
00456 {
00457 struct mi_root* rpl_tree= NULL;
00458 struct mi_node* node= NULL;
00459 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
00460 if(rpl_tree == NULL)
00461 return 0;
00462 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "actual probability: %u percent\n",(*probability));
00463 if(node == NULL)
00464 goto error;
00465
00466 return rpl_tree;
00467
00468 error:
00469 free_mi_tree(rpl_tree);
00470 return 0;
00471 }
00472
00473 static struct mi_root* mi_get_hash(struct mi_root* cmd, void* param )
00474 {
00475 struct mi_root* rpl_tree= NULL;
00476 struct mi_node* node= NULL;
00477
00478 if (!hash_file) {
00479 LM_INFO("no hash_file given, disable hash functionality\n");
00480 rpl_tree = init_mi_tree(404, "Functionality disabled\n", 23);
00481 } else {
00482 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
00483 if(rpl_tree == NULL)
00484 return 0;
00485 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "%.*s\n", MD5_LEN, config_hash);
00486 if(node == NULL)
00487 goto error;
00488 }
00489 return rpl_tree;
00490
00491 error:
00492 free_mi_tree(rpl_tree);
00493 return 0;
00494 }
00495
00496
00504 static int MD5File(char *dest, const char *file_name)
00505 {
00506 MD5_CTX context;
00507 FILE *input;
00508 unsigned char buffer[32768];
00509 unsigned char hash[16];
00510 unsigned int counter, size;
00511
00512 struct stat stats;
00513
00514 if (!dest || !file_name) {
00515 LM_ERR("invalid parameter value\n");
00516 return -1;
00517 }
00518
00519 if (stat(file_name, &stats) != 0) {
00520 LM_ERR("could not stat file %s\n", file_name);
00521 return -1;
00522 }
00523 size = stats.st_size;
00524
00525 MD5Init(&context);
00526 if((input = fopen(file_name, "rb")) == NULL) {
00527 LM_ERR("could not open file %s\n", file_name);
00528 return -1;
00529 }
00530
00531 while(size) {
00532 counter = (size > sizeof(buffer)) ? sizeof(buffer) : size;
00533 if ((counter = fread(buffer, 1, counter, input)) <= 0) {
00534 fclose(input);
00535 return -1;
00536 }
00537 U_MD5Update(&context, buffer, counter);
00538 size -= counter;
00539 }
00540 fclose(input);
00541 U_MD5Final(hash, &context);
00542
00543 string2hex(hash, 16, dest);
00544 LM_DBG("MD5 calculated: %.*s for file %s\n", MD5_LEN, dest, file_name);
00545
00546 return 0;
00547 }
00548
00549
00550 static struct mi_root* mi_check_hash(struct mi_root* cmd, void* param )
00551 {
00552 struct mi_root* rpl_tree= NULL;
00553 struct mi_node* node= NULL;
00554 char tmp[MD5_LEN];
00555 memset(tmp, 0, MD5_LEN);
00556
00557 if (!hash_file) {
00558 LM_INFO("no hash_file given, disable hash functionality\n");
00559 rpl_tree = init_mi_tree(404, "Functionality disabled\n", 23);
00560 } else {
00561 if (MD5File(tmp, hash_file) != 0) {
00562 LM_ERR("could not hash the config file");
00563 rpl_tree = init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN );
00564 return rpl_tree;
00565 }
00566
00567 if (strncmp(config_hash, tmp, MD5_LEN) == 0) {
00568 rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN );
00569 if(rpl_tree == NULL)
00570 return 0;
00571 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "The actual config file hash is identical to the stored one.\n");
00572 } else {
00573 rpl_tree = init_mi_tree( 400, "Error", 5 );
00574 if(rpl_tree == NULL)
00575 return 0;
00576 node = addf_mi_node_child( &rpl_tree->node, 0, 0, 0, "The actual config file hash is not identical to the stored one.\n");
00577 }
00578 if(node == NULL)
00579 goto error;
00580 }
00581
00582 return rpl_tree;
00583
00584 error:
00585 free_mi_tree(rpl_tree);
00586 return 0;
00587 }
00588
00589 static int set_prob(struct sip_msg *bar, char *percent_par, char *foo)
00590 {
00591 *probability=(int)(long)percent_par;
00592 return 1;
00593 }
00594
00595 static int reset_prob(struct sip_msg *bar, char *percent_par, char *foo)
00596 {
00597 *probability=initial_prob;
00598 return 1;
00599 }
00600
00601 static int get_prob(struct sip_msg *bar, char *foo1, char *foo2)
00602 {
00603 return *probability;
00604 }
00605
00606 static int rand_event(struct sip_msg *bar, char *foo1, char *foo2)
00607 {
00608 double tmp;
00609
00610
00611 if ((*probability) == 0) return -1;
00612 if ((*probability) == 100) return 1;
00613
00614 tmp = ((double) rand() / RAND_MAX);
00615 LM_DBG("generated random %f\n", tmp);
00616 if (tmp < ((double) (*probability) / 100)) {
00617 LM_DBG("return true\n");
00618 return 1;
00619 }
00620 else {
00621 LM_DBG("return false\n");
00622 return -1;
00623 }
00624 }
00625
00626 static int pv_get_random_val(struct sip_msg *msg, pv_param_t *param,
00627 pv_value_t *res)
00628 {
00629 int n;
00630 int l = 0;
00631 char *ch;
00632
00633 if(msg==NULL || res==NULL)
00634 return -1;
00635
00636 n = rand();
00637 ch = int2str(n , &l);
00638 res->rs.s = ch;
00639 res->rs.len = l;
00640 res->ri = n;
00641 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
00642
00643 return 0;
00644 }
00645
00646 static int m_sleep(struct sip_msg *msg, char *time, char *str2)
00647 {
00648 LM_DBG("sleep %lu seconds\n", (unsigned long)time);
00649 sleep((unsigned int)(unsigned long)time);
00650 return 1;
00651 }
00652
00653 static int m_usleep(struct sip_msg *msg, char *time, char *str2)
00654 {
00655 LM_DBG("sleep %lu microseconds\n", (unsigned long)time);
00656 sleep_us((unsigned int)(unsigned long)time);
00657 return 1;
00658 }
00659
00660 static int dbg_abort(struct sip_msg* msg, char* foo, char* bar)
00661 {
00662 LM_CRIT("abort called\n");
00663 abort();
00664 return 0;
00665 }
00666
00667 static int dbg_pkg_status(struct sip_msg* msg, char* foo, char* bar)
00668 {
00669 pkg_status();
00670 return 1;
00671 }
00672
00673 static int dbg_shm_status(struct sip_msg* msg, char* foo, char* bar)
00674 {
00675 shm_status();
00676 return 1;
00677 }
00678
00679 static int dbg_pkg_summary(struct sip_msg* msg, char* foo, char* bar)
00680 {
00681 pkg_sums();
00682 return 1;
00683 }
00684
00685 static int dbg_shm_summary(struct sip_msg* msg, char* foo, char* bar)
00686 {
00687 shm_sums();
00688 return 1;
00689 }
00690
00691 int cfg_lock_helper(str *lkey, int mode)
00692 {
00693 unsigned int pos;
00694 pos = core_case_hash(lkey, 0, _cfg_lock_size);
00695 LM_DBG("cfg_lock mode %d on %u\n", mode, pos);
00696 if(mode==0)
00697 lock_set_get(_cfg_lock_set, pos);
00698 else
00699 lock_set_release(_cfg_lock_set, pos);
00700 return 1;
00701 }
00702
00703 int cfg_lock_wrapper(struct sip_msg *msg, gparam_p key, int mode)
00704 {
00705 str s;
00706 if(fixup_get_svalue(msg, key, &s)!=0)
00707 {
00708 LM_ERR("cannot get first parameter\n");
00709 return -1;
00710 }
00711 return cfg_lock_helper(&s, mode);
00712 }
00713
00714 static int cfg_lock(struct sip_msg *msg, char *key, char *s2)
00715 {
00716 if(_cfg_lock_set==NULL || key==NULL)
00717 return -1;
00718 return cfg_lock_wrapper(msg, (gparam_p)key, 0);
00719 }
00720
00721 static int cfg_unlock(struct sip_msg *msg, char *key, char *s2)
00722 {
00723 if(_cfg_lock_set==NULL || key==NULL)
00724 return -1;
00725 return cfg_lock_wrapper(msg, (gparam_p)key, 1);
00726 }
00727
00728
00729 static int mod_init(void)
00730 {
00731 if(register_mi_mod(exports.name, mi_cmds)!=0)
00732 {
00733 LM_ERR("failed to register MI commands\n");
00734 return -1;
00735 }
00736
00737 if (!hash_file) {
00738 LM_INFO("no hash_file given, disable hash functionality\n");
00739 } else {
00740 if (MD5File(config_hash, hash_file) != 0) {
00741 LM_ERR("could not hash the config file");
00742 return -1;
00743 }
00744 LM_DBG("config file hash is %.*s", MD5_LEN, config_hash);
00745 }
00746
00747 if (initial_prob > 100) {
00748 LM_ERR("invalid probability <%d>\n", initial_prob);
00749 return -1;
00750 }
00751 LM_DBG("initial probability %d percent\n", initial_prob);
00752
00753 probability=(int *) shm_malloc(sizeof(int));
00754
00755 if (!probability) {
00756 LM_ERR("no shmem available\n");
00757 return -1;
00758 }
00759 *probability = initial_prob;
00760
00761 gflags=(unsigned int *) shm_malloc(sizeof(unsigned int));
00762 if (!gflags) {
00763 LM_ERR(" no shmem available\n");
00764 return -1;
00765 }
00766 *gflags=initial_gflags;
00767 if(_cfg_lock_size>0 && _cfg_lock_size<=10)
00768 {
00769 _cfg_lock_size = 1<<_cfg_lock_size;
00770 _cfg_lock_set = lock_set_alloc(_cfg_lock_size);
00771 if(_cfg_lock_set==NULL || lock_set_init(_cfg_lock_set)==NULL)
00772 {
00773 LM_ERR("cannot initiate lock set\n");
00774 return -1;
00775 }
00776 }
00777 return 0;
00778 }
00779
00780
00781 static void mod_destroy(void)
00782 {
00783 if (probability)
00784 shm_free(probability);
00785 if (gflags)
00786 shm_free(gflags);
00787 if(_cfg_lock_set!=NULL)
00788 {
00789 lock_set_destroy(_cfg_lock_set);
00790 lock_set_dealloc(_cfg_lock_set);
00791 }
00792 }
00793
00797 int cfgutils_lock(str *lkey)
00798 {
00799 return cfg_lock_helper(lkey, 0);
00800 }
00801
00805 int cfgutils_unlock(str *lkey)
00806 {
00807 return cfg_lock_helper(lkey, 1);
00808 }
00809
00810 static int fixup_core_hash(void **param, int param_no)
00811 {
00812 if (param_no == 1)
00813 return fixup_spve_null(param, 1);
00814 else if (param_no == 2)
00815 return fixup_spve_null(param, 1);
00816 else if (param_no == 3)
00817 return fixup_igp_null(param, 1);
00818 else
00819 return 0;
00820 }
00821
00822 static int w_core_hash(struct sip_msg *msg, char *p1, char *p2, char *p3)
00823 {
00824 str s1, s2;
00825 int size;
00826
00827 if (fixup_get_svalue(msg, (gparam_p) p1, &s1) != 0)
00828 {
00829 LM_ERR("invalid s1 paramerer\n");
00830 return -1;
00831 }
00832 if (fixup_get_svalue(msg, (gparam_p) p2, &s2) != 0)
00833 {
00834 LM_ERR("invalid s2 paramerer\n");
00835 return -1;
00836 }
00837 if (fixup_get_ivalue(msg, (gparam_p) p3, &size) != 0)
00838 {
00839 LM_ERR("invalid size paramerer\n");
00840 return -1;
00841 }
00842
00843 if (size <= 0) size = 2;
00844 else size = 1 << size;
00845
00846
00847 return core_hash(&s1, s2.len ? &s2 : NULL, size) + 1;
00848 }
00849
00853 int bind_cfgutils(cfgutils_api_t *api)
00854 {
00855 if (!api) {
00856 ERR("Invalid parameter value\n");
00857 return -1;
00858 }
00859 api->mlock = cfgutils_lock;
00860 api->munlock = cfgutils_unlock;
00861
00862 return 0;
00863 }