modules_k/dispatcher/dispatcher.c
31ccf6a2
 /**
  * $Id$
  *
  * dispatcher module -- stateless load balancing
  *
ba07eb39
  * Copyright (C) 2004-2005 FhG Fokus
  * Copyright (C) 2006 Voice Sistem SRL
31ccf6a2
  *
27642a08
  * This file is part of Kamailio, a free SIP server.
31ccf6a2
  *
27642a08
  * Kamailio is free software; you can redistribute it and/or modify
31ccf6a2
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
27642a08
  * Kamailio is distributed in the hope that it will be useful,
31ccf6a2
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * History
  * -------
  * 2004-07-31  first version, by daniel
081b5d4e
  * 2007-01-11  Added a function to check if a specific gateway is in a group
  *				(carsten - Carsten Bock, BASIS AudioNet GmbH)
  * 2007-02-09  Added active probing of failed destinations and automatic
  *				re-enabling of destinations (carsten)
  * 2007-05-08  Ported the changes to SVN-Trunk and renamed ds_is_domain
  *				to ds_is_from_list.  (carsten)
101e9af4
  * 2007-07-18  Added support for load/reload groups from DB 
  * 			   reload triggered from ds_reload MI_Command (ancuta)
31ccf6a2
  */
 
aecdbe9b
 /*! \file
  * \ingroup dispatcher
  * \brief Dispatcher :: Dispatch
  */
 
 /*! \defgroup dispatcher Dispatcher :: Load balancing and failover module
  * 	The dispatcher module implements a set of functions for distributing SIP requests on a 
  *	set of servers, but also grouping of server resources.
  *
  *	- The module has an internal API exposed to other modules.
  *	- The module implements a couple of MI functions for managing the list of server resources
  */
 
31ccf6a2
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <unistd.h>
 
c497c466
 #include "../../lib/kmi/mi.h"
31ccf6a2
 #include "../../sr_module.h"
 #include "../../dprint.h"
 #include "../../error.h"
 #include "../../ut.h"
a4ba0359
 #include "../../route.h"
31ccf6a2
 #include "../../mem/mem.h"
dfb0caa1
 #include "../../mod_fix.h"
31ccf6a2
 
59c31fe7
 #include "ds_ht.h"
31ccf6a2
 #include "dispatch.h"
 
 MODULE_VERSION
 
9de77c2b
 #define DS_SET_ID_COL			"setid"
 #define DS_DEST_URI_COL			"destination"
 #define DS_DEST_FLAGS_COL		"flags"
 #define DS_DEST_PRIORITY_COL	"priority"
65160302
 #define DS_DEST_ATTRS_COL		"attrs"
9de77c2b
 #define DS_TABLE_NAME			"dispatcher"
101e9af4
 
31ccf6a2
 /** parameters */
 char *dslistfile = CFG_DIR"dispatcher.list";
a4ba0359
 int  ds_force_dst   = 0;
 int  ds_flags       = 0; 
 int  ds_use_default = 0; 
e2cf6343
 static str dst_avp_param = {NULL, 0};
 static str grp_avp_param = {NULL, 0};
 static str cnt_avp_param = {NULL, 0};
095ab21d
 str hash_pvar_param = {NULL, 0};
 
8cdef0e8
 int_str dst_avp_name;
 unsigned short dst_avp_type;
 int_str grp_avp_name;
 unsigned short grp_avp_type;
 int_str cnt_avp_name;
 unsigned short cnt_avp_type;
 
e26079d5
 pv_elem_t * hash_param_model = NULL;
095ab21d
 
081b5d4e
 int probing_threshhold = 3; /* number of failed requests, before a destination
 							   is taken into probing */
101e9af4
 str ds_ping_method = {"OPTIONS",7};
 str ds_ping_from   = {"sip:dispatcher@localhost", 24};
 static int ds_ping_interval = 0;
8381c032
 int ds_probing_mode  = 0;
 int ds_append_branch = 1;
59c31fe7
 int ds_hash_size = 0;
 int ds_hash_expire = 7200;
101e9af4
 
2e561eca
 /* tm */
 struct tm_binds tmb;
 
101e9af4
 /*db */
9de77c2b
 str ds_db_url            = {NULL, 0};
 str ds_set_id_col        = str_init(DS_SET_ID_COL);
 str ds_dest_uri_col      = str_init(DS_DEST_URI_COL);
 str ds_dest_flags_col    = str_init(DS_DEST_FLAGS_COL);
 str ds_dest_priority_col = str_init(DS_DEST_PRIORITY_COL);
65160302
 str ds_dest_attrs_col    = str_init(DS_DEST_ATTRS_COL);
9de77c2b
 str ds_table_name        = str_init(DS_TABLE_NAME);
101e9af4
 
b14bb7d7
 str ds_setid_pvname   = {NULL, 0};
 pv_spec_t ds_setid_pv;
31ccf6a2
 
 /** module functions */
 static int mod_init(void);
 static int child_init(int);
 
 static int w_ds_select_dst(struct sip_msg*, char*, char*);
44f3472f
 static int w_ds_select_domain(struct sip_msg*, char*, char*);
a4ba0359
 static int w_ds_next_dst(struct sip_msg*, char*, char*);
 static int w_ds_next_domain(struct sip_msg*, char*, char*);
 static int w_ds_mark_dst0(struct sip_msg*, char*, char*);
 static int w_ds_mark_dst1(struct sip_msg*, char*, char*);
31ccf6a2
 
081b5d4e
 static int w_ds_is_from_list0(struct sip_msg*, char*, char*);
 static int w_ds_is_from_list1(struct sip_msg*, char*, char*);
 
e2cf6343
 static void destroy(void);
31ccf6a2
 
ff4dd78e
 static int ds_warn_fixup(void** param, int param_no);
31ccf6a2
 
e2cf6343
 static struct mi_root* ds_mi_set(struct mi_root* cmd, void* param);
 static struct mi_root* ds_mi_list(struct mi_root* cmd, void* param);
 static struct mi_root* ds_mi_reload(struct mi_root* cmd_tree, void* param);
351fc577
 static int mi_child_init(void);
a4ba0359
 
31ccf6a2
 static cmd_export_t cmds[]={
fc113aee
 	{"ds_select_dst",    (cmd_function)w_ds_select_dst,    2, fixup_igp_igp, 0, REQUEST_ROUTE|FAILURE_ROUTE},
 	{"ds_select_domain", (cmd_function)w_ds_select_domain, 2, fixup_igp_igp, 0, REQUEST_ROUTE|FAILURE_ROUTE},
c4d2e802
 	{"ds_next_dst",      (cmd_function)w_ds_next_dst,      0, ds_warn_fixup, 0, FAILURE_ROUTE},
 	{"ds_next_domain",   (cmd_function)w_ds_next_domain,   0, ds_warn_fixup, 0, FAILURE_ROUTE},
 	{"ds_mark_dst",      (cmd_function)w_ds_mark_dst0,     0, ds_warn_fixup, 0, FAILURE_ROUTE},
 	{"ds_mark_dst",      (cmd_function)w_ds_mark_dst1,     1, ds_warn_fixup, 0, FAILURE_ROUTE},
 	{"ds_is_from_list",  (cmd_function)w_ds_is_from_list0, 0, 0, 0, REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE},
75739b85
 	{"ds_is_from_list",  (cmd_function)w_ds_is_from_list1, 1, fixup_uint_null, 0, REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE},
80998a7f
 	{0,0,0,0,0,0}
31ccf6a2
 };
 
 
 static param_export_t params[]={
101e9af4
 	{"list_file",       STR_PARAM, &dslistfile},
e2cf6343
 	{"db_url",		    STR_PARAM, &ds_db_url.s},
 	{"table_name", 	    STR_PARAM, &ds_table_name.s},
 	{"setid_col",       STR_PARAM, &ds_set_id_col.s},
 	{"destination_col", STR_PARAM, &ds_dest_uri_col.s},
c7d56382
 	{"flags_col",       STR_PARAM, &ds_dest_flags_col.s},
9de77c2b
 	{"priority_col",    STR_PARAM, &ds_dest_priority_col.s},
65160302
 	{"attrs_col",       STR_PARAM, &ds_dest_attrs_col.s},
101e9af4
 	{"force_dst",       INT_PARAM, &ds_force_dst},
 	{"flags",           INT_PARAM, &ds_flags},
 	{"use_default",     INT_PARAM, &ds_use_default},
e2cf6343
 	{"dst_avp",         STR_PARAM, &dst_avp_param.s},
 	{"grp_avp",         STR_PARAM, &grp_avp_param.s},
 	{"cnt_avp",         STR_PARAM, &cnt_avp_param.s},
095ab21d
 	{"hash_pvar",       STR_PARAM, &hash_pvar_param.s},
b14bb7d7
 	{"setid_pvname",    STR_PARAM, &ds_setid_pvname.s},
081b5d4e
 	{"ds_probing_threshhold", INT_PARAM, &probing_threshhold},
e2cf6343
 	{"ds_ping_method",     STR_PARAM, &ds_ping_method.s},
 	{"ds_ping_from",       STR_PARAM, &ds_ping_from.s},
081b5d4e
 	{"ds_ping_interval",   INT_PARAM, &ds_ping_interval},
d1de0cc5
 	{"ds_probing_mode",    INT_PARAM, &ds_probing_mode},
8381c032
 	{"ds_append_branch",   INT_PARAM, &ds_append_branch},
59c31fe7
 	{"ds_hash_sixe",       INT_PARAM, &ds_hash_size},
31ccf6a2
 	{0,0,0}
 };
 
 
de26de44
 static mi_export_t mi_cmds[] = {
cd63f545
 	{ "ds_set_state",   ds_mi_set,     0,                 0,  0            },
 	{ "ds_list",        ds_mi_list,    MI_NO_INPUT_FLAG,  0,  0            },
 	{ "ds_reload",      ds_mi_reload,  0,                 0,  mi_child_init},
fcb8aeaf
 	{ 0, 0, 0, 0, 0}
de26de44
 };
 
 
31ccf6a2
 /** module exports */
 struct module_exports exports= {
 	"dispatcher",
51716422
 	DEFAULT_DLFLAGS, /* dlopen flags */
31ccf6a2
 	cmds,
 	params,
739aec8b
 	0,          /* exported statistics */
de26de44
 	mi_cmds,    /* exported MI functions */
71c26efd
 	0,          /* exported pseudo-variables */
3eee3a4e
 	0,          /* extra processes */
31ccf6a2
 	mod_init,   /* module initialization function */
3ed44241
 	0,
31ccf6a2
 	(destroy_function) destroy,
 	child_init  /* per-child init function */
 };
 
 /**
  * init module function
  */
 static int mod_init(void)
 {
c7d56382
 	pv_spec_t avp_spec;
 
9bdaf1a8
 	if(register_mi_mod(exports.name, mi_cmds)!=0)
 	{
 		LM_ERR("failed to register MI commands\n");
 		return -1;
 	}
 
e2cf6343
 	if (dst_avp_param.s)
c7d56382
 		dst_avp_param.len = strlen(dst_avp_param.s);
e2cf6343
 	if (grp_avp_param.s)
c7d56382
 		grp_avp_param.len = strlen(grp_avp_param.s);
e2cf6343
 	if (cnt_avp_param.s)
c7d56382
 		cnt_avp_param.len = strlen(cnt_avp_param.s);	
095ab21d
 	if (hash_pvar_param.s)
b14bb7d7
 		hash_pvar_param.len = strlen(hash_pvar_param.s);
 	if (ds_setid_pvname.s)
 		ds_setid_pvname.len = strlen(ds_setid_pvname.s);
e2cf6343
 	if (ds_ping_from.s) ds_ping_from.len = strlen(ds_ping_from.s);
 	if (ds_ping_method.s) ds_ping_method.len = strlen(ds_ping_method.s);
 
101e9af4
 	if(init_data()!= 0)
 		return -1;
 
59c31fe7
 	if(ds_hash_size>0)
 	{
 		if(ds_ht_init(1<<ds_hash_size, ds_hash_expire)<0)
 			return -1;
 		register_timer(ds_ht_timer, NULL, 10);
 	}
e2cf6343
 	if(ds_db_url.s)
31ccf6a2
 	{
c7d56382
 		ds_db_url.len     = strlen(ds_db_url.s);
 		ds_table_name.len = strlen(ds_table_name.s);
65160302
 		ds_set_id_col.len        = strlen(ds_set_id_col.s);
 		ds_dest_uri_col.len      = strlen(ds_dest_uri_col.s);
 		ds_dest_flags_col.len    = strlen(ds_dest_flags_col.s);
 		ds_dest_priority_col.len = strlen(ds_dest_priority_col.s);
 		ds_dest_attrs_col.len    = strlen(ds_dest_attrs_col.s);
c7d56382
 
c503d21d
 		if(init_ds_db()!= 0)
101e9af4
 		{
c503d21d
 			LM_ERR("could not initiate a connect to the database\n");
101e9af4
 			return -1;
 		}
 	} else {
ac082a22
 		if(ds_load_list(dslistfile)!=0) {
 			LM_ERR("no dispatching list loaded from file\n");
 			return -1;
 		} else {
 			LM_DBG("loaded dispatching list\n");
 		}
31ccf6a2
 	}
65160302
 
e2cf6343
 	if (dst_avp_param.s && dst_avp_param.len > 0)
101e9af4
 	{
e2cf6343
 		if (pv_parse_spec(&dst_avp_param, &avp_spec)==0
b0a7f212
 				|| avp_spec.type!=PVT_AVP)
101e9af4
 		{
c7d56382
 			LM_ERR("malformed or non AVP %.*s AVP definition\n",
 					dst_avp_param.len, dst_avp_param.s);
8cdef0e8
 			return -1;
 		}
 
b0a7f212
 		if(pv_get_avp_name(0, &(avp_spec.pvp), &dst_avp_name, &dst_avp_type)!=0)
8cdef0e8
 		{
c7d56382
 			LM_ERR("[%.*s]- invalid AVP definition\n", dst_avp_param.len,
 					dst_avp_param.s);
8cdef0e8
 			return -1;
 		}
 	} else {
 		dst_avp_name.n = 0;
 		dst_avp_type = 0;
 	}
e2cf6343
 	if (grp_avp_param.s && grp_avp_param.len > 0)
101e9af4
 	{
e2cf6343
 		if (pv_parse_spec(&grp_avp_param, &avp_spec)==0
b0a7f212
 				|| avp_spec.type!=PVT_AVP)
101e9af4
 		{
c7d56382
 			LM_ERR("malformed or non AVP %.*s AVP definition\n",
 					grp_avp_param.len, grp_avp_param.s);
8cdef0e8
 			return -1;
 		}
 
b0a7f212
 		if(pv_get_avp_name(0, &(avp_spec.pvp), &grp_avp_name, &grp_avp_type)!=0)
8cdef0e8
 		{
c7d56382
 			LM_ERR("[%.*s]- invalid AVP definition\n", grp_avp_param.len,
 					grp_avp_param.s);
8cdef0e8
 			return -1;
 		}
 	} else {
 		grp_avp_name.n = 0;
 		grp_avp_type = 0;
 	}
e2cf6343
 	if (cnt_avp_param.s && cnt_avp_param.len > 0)
101e9af4
 	{
e2cf6343
 		if (pv_parse_spec(&cnt_avp_param, &avp_spec)==0
b0a7f212
 				|| avp_spec.type!=PVT_AVP)
101e9af4
 		{
c7d56382
 			LM_ERR("malformed or non AVP %.*s AVP definition\n",
 					cnt_avp_param.len, cnt_avp_param.s);
8cdef0e8
 			return -1;
 		}
 
b0a7f212
 		if(pv_get_avp_name(0, &(avp_spec.pvp), &cnt_avp_name, &cnt_avp_type)!=0)
8cdef0e8
 		{
c7d56382
 			LM_ERR("[%.*s]- invalid AVP definition\n", cnt_avp_param.len,
 					cnt_avp_param.s);
8cdef0e8
 			return -1;
 		}
 	} else {
 		cnt_avp_name.n = 0;
 		cnt_avp_type = 0;
 	}
081b5d4e
 
095ab21d
 	if (hash_pvar_param.s && *hash_pvar_param.s) {
 		if(pv_parse_format(&hash_pvar_param, &hash_param_model) < 0
 				|| hash_param_model==NULL) {
 			LM_ERR("malformed PV string: %s\n", hash_pvar_param.s);
 			return -1;
 		}		
 	} else {
 		hash_param_model = NULL;
 	}
b14bb7d7
 	
 	if(ds_setid_pvname.s!=0)
 	{
 		if(pv_parse_spec(&ds_setid_pvname, &ds_setid_pv)==NULL
 				|| !pv_is_w(&ds_setid_pv))
 		{
 			LM_ERR("[%s]- invalid setid_pvname\n", ds_setid_pvname.s);
 			return -1;
 		}
 	}
081b5d4e
 	/* Only, if the Probing-Timer is enabled the TM-API needs to be loaded: */
101e9af4
 	if (ds_ping_interval > 0)
 	{
081b5d4e
 		/*****************************************************
 		 * TM-Bindings
 	  	 *****************************************************/
fd5ddfd1
 		if (load_tm_api( &tmb ) == -1)
101e9af4
 		{
fd5ddfd1
 			LM_ERR("could not load the TM-functions - disable DS ping\n");
 			return -1;
081b5d4e
 		}
fd5ddfd1
 		/*****************************************************
 		 * Register the PING-Timer
 		 *****************************************************/
 		register_timer(ds_check_timer, NULL, ds_ping_interval);
081b5d4e
 	}
8cdef0e8
 
31ccf6a2
 	return 0;
 }
 
aecdbe9b
 /*! \brief
31ccf6a2
  * Initialize children
  */
 static int child_init(int rank)
 {
101e9af4
 	srand((11+rank)*getpid()*7);
c503d21d
 
31ccf6a2
 	return 0;
 }
 
351fc577
 static int mi_child_init(void)
c503d21d
 {
2af93c2f
 	
e2cf6343
 	if(ds_db_url.s)
2af93c2f
 		return ds_connect_db();
 	return 0;
c503d21d
 
 }
 
aecdbe9b
 /*! \brief
2af93c2f
  * destroy function
  */
e2cf6343
 static void destroy(void)
2af93c2f
 {
 	ds_destroy_list();
e2cf6343
 	if(ds_db_url.s)
2af93c2f
 		ds_disconnect_db();
 }
 
31ccf6a2
 /**
  *
  */
 static int w_ds_select_dst(struct sip_msg* msg, char* set, char* alg)
 {
a4ba0359
 	int a, s;
 	
31ccf6a2
 	if(msg==NULL)
 		return -1;
05723a03
 	if(fixup_get_ivalue(msg, (gparam_p)set, &s)!=0)
a4ba0359
 	{
101e9af4
 		LM_ERR("no dst set value\n");
a4ba0359
 		return -1;
 	}
05723a03
 	if(fixup_get_ivalue(msg, (gparam_p)alg, &a)!=0)
a4ba0359
 	{
101e9af4
 		LM_ERR("no alg value\n");
a4ba0359
 		return -1;
 	}
31ccf6a2
 
a4ba0359
 	return ds_select_dst(msg, s, a, 0 /*set dst uri*/);
44f3472f
 }
 
 /**
  *
  */
 static int w_ds_select_domain(struct sip_msg* msg, char* set, char* alg)
 {
a4ba0359
 	int a, s;
44f3472f
 	if(msg==NULL)
 		return -1;
 
05723a03
 	if(fixup_get_ivalue(msg, (gparam_p)set, &s)!=0)
a4ba0359
 	{
101e9af4
 		LM_ERR("no dst set value\n");
a4ba0359
 		return -1;
 	}
05723a03
 	if(fixup_get_ivalue(msg, (gparam_p)alg, &a)!=0)
a4ba0359
 	{
101e9af4
 		LM_ERR("no alg value\n");
a4ba0359
 		return -1;
 	}
 
 	return ds_select_dst(msg, s, a, 1/*set host port*/);
 }
 
 /**
  *
  */
 static int w_ds_next_dst(struct sip_msg *msg, char *str1, char *str2)
 {
 	return ds_next_dst(msg, 0/*set dst uri*/);
 }
 
 /**
  *
  */
 static int w_ds_next_domain(struct sip_msg *msg, char *str1, char *str2)
 {
 	return ds_next_dst(msg, 1/*set host port*/);
 }
 
 /**
  *
  */
 static int w_ds_mark_dst0(struct sip_msg *msg, char *str1, char *str2)
 {
 	return ds_mark_dst(msg, 0);
 }
 
 /**
  *
  */
 static int w_ds_mark_dst1(struct sip_msg *msg, char *str1, char *str2)
 {
 	if(str1 && (str1[0]=='i' || str1[0]=='I' || str1[0]=='0'))
 		return ds_mark_dst(msg, 0);
081b5d4e
 	else if(str1 && (str1[0]=='p' || str1[0]=='P' || str1[0]=='2'))
 		return ds_mark_dst(msg, 2);
a4ba0359
 	else
 		return ds_mark_dst(msg, 1);
31ccf6a2
 }
 
ff4dd78e
 static int ds_warn_fixup(void** param, int param_no)
 {
e2cf6343
 	if(!dst_avp_param.s || !grp_avp_param.s || !cnt_avp_param.s)
ff4dd78e
 	{
101e9af4
 		LM_ERR("failover functions used, but AVPs paraamters required"
 				" are NULL -- feature disabled\n");
ff4dd78e
 	}
 	return 0;
 }
ba07eb39
 
 /************************** MI STUFF ************************/
 
e2cf6343
 static struct mi_root* ds_mi_set(struct mi_root* cmd_tree, void* param)
ba07eb39
 {
 	str sp;
 	int ret;
 	unsigned int group, state;
 	struct mi_node* node;
 
33393fd3
 	node = cmd_tree->node.kids;
ba07eb39
 	if(node == NULL)
33393fd3
 		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
ba07eb39
 	sp = node->value;
e2cf6343
 	if(sp.len<=0 || !sp.s)
ba07eb39
 	{
101e9af4
 		LM_ERR("bad state value\n");
33393fd3
 		return init_mi_tree( 500, "bad state value", 15);
ba07eb39
 	}
 
 	state = 1;
 	if(sp.s[0]=='0' || sp.s[0]=='I' || sp.s[0]=='i')
 		state = 0;
 	node = node->next;
 	if(node == NULL)
33393fd3
 		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
ba07eb39
 	sp = node->value;
 	if(sp.s == NULL)
 	{
33393fd3
 		return init_mi_tree(500, "group not found", 15);
ba07eb39
 	}
 
 	if(str2int(&sp, &group))
 	{
101e9af4
 		LM_ERR("bad group value\n");
33393fd3
 		return init_mi_tree( 500, "bad group value", 16);
ba07eb39
 	}
 
 	node= node->next;
 	if(node == NULL)
33393fd3
 		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
ba07eb39
 
 	sp = node->value;
 	if(sp.s == NULL)
 	{
33393fd3
 		return init_mi_tree(500,"address not found", 18 );
ba07eb39
 	}
 
 	if(state==1)
 		ret = ds_set_state(group, &sp, DS_INACTIVE_DST, 0);
 	else
 		ret = ds_set_state(group, &sp, DS_INACTIVE_DST, 1);
 
 	if(ret!=0)
 	{
101e9af4
 		return init_mi_tree(404, "destination not found", 21);
ba07eb39
 	}
 
33393fd3
 	return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
ba07eb39
 }
 
 
 
 
e2cf6343
 static struct mi_root* ds_mi_list(struct mi_root* cmd_tree, void* param)
ba07eb39
 {
33393fd3
 	struct mi_root* rpl_tree;
ba07eb39
 
33393fd3
 	rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
 	if (rpl_tree==NULL)
ba07eb39
 		return 0;
 
33393fd3
 	if( ds_print_mi_list(&rpl_tree->node)< 0 )
ba07eb39
 	{
789504a6
 		LM_ERR("failed to add node\n");
33393fd3
 		free_mi_tree(rpl_tree);
ba07eb39
 		return 0;
 	}
 
33393fd3
 	return rpl_tree;
ba07eb39
 }
 
101e9af4
 #define MI_ERR_RELOAD 			"ERROR Reloading data"
 #define MI_ERR_RELOAD_LEN 		(sizeof(MI_ERR_RELOAD)-1)
 #define MI_NOT_SUPPORTED		"DB mode not configured"
 #define MI_NOT_SUPPORTED_LEN 	(sizeof(MI_NOT_SUPPORTED)-1)
 
e2cf6343
 static struct mi_root* ds_mi_reload(struct mi_root* cmd_tree, void* param)
101e9af4
 {
e2cf6343
 	if(!ds_db_url.s) {
081630ba
 		if (ds_load_list(dslistfile)!=0)
 			return init_mi_tree(500, MI_ERR_RELOAD, MI_ERR_RELOAD_LEN);
 	} else {
 		if(ds_load_db()<0)
 			return init_mi_tree(500, MI_ERR_RELOAD, MI_ERR_RELOAD_LEN);
 	}
101e9af4
 	return init_mi_tree(200, MI_OK_S, MI_OK_LEN);
 }
 
081b5d4e
 
 static int w_ds_is_from_list0(struct sip_msg *msg, char *str1, char *str2)
 {
 	return ds_is_from_list(msg, -1);
 }
 
 
 static int w_ds_is_from_list1(struct sip_msg *msg, char *set, char *str2)
 {
cfc67d90
 	return ds_is_from_list(msg, (int)(long)set);
081b5d4e
 }