Răsfoiți Sursa

- add missing files (from previous commit)
- Credits belogs to Hardy Kahl, hardy dot kahl at 1und1 dot de


git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@5131 689a6050-402a-0410-94f2-e92a70836424

Henning Westerholt 17 ani în urmă
părinte
comite
7bf8d6fb29

+ 227 - 0
modules/carrierroute/cr_domain.c

@@ -0,0 +1,227 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2007-2008 1&1 Internet AG
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * 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
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * 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
+ */
+
+/**
+ * \file cr_domain.c
+ * \brief Contains the functions to manage routing domains.
+ * \ingroup carrierroute
+ * - Module; \ref carrierroute
+ */
+
+#include <stdlib.h>
+#include "../../mem/shm_mem.h"
+#include "../../ut.h"
+#include "cr_domain.h"
+#include "cr_map.h"
+#include "cr_rule.h"
+
+
+/**
+ * Destroys route_flags list in shared memory by freing all its memory.
+ *
+ * @param data the start of the route_flags list to be destroyed
+ */
+static void destroy_route_flags_list(void *data) {
+	struct route_flags *rf, *rf_tmp;
+
+	rf=(struct route_flags *)(data);
+	while (rf!=NULL) {
+		rf_tmp = rf->next;
+		destroy_route_flags(rf);
+		rf = rf_tmp;
+	}
+}
+
+
+/**
+ * Destroys failure_route_rule list in shared memory by freing all its memory.
+ *
+ * @param data the start of the failure_route_rule list to be destroyed
+ */
+static void destroy_failure_route_rule_list(void *data) {
+	struct failure_route_rule *rs, *rs_tmp;
+	
+	rs = (struct failure_route_rule *)(data);
+	while (rs != NULL) {
+		rs_tmp = rs->next;
+		destroy_failure_route_rule(rs);
+		rs = rs_tmp;
+	}
+}
+
+
+/**
+ * Create a new domain in shared memory and set it up.
+ *
+ * @param domain_name the name of the domain
+ * @param domain_id the id of the domain
+ *
+ * @return a pointer to the newly allocated domain data or NULL on
+ * error, in which case it LOGs an error message.
+ */
+struct domain_data_t * create_domain_data(const str * domain_name, int domain_id) {
+	struct domain_data_t * tmp;
+	if ((tmp = shm_malloc(sizeof(struct domain_data_t))) == NULL) {
+		LM_ERR("out of shared memory\n");
+		return NULL;
+	}
+	memset(tmp, 0, sizeof(struct domain_data_t));
+	if (shm_str_dup(&tmp->name, domain_name)!=0) {
+		LM_ERR("cannot duplicate string\n");
+		shm_free(tmp);
+		return NULL;
+	}
+	tmp->id = domain_id;
+	if ((tmp->tree = dtrie_init()) == NULL) {
+		shm_free(tmp->name.s);
+		shm_free(tmp);
+		return NULL;
+	}
+	if ((tmp->failure_tree = dtrie_init()) == NULL) {
+		dtrie_destroy(&tmp->tree, NULL);
+		shm_free(tmp->name.s);
+		shm_free(tmp);
+		return NULL;
+	}
+	return tmp;
+}
+
+
+/**
+ * Destroys the given domain and frees the used memory.
+ *
+ * @param domain_data the to the structure to be destroyed.
+ */
+void destroy_domain_data(struct domain_data_t *domain_data) {
+	dtrie_destroy(&domain_data->tree, destroy_route_flags_list);
+	dtrie_destroy(&domain_data->failure_tree, destroy_failure_route_rule_list);
+	shm_free(domain_data->name.s);
+	shm_free(domain_data);
+}
+
+
+/**
+ * Adds the given route information to the prefix tree identified by
+ * node. scan_prefix identifies the number for which the information
+ * is. The rewrite_* parameters define what to do in case of a match.
+ * prob gives the probability with which this rule applies if there are
+ * more than one for a given prefix.
+ *
+ * @param node the root of the routing tree
+ * @param scan_prefix the prefix for which to add the rule (must not contain non-digits)
+ * @param flags user defined flags
+ * @param mask mask for user defined flags
+ * @param full_prefix the whole scan prefix
+ * @param max_targets the number of targets
+ * @param prob the weight of the rule
+ * @param rewrite_hostpart the rewrite_host of the rule
+ * @param strip the number of digits to be stripped off userpart before prepending prefix
+ * @param rewrite_local_prefix the rewrite prefix
+ * @param rewrite_local_suffix the rewrite suffix
+ * @param status the status of the rule
+ * @param hash_index the hash index of the rule
+ * @param backup indicates if the route is backed up by another. only 
+                 useful if status==0, if set, it is the hash value
+                 of another rule
+  * @param backed_up an -1-termintated array of hash indices of the route 
+                    for which this route is backup
+ * @param comment a comment for the route rule
+ *
+ * @return 0 on success, -1 on failure
+ *
+ * @see add_route()
+ */
+int add_route_to_tree(struct dtrie_node_t *node, const str * scan_prefix,
+		flag_t flags, flag_t mask, const str * full_prefix, int max_targets, double prob,
+		const str * rewrite_hostpart, int strip, const str * rewrite_local_prefix,
+		const str * rewrite_local_suffix, int status, int hash_index, 
+		int backup, int * backed_up, const str * comment) {
+	void **ret;
+	struct route_flags *rf;
+
+	ret = dtrie_contains(node, scan_prefix->s, scan_prefix->len);
+
+	rf = add_route_flags((struct route_flags **)ret, flags, mask);
+	if (rf == NULL) {
+		LM_ERR("cannot insert route flags into list\n");
+		return -1;
+	}
+
+	if (ret == NULL) {
+		/* node does not exist */
+		if (dtrie_insert(node, scan_prefix->s, scan_prefix->len, rf) != 0) {
+			LM_ERR("cannot insert route flags into d-trie\n");
+			return -1;
+		}
+	}
+
+	/* Now add rule to flags */
+	return add_route_rule(rf, full_prefix, max_targets, prob, rewrite_hostpart, strip,
+												rewrite_local_prefix, rewrite_local_suffix, status, hash_index,
+												backup, backed_up, comment);
+}
+
+
+/**
+ * Adds the given failure route information to the failure prefix tree identified by
+ * failure_node. scan_prefix, host, reply_code, flags identifies the number for which
+ * the information is and the next_domain parameters defines where to continue
+ * routing in case of a match.
+ *
+ * @param failure_tree the root of the failure routing tree
+ * @param scan_prefix the prefix for which to add the rule (must not contain non-digits)
+ * @param full_prefix the whole scan prefix
+ * @param host the hostname last tried
+ * @param reply_code the reply code 
+ * @param flags user defined flags
+ * @param mask mask for user defined flags
+ * @param next_domain continue routing with this domain id
+ * @param comment a comment for the route rule
+ *
+ * @return 0 on success, -1 on failure
+ *
+ * @see add_route()
+ */
+int add_failure_route_to_tree(struct dtrie_node_t * failure_node, const str * scan_prefix,
+		const str * full_prefix, const str * host, const str * reply_code,
+		const flag_t flags, const flag_t mask, const int next_domain, const str * comment) {
+	void **ret;
+	struct failure_route_rule *frr;
+
+	ret = dtrie_contains(failure_node, scan_prefix->s, scan_prefix->len);
+
+	frr = add_failure_route_rule((struct failure_route_rule **)ret, full_prefix, host, reply_code, flags, mask, next_domain, comment);
+	if (frr == NULL) {
+		LM_ERR("cannot insert failure route rule into list\n");
+		return -1;
+		}
+
+	if (ret == NULL) {
+		/* node does not exist */
+		if (dtrie_insert(failure_node, scan_prefix->s, scan_prefix->len, frr) != 0) {
+			LM_ERR("cannot insert failure route rule into d-trie\n");
+			return -1;
+		}
+	}
+
+	return 0;
+}

+ 132 - 0
modules/carrierroute/cr_domain.h

@@ -0,0 +1,132 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2007-2008 1&1 Internet AG
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * 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
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * 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
+ */
+
+/**
+ * \file cr_domain.h
+ * \brief Contains the functions to manage routing domains.
+ * \ingroup carrierroute
+ * - Module; \ref carrierroute
+ */
+
+#ifndef CR_DOMAIN_H
+#define CR_DOMAIN_H
+
+#include "../../str.h"
+#include "../../flags.h"
+#include "../../trie/dtrie.h"
+
+
+/**
+ * The struct for the domain.
+ * Contains the head of each prefix tree.
+ */
+struct domain_data_t {
+	int id; /*!< the numerical id of the routing tree */
+	str name; /*!< the name of the routing tree */
+	struct dtrie_node_t * tree; /*!< the root node of the routing tree. Payload is of type (struct route_flags *) */
+	struct dtrie_node_t * failure_tree; /*!< the root node of the failure routing tree. Payload is of type (struct failure_route_rule *) */
+};
+
+
+/**
+ * Create a new domain in shared memory and set it up.
+ *
+ * @param domain_name the name of the domain
+ * @param domain_id the id of the domain
+ *
+ * @return a pointer to the newly allocated domain data or NULL on
+ * error, in which case it LOGs an error message.
+ */
+struct domain_data_t * create_domain_data(const str * domain, int id);
+
+
+/**
+ * Destroys the given domain and frees the used memory.
+ *
+ * @param domain_data the to the structure to be destroyed.
+ */
+void destroy_domain_data(struct domain_data_t *domain_data);
+
+
+/**
+ * Adds the given route information to the prefix tree identified by
+ * node. scan_prefix identifies the number for which the information
+ * is. The rewrite_* parameters define what to do in case of a match.
+ * prob gives the probability with which this rule applies if there are
+ * more than one for a given prefix.
+ *
+ * @param node the root of the routing tree
+ * @param scan_prefix the prefix for which to add the rule (must not contain non-digits)
+ * @param flags user defined flags
+ * @param mask mask for user defined flags
+ * @param full_prefix the whole scan prefix
+ * @param max_targets the number of targets
+ * @param prob the weight of the rule
+ * @param rewrite_hostpart the rewrite_host of the rule
+ * @param strip the number of digits to be stripped off userpart before prepending prefix
+ * @param rewrite_local_prefix the rewrite prefix
+ * @param rewrite_local_suffix the rewrite suffix
+ * @param status the status of the rule
+ * @param hash_index the hash index of the rule
+ * @param backup indicates if the route is backed up by another. only 
+                 useful if status==0, if set, it is the hash value
+                 of another rule
+ * @param backed_up an -1-termintated array of hash indices of the route 
+                    for which this route is backup
+ * @param comment a comment for the route rule
+ *
+ * @return 0 on success, -1 on failure
+ *
+ * @see add_route()
+ */
+int add_route_to_tree(struct dtrie_node_t *node, const str * scan_prefix,
+		flag_t flags, flag_t mask, const str * full_prefix, int max_targets, double prob,
+		const str * rewrite_hostpart, int strip, const str * rewrite_local_prefix,
+		const str * rewrite_local_suffix, int status, int hash_index, 
+		int backup, int * backed_up, const str * comment);
+
+
+/**
+ * Adds the given failure route information to the failure prefix tree identified by
+ * failure_node. scan_prefix, host, reply_code, flags identifies the number for which
+ * the information is and the next_domain parameters defines where to continue
+ * routing in case of a match.
+ *
+ * @param failure_tree the root of the failure routing tree
+ * @param scan_prefix the prefix for which to add the rule (must not contain non-digits)
+ * @param full_prefix the whole scan prefix
+ * @param host the hostname last tried
+ * @param reply_code the reply code 
+ * @param flags user defined flags
+ * @param mask mask for user defined flags
+ * @param next_domain continue routing with this domain id
+ * @param comment a comment for the route rule
+ *
+ * @return 0 on success, -1 on failure
+ *
+ * @see add_route()
+ */
+int add_failure_route_to_tree(struct dtrie_node_t * failure_node, const str * scan_prefix,
+		const str * full_prefix, const str * host, const str * reply_code,
+		const flag_t flags, const flag_t mask, const int next_domain, const str * comment);
+
+#endif

+ 387 - 0
modules/carrierroute/cr_fixup.c

@@ -0,0 +1,387 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2007-2008 1&1 Internet AG
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * 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
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * 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
+ */
+
+/**
+ * \file cr_fixup.c
+ * \brief Fixup functions.
+ * \ingroup carrierroute
+ * - Module; \ref carrierroute
+ */
+
+#include "../../mod_fix.h"
+#include "../../mem/mem.h"
+#include "cr_fixup.h"
+#include "carrierroute.h"
+#include "cr_map.h"
+#include "cr_domain.h"
+#include "prime_hash.h"
+
+
+/**
+ * Fixes the hash source to enum values
+ *
+ * @param my_hash_source the hash source as string
+ *
+ * @return the enum value on success, -1 on failure
+ */
+static enum hash_source hash_fixup(const char * my_hash_source) {
+	if (strcasecmp("call_id", my_hash_source) == 0) {
+		return shs_call_id;
+	} else if (strcasecmp("from_uri", my_hash_source) == 0) {
+		return shs_from_uri;
+	} else if (strcasecmp("from_user", my_hash_source) == 0) {
+		return shs_from_user;
+	} else if (strcasecmp("to_uri", my_hash_source) == 0) {
+		return shs_to_uri;
+	} else if (strcasecmp("to_user", my_hash_source) == 0) {
+		return shs_to_user;
+	} else {
+		return shs_error;
+	}
+}
+
+
+/**
+ * fixes the module functions' parameters with generic pseudo variable support.
+ *
+ * @param param the parameter
+ *
+ * @return 0 on success, -1 on failure
+ */
+static int pv_fixup(void ** param) {
+	pv_elem_t *model;
+	str s;
+
+	s.s = (char *)(*param);
+	s.len = strlen(s.s);
+	if (s.len <= 0) return -1;
+	/* Check the format */
+	if(pv_parse_format(&s, &model)<0) {
+		LM_ERR("pv_parse_format failed for '%s'\n", (char *)(*param));
+		return -1;
+	}
+	*param = (void*)model;
+
+	return 0;
+}
+
+
+/**
+ * fixes the module functions' parameters if it is a carrier.
+ * supports name string, pseudo-variables and AVPs.
+ *
+ * @param param the parameter
+ *
+ * @return 0 on success, -1 on failure
+ */
+static int carrier_fixup(void ** param) {
+	pv_spec_t avp_spec;
+	gparam_t *gp;
+	str s;
+
+	gp = (gparam_t *)pkg_malloc(sizeof(gparam_t));
+	if (gp == NULL) {
+		LM_ERR("no more memory\n");
+		return -1;
+	}
+	memset(gp, 0, sizeof(gparam_t));
+	
+	s.s = (char *)(*param);
+	s.len = strlen(s.s);
+
+	if (s.s[0]!='$') {
+		/* This is a name string */
+		gp->type=GPARAM_TYPE_INT;
+		
+		/* get carrier id */
+		if ((gp->v.ival = find_carrier(s)) < 0) {
+			LM_ERR("could not find carrier '%s'\n", (char *)(*param));
+			pkg_free(gp);
+			return -1;
+		}
+		LM_INFO("carrier %s has id %i\n", (char *)*param, gp->v.ival);
+		
+		pkg_free(*param);
+		*param = (void *)gp;
+	}
+	else {
+		/* This is a pseudo-variable */
+		if (pv_parse_spec(&s, &avp_spec)==0) {
+			LM_ERR("pv_parse_spec failed for '%s'\n", (char *)(*param));
+			pkg_free(gp);
+			return -1;
+		}
+		if (avp_spec.type==PVT_AVP) {
+			/* This is an AVP - could be an id or name */
+			gp->type=GPARAM_TYPE_AVP;
+			if(pv_get_avp_name(0, &(avp_spec.pvp), &(gp->v.avp.name), &(gp->v.avp.flags))!=0) {
+				LM_ERR("Invalid AVP definition <%s>\n", (char *)(*param));
+				pkg_free(gp);
+				return -1;
+			}
+		} else {
+			gp->type=GPARAM_TYPE_PVE;
+			if(pv_parse_format(&s, &(gp->v.pve))<0) {
+				LM_ERR("pv_parse_format failed for '%s'\n", (char *)(*param));
+				pkg_free(gp);
+				return -1;
+			}
+		}
+	}
+	*param = (void*)gp;
+
+	return 0;
+}
+
+
+/**
+ * fixes the module functions' parameters if it is a domain.
+ * supports name string, and AVPs.
+ *
+ * @param param the parameter
+ *
+ * @return 0 on success, -1 on failure
+ */
+static int domain_fixup(void ** param) {
+	pv_spec_t avp_spec;
+	gparam_t *gp;
+	str s;
+
+	gp = (gparam_t *)pkg_malloc(sizeof(gparam_t));
+	if (gp == NULL) {
+		LM_ERR("no more memory\n");
+		return -1;
+	}
+	memset(gp, 0, sizeof(gparam_t));
+	
+	s.s = (char *)(*param);
+	s.len = strlen(s.s);
+	
+	if (s.s[0]!='$') {
+		/* This is a name string */
+		gp->type=GPARAM_TYPE_INT;
+		
+		/* get domain id */
+		if ((gp->v.ival = add_domain(&s)) < 0) {
+			LM_ERR("could not add domain\n");
+			pkg_free(gp);
+			return -1;
+		}
+		pkg_free(*param);
+		*param = (void *)gp;
+	}
+	else {
+		/* This is a pseudo-variable */
+		if (pv_parse_spec(&s, &avp_spec)==0) {
+			LM_ERR("pv_parse_spec failed for '%s'\n", (char *)(*param));
+			pkg_free(gp);
+			return -1;
+		}
+		if (avp_spec.type==PVT_AVP) {
+			/* This is an AVP - could be an id or name */
+			gp->type=GPARAM_TYPE_AVP;
+			if(pv_get_avp_name(0, &(avp_spec.pvp), &(gp->v.avp.name), &(gp->v.avp.flags))!=0) {
+				LM_ERR("Invalid AVP definition <%s>\n", (char *)(*param));
+				pkg_free(gp);
+				return -1;
+			}
+		} else {
+			gp->type=GPARAM_TYPE_PVE;
+			if(pv_parse_format(&s, &(gp->v.pve))<0) {
+				LM_ERR("pv_parse_format failed for '%s'\n", (char *)(*param));
+				pkg_free(gp);
+				return -1;
+			}
+		}	
+	}
+	*param = (void*)gp;
+
+	return 0;
+}
+
+
+/**
+ * fixes the module functions' parameters in case of AVP names.
+ *
+ * @param param the parameter
+ *
+ * @return 0 on success, -1 on failure
+ */
+static int avp_name_fixup(void ** param) {
+	pv_spec_t avp_spec;
+	gparam_t *gp;
+	str s;
+
+	s.s = (char *)(*param);
+	s.len = strlen(s.s);
+	if (s.len <= 0) return -1;
+	if (pv_parse_spec(&s, &avp_spec)==0 || avp_spec.type!=PVT_AVP) {
+		LM_ERR("Malformed or non AVP definition <%s>\n", (char *)(*param));
+		return -1;
+	}
+	
+	gp = (gparam_t *)pkg_malloc(sizeof(gparam_t));
+	if (gp == NULL) {
+		LM_ERR("no more memory\n");
+		return -1;
+	}
+	memset(gp, 0, sizeof(gparam_t));
+	
+	gp->type=GPARAM_TYPE_AVP;
+	if(pv_get_avp_name(0, &(avp_spec.pvp), &(gp->v.avp.name), &(gp->v.avp.flags))!=0) {
+		LM_ERR("Invalid AVP definition <%s>\n", (char *)(*param));
+		pkg_free(gp);
+		return -1;
+	}
+
+	*param = (void*)gp;
+	
+	return 0;
+}
+
+
+/**
+ * fixes the module functions' parameters, i.e. it maps
+ * the routing domain names to numbers for faster access
+ * at runtime
+ *
+ * @param param the parameter
+ * @param param_no the number of the parameter
+ *
+ * @return 0 on success, -1 on failure
+ */
+int cr_route_fixup(void ** param, int param_no) {
+	enum hash_source my_hash_source;
+
+	if (param_no == 1) {
+		/* carrier */
+		if (carrier_fixup(param) < 0) {
+			LM_ERR("cannot fixup parameter %d\n", param_no);
+			return -1;
+		}
+	}
+	else if (param_no == 2) {
+		/* domain */
+		if (domain_fixup(param) < 0) {
+			LM_ERR("cannot fixup parameter %d\n", param_no);
+			return -1;
+		}
+	}
+	else if ((param_no == 3) || (param_no == 4)){
+		/* prefix matching */
+		/* rewrite user */
+		if (pv_fixup(param) < 0) {
+			LM_ERR("cannot fixup parameter %d\n", param_no);
+			return -1;
+		}
+	}
+	else if (param_no == 5) {
+		/* hash source */
+		if ((my_hash_source = hash_fixup((char *)*param)) == shs_error) {
+			LM_ERR("invalid hash source\n");
+			return -1;
+		}
+		pkg_free(*param);
+		*param = (void *)my_hash_source;
+	}
+	else if (param_no == 6) {
+		/* destination avp name */
+		if (avp_name_fixup(param) < 0) {
+			LM_ERR("cannot fixup parameter %d\n", param_no);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+
+/**
+ * fixes the module functions' parameters, i.e. it maps
+ * the routing domain names to numbers for faster access
+ * at runtime
+ *
+ * @param param the parameter
+ * @param param_no the number of the parameter
+ *
+ * @return 0 on success, -1 on failure
+ */
+int cr_load_next_domain_fixup(void ** param, int param_no) {
+	if (param_no == 1) {
+		/* carrier */
+		if (carrier_fixup(param) < 0) {
+			LM_ERR("cannot fixup parameter %d\n", param_no);
+			return -1;
+		}
+	}
+	else if (param_no == 2) {
+		/* domain */
+		if (domain_fixup(param) < 0) {
+			LM_ERR("cannot fixup parameter %d\n", param_no);
+			return -1;
+		}
+	}
+	else if ((param_no == 3) || (param_no == 4) || (param_no == 5)) {
+		/* prefix matching */
+		/* host */
+		/* reply code */
+		if (pv_fixup(param) < 0) {
+			LM_ERR("cannot fixup parameter %d\n", param_no);
+			return -1;
+		}
+	}
+	else if (param_no == 6) {
+		/* destination avp name */
+		if (avp_name_fixup(param) < 0) {
+			LM_ERR("cannot fixup parameter %d\n", param_no);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+
+int cr_load_user_carrier_fixup(void ** param, int param_no) {
+	if (mode == CARRIERROUTE_MODE_FILE) {
+		LM_ERR("command cr_user_rewrite_uri can't be used in file mode\n");
+		return -1;
+	}
+
+	if ((param_no == 1) || (param_no == 2)) {
+		/* user */
+		/* domain */
+		if (pv_fixup(param) < 0) {
+			LM_ERR("cannot fixup parameter %d\n", param_no);
+			return -1;
+		}
+	}
+	else if (param_no == 3) {
+		/* destination avp name */
+		if (avp_name_fixup(param) < 0) {
+			LM_ERR("cannot fixup parameter %d\n", param_no);
+			return -1;
+		}
+	}
+
+	return 0;
+}

+ 41 - 0
modules/carrierroute/cr_fixup.h

@@ -0,0 +1,41 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2007-2008 1&1 Internet AG
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+ * 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
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * 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
+ *
+ */
+
+/**
+ * \file cr_fixup.h
+ * \brief Fixup functions.
+ * \ingroup carrierroute
+ * - Module; \ref carrierroute
+ */
+
+#ifndef CR_FIXUP_H
+#define CR_FIXUP_H
+
+
+int cr_route_fixup(void ** param, int param_no);
+
+int cr_load_user_carrier_fixup(void ** param, int param_no);
+
+int cr_load_next_domain_fixup(void ** param, int param_no);
+
+#endif