From 635f23b12eff2431ca9a14bb39f4204dc2a7227b Mon Sep 17 00:00:00 2001 From: Charles Chance Date: Fri, 9 Jan 2015 17:16:07 +0000 Subject: [PATCH 1/2] registrar: add optional check for local path during lookup() - when performing a lookup the Path (if present) is evaluated and if the first hop is local we skip it to avoid looping. - useful if multiple servers are sharing a common database, each saving contacts with their local address as the Path. --- modules/registrar/lookup.c | 74 +++++++++++++++++++++++++++++++++---- modules/registrar/reg_mod.c | 2 + modules/registrar/reg_mod.h | 1 + 3 files changed, 70 insertions(+), 7 deletions(-) diff --git a/modules/registrar/lookup.c b/modules/registrar/lookup.c index 1d25acdccd3..0e481f3c326 100644 --- a/modules/registrar/lookup.c +++ b/modules/registrar/lookup.c @@ -41,6 +41,7 @@ #include "../../action.h" #include "../../mod_fix.h" #include "../../parser/parse_rr.h" +#include "../../forward.h" #include "../usrloc/usrloc.h" #include "common.h" #include "regtime.h" @@ -121,6 +122,8 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode) sr_xavp_t *list=NULL; str xname = {"ruid", 4}; sr_xval_t xval; + sip_uri_t path_uri; + str path_str; ret = -1; @@ -256,16 +259,47 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode) xavp_add_value(®_xavp_rcd, &xval, NULL); } } + /* If a Path is present, use first path-uri in favour of * received-uri because in that case the last hop towards the uac * has to handle NAT. - agranig */ if (ptr->path.s && ptr->path.len) { - if (get_path_dst_uri(&ptr->path, &path_dst) < 0) { + /* make a copy, so any change we need to make here does not mess up the structure in usrloc */ + path_str = ptr->path; + if (get_path_dst_uri(&path_str, &path_dst) < 0) { LM_ERR("failed to get dst_uri for Path\n"); ret = -3; goto done; } - if (set_path_vector(_m, &ptr->path) < 0) { + if (path_check_local > 0) { + if (parse_uri(path_dst.s, path_dst.len, &path_uri) < 0){ + LM_ERR("failed to parse the Path URI\n"); + ret = -3; + goto done; + } + if (check_self(&(path_uri.host), 0, 0)) { + /* first hop in path vector is local - check for additional hops and if present, point to next one */ + if (path_str.len > (path_dst.len + 3)) { + path_str.s = path_str.s + path_dst.len + 3; + path_str.len = path_str.len - path_dst.len - 3; + if (get_path_dst_uri(&path_str, &path_dst) < 0) { + LM_ERR("failed to get second dst_uri for Path\n"); + ret = -3; + goto done; + } + } else { + /* no more hops */ + path_dst.s = NULL; + path_dst.len = 0; + } + } + } + } else { + path_dst.s = NULL; + path_dst.len = 0; + } + if (path_dst.s && path_dst.len) { + if (set_path_vector(_m, &path_str) < 0) { LM_ERR("failed to set path vector\n"); ret = -3; goto done; @@ -333,10 +367,36 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode) for( ; ptr ; ptr = ptr->next ) { if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) { path_dst.len = 0; - if(ptr->path.s && ptr->path.len - && get_path_dst_uri(&ptr->path, &path_dst) < 0) { - LM_ERR("failed to get dst_uri for Path\n"); - continue; + if(ptr->path.s && ptr->path.len) { + path_str = ptr->path; + if (get_path_dst_uri(&path_str, &path_dst) < 0) { + LM_ERR("failed to get dst_uri for Path\n"); + continue; + } + if (path_check_local > 0) { + if (parse_uri(path_dst.s, path_dst.len, &path_uri) < 0) { + LM_ERR("failed to parse the Path URI\n"); + continue; + } + if (check_self(&(path_uri.host), 0, 0)) { + /* first hop in path vector is local - check for additional hops and if present, point to next one */ + if (path_str.len > (path_dst.len + 3)) { + path_str.s = path_str.s + path_dst.len + 3; + path_str.len = path_str.len - path_dst.len - 3; + if (get_path_dst_uri(&path_str, &path_dst) < 0) { + LM_ERR("failed to get second dst_uri for Path\n"); + continue; + } + } else { + /* no more hops */ + path_dst.s = NULL; + path_dst.len = 0; + } + } + } + } else { + path_dst.s = NULL; + path_dst.len = 0; } /* The same as for the first contact applies for branches @@ -345,7 +405,7 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode) ptr->instance.len, ptr->instance.s); if (append_branch(_m, &ptr->c, path_dst.len?&path_dst:&ptr->received, - &ptr->path, ptr->q, ptr->cflags, + path_dst.len?&path_str:0, ptr->q, ptr->cflags, ptr->sock, ptr->instance.len?&(ptr->instance):0, ptr->instance.len?ptr->reg_id:0, diff --git a/modules/registrar/reg_mod.c b/modules/registrar/reg_mod.c index f187fb37e55..83c0d25cb30 100644 --- a/modules/registrar/reg_mod.c +++ b/modules/registrar/reg_mod.c @@ -116,6 +116,7 @@ int path_mode = PATH_MODE_STRICT; /*!< if the Path HF should be inserted in the int path_use_params = 0; /*!< if the received- and nat-parameters of last Path uri should be used * to determine if UAC is nat'ed */ +int path_check_local = 0; /* sruid to get internal uid */ sruid_t _reg_sruid; @@ -233,6 +234,7 @@ static param_export_t params[] = { {"use_path", INT_PARAM, &path_enabled }, {"path_mode", INT_PARAM, &path_mode }, {"path_use_received", INT_PARAM, &path_use_params }, + {"path_check_local", INT_PARAM, &path_check_local }, {"xavp_cfg", PARAM_STR, ®_xavp_cfg }, {"xavp_rcd", PARAM_STR, ®_xavp_rcd }, {"gruu_enabled", INT_PARAM, ®_gruu_enabled }, diff --git a/modules/registrar/reg_mod.h b/modules/registrar/reg_mod.h index 96def72d01c..5dffa752ae3 100644 --- a/modules/registrar/reg_mod.h +++ b/modules/registrar/reg_mod.h @@ -94,6 +94,7 @@ extern int method_filtering; extern int path_enabled; extern int path_mode; extern int path_use_params; +extern int path_check_local; extern int reg_gruu_enabled; extern int reg_outbound_mode; extern int reg_regid_mode; From 4ff2c48d66a3bce2c491b44d0f1b5e939e5508ff Mon Sep 17 00:00:00 2001 From: Charles Chance Date: Fri, 9 Jan 2015 17:22:59 +0000 Subject: [PATCH 2/2] registrar: update documentation to include path_check_local parameter --- modules/registrar/doc/registrar_admin.xml | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/modules/registrar/doc/registrar_admin.xml b/modules/registrar/doc/registrar_admin.xml index c7d5b989e55..f1c9dc51a47 100644 --- a/modules/registrar/doc/registrar_admin.xml +++ b/modules/registrar/doc/registrar_admin.xml @@ -630,6 +630,32 @@ modparam("registrar", "path_use_received", 1) +
+ <varname>path_check_local</varname> (integer) + + If set to 1, when performing a lookup the Path (if present) is evaluated + and if the first hop is local (according to myself test), we + skip it to avoid unnecessary looping. + + + This is useful if multiple servers are sharing a common location database, + each saving contacts with their local address as the Path. + + + + Default value is 0 (disabled). + + + + Set <varname>path_check_local</varname> parameter + +... +modparam("registrar", "path_check_local", 1) +... + + +
+
<varname>reg_callid_avp</varname> (string)