[sr-dev] Migration of Open IMS Core to sip-router

Dragos Vingarzan dragos.vingarzan at gmail.com
Fri Jul 24 13:04:02 CEST 2009


Hi Jan,

On Fri, Jul 24, 2009 at 11:07 AM, Jan Janak <jan at ryngle.com> wrote:

>
> Wow, that's a bold move! Knowing that it is relatively easy to migrate
> such stuff to sip-router is very encouraging, thanks.


This in the modules' Makefile:

ifeq ($(CFG_NAME),sip-router)
    DEFS+=-DSER_MOD_INTERFACE
endif

and then changes in the code based on the #ifdef SER_MOD_INTERFACE did it
quite nicely. Also love the new modules partitioning as I got into a big
mess before with just one directory.


>
> >  * enum - support for query on the originating side, useful in PSTN
> >    inbound processing
>
> Could you send this patch to the mailing list and cc Juha?

 Attached.... but... this is one of our crazy-experimental stuff. I mean I
haven't yet figured it our what to do with multiple response or what is the
final list of things to change in the message, so it looks a bit messy to be
merged in the master now.

As a bit of background info, this thing is useful when you have some sort of
PSTN access gateway that would proxy all calls towards a SIP network. The
node in charge of deciding the what-next part is called in IMS related
terminology a TRansit Control Function (TRC or TRCF) and I have also
attached a sample cfg for such a node. The advantage of doing also
enum_orig() is that this node can decide, based on ENUM configuration,
whether to trigger or not an originating leg processing in an originating
domain proxy. Or putting it in another way, this provides the glue to have
originating SIP services for PSTN UEs.


>
> >  * ratelimit - a much extended ratelimit module, with multiple
> >    queues, dynamic limiting capabilities based on internal/external
> >    indicators, random retry-after capabilities, etc; which although
> >    sent towards the SER trunk, never made it
>
> I think your improvements made it to the kamailio version which now
> resides in sip-router/modules_k/ratelimit. Please try to see if it
> contains everything that you need. If yes then we can adopt the
> kamailio version of the module and junk the ser version (and move the
> module from modules_k to modules directory).

yes, the kamailio version includes our changes and actually more. It should
be then pretty safe to drop the ser version if the original owner won't
complain. I guess the original functionality is still usable from there
anyway.


>
> >  * tls - some hashing functions
>
> I'd be happy to see how we can integrate it into the tls module if you
> send me a patch.

Will come soon, but first I want to check it one more time as they are about
2 years old.

Yeah, we would be happy to host your code in our git repository on
> sip-router, I think that this is a good idea, having all the stuff
> available through git would make it much easier to integrate stuff.
>
> First of all I suggest that we start by importing the whole openims
> svn tree into a standalone project in our git repository. We can setup
> scripts that will track the svn tree for a while and import any
> changes done by your developers there until you announce that the
> project migrated. Having the whole SVN repository imported this way
> would allow us to merge selected parts (i.e. openims modules) into the
> main repository with full history. That would be the first step. I
> volunteer to set this up if you send me berlios usernames, full names
> and email addresses (needed to convert svn commit usernames to git
> commit logs with full names and emails) of all developers.

This sounds great. Will do. We also have some branches, but I think that
those would be too much to import.

Then I hope that we could keep all the openimscore changes localized just to
modules as really the core does not need to be different for IMS.


>
>
> After that we can decide how to integrate it with sip-router. Let me
> just enumerate all the options that come to my mind:
>  1) We keep openims as a standalone project within our git repository
>  2) We import all the patches and extra modules on a separate branch
> within the main
>     repository.
>  3) We add all extra openims modules into to the master branch into a
> new module
>     directory such as modules_o and commit patches that those modules
> needs.
>  4) We drop new openims modules into the directory modules and
> integrate patches.
>
> I think that there is no single best option, what would work best
> depends on the nature of the changes that we need to do to existing
> code (i.e. patches to sip-router core and modules) and also on your
> long term goals with the openims project.
>
> Option 1) would work well if you plan to keep openims as a standalone
> project that draws code from sip-router. This option would give you
> considerable freedom to do changes to the code (even extensive ones)
> and yet remain synchronized with the main sip-router tree. We would
> setup a new project for openims in our git repository and set it up in
> such a way that it becomes easy to pull changes from the sip-router
> repository into the openims repository. Whenever you have something
> that is ready to be integrated into the main sip-router tree, you
> could simply let us know that there is something we should pull and
> once we do, the change would eventually propagate from sip-router to
> openims next time you pull. Git makes this mode of operation
> relatively painless, this is also roughly the model that the Linux
> kernel uses.

I guess we don't really need this much liberty. Plus that the past
experience with ser/ser_ims shows that we only once pulled the ser over our
changes. Yes, it was probably harder to pull it with cvs/svn, but we've done
our changes at the core already, mainly to have Diameter support, so the
differences are not that big and hopefully reconcilable.


>
> Option 2) would give you the same amount of freedom as 1), but it
> would probably be difficult to maintain a large number of changes on a
> separate branch for extended periods of time (my own experience). In
> my opinion this would only be suitable if the long term goal is to
> fully integrate openims with sip-router, but we are unsure how long it
> will take to integrate all necessary changes and patches.

Agree. Then from our side we'd just like to maintain a bunch of experimental
modules, which hopefully would donate code to the base sr modules if
necessary. We're not really building a commercially usable IMS thingy, so we
also don't have the resource to maintain it properly in such scenarios.


>
>
> Option 3) (a new module directory), I am not sure whether we really
> need to put openims modules into a separate module directory. Having
> two module directories is a temporary measure because we have two
> versions of most modules, but our long term goal was to migrate them
> where possible. I suppose that all openims modules are new, so we can
> either put them in "modules" directory right away, or in "modules_s"
> or "modules_k", depending on which version of existing modules their
> require.

But... it's so nice :-p. I really liked this because it really lets me have
a separate experimental directory, which also adds some sense to what is for
what. And then I just added my crazy-enum module there too and it did not
interfere with the normal stable one. It looks and feels like a branch, but
it's easier for development.


>
>
> Option 3) and 4) are suitable if your long term goals is to merge
> openims modules into sip-router and make them part of the sip-router
> project. Note that this means that openims developers would have to
> follow the sip-router way o development (releases, testing, code
> integration), no matter how bad or good it is :-).

errrm ... can't really do unfortunately. So I would rather stick with the
experimental flag and keep it separated so that you could also just ignore
any complaints on the lists about crashes or issues when using this. We
don't have any releases now as we can't really aford them. Our trunk is
supposed to be "stable" and then we have branches for which there is
absolutely no waranty.

Our long term goals are:
- to merge back with the SER from which we diverged long time ago. We had
some changes that we needed quickly and could not wait for them to be
stabilized, accepted and pushed to SER. Now we know that some were useless,
some not, some were accepted already and some are still on the waiting list.
Hopefully we'll reconcile on the core changes and then just have all the IMS
stuff in the additional modules.
- to merge with Kamailio, because it's quite dumb some time that you need to
keep and maintain several different ser binaries and configuration files for
doing very similar tasks. For example, most of our users use also the
Kamailio presence server, so they also have to checkout that and care about.
- to upgrade to the latest interfaces for modules, databases and so on as to
take advantage of the new features
- to eliminate the sr sync issues so that our users could immediately
benefit from the latest sr changes, without having to go through syncs every
few months.
- to keep being experimental and to try crazy stuff like the RFC5031 ;-) and
hopefully provide some code for future stable modules.


>
> I would personally favor 1) if you want to continue on your own or 4)
> if you want to integrate your stuff with sip-router, but let's see
> what other have to say. In any case we can start with importing svn
> into git, that's something we will need anyway.

So I guess then that we'd need something like 1, which would be great if the
sync would be done automatically. Sure it would be lighter on our support
efforts if we'd just pull regularly with the sr releases, but this did not
work so well before.

I was thinking about some sort of reversed svn:externals solution, where we
could have a branch like in 1, but all the parts around the modules_ims
would be pulled on checkout from the master or from some link to whatever
last release that was good enough for our purposes.


Thanx&Cheers,
-Dragos
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.sip-router.org/pipermail/sr-dev/attachments/20090724/2298c5e5/attachment-0001.htm>
-------------- next part --------------
Index: enum.c
===================================================================
--- enum.c	(revision 25)
+++ enum.c	(working copy)
@@ -32,6 +32,10 @@
 #include "enum.h"
 #include "../../parser/parse_uri.h"
 #include "../../parser/parse_from.h"
+#include "../../parser/parse_nameaddr.h"
+#include "../../parser/parse_rr.h"
+#include "../../lump_struct.h"
+#include "../../data_lump.h"
 #include "../../ut.h"
 #include "../../resolve.h"
 #include "../../mem/mem.h"
@@ -474,3 +478,415 @@
 	free_rdata_list(head);
 	return first ? -1 : 1;
 }
+
+str s_asserted_identity={"P-Asserted-Identity",19};
+/**
+ * Looks for the P-Asserted-Identity header and extracts its content
+ * @param msg - the sip message
+ * @returns the asserted identity
+ */
+str get_asserted_identity(struct sip_msg *msg)
+{
+	name_addr_t id;
+	struct hdr_field *h;
+	rr_t *r;
+	memset(&id,0,sizeof(name_addr_t));
+	if (!msg) return id.uri;
+	if (parse_headers(msg, HDR_EOH_F, 0)<0) {
+		return id.uri;
+	}
+	h = msg->headers;
+	while(h)
+	{
+		if (h->name.len == s_asserted_identity.len  &&
+			strncasecmp(h->name.s,s_asserted_identity.s,s_asserted_identity.len)==0)
+		{
+			if (parse_rr(h)<0){
+				//This might be an old client
+				LOG(L_CRIT,"WARN:enum:get_asserted_identity: P-Asserted-Identity header must contain a Nameaddr!!! Fix the client!\n");
+				id.name.s = h->body.s;
+				id.name.len = 0;
+				id.len = h->body.len;
+				id.uri = h->body;
+				while(id.uri.len && (id.uri.s[0]==' ' || id.uri.s[0]=='\t' || id.uri.s[0]=='<')){
+					id.uri.s = id.uri.s+1;
+					id.uri.len --;
+				}
+				while(id.uri.len && (id.uri.s[id.uri.len-1]==' ' || id.uri.s[id.uri.len-1]=='\t' || id.uri.s[id.uri.len-1]=='>')){
+					id.uri.len--;
+				}
+				return id.uri;	
+			}
+			r = (rr_t*) h->parsed;
+			id = r->nameaddr;			
+			free_rr(&r);
+			h->parsed=r;
+			//LOG(L_RIT,"%.*s",id.uri.len,id.uri.s);
+			return id.uri;
+		}
+		h = h->next;
+	}
+	return id.uri;
+}
+
+/**
+ *	Get the public identity from P-Asserted-Identity, or From if asserted not found.
+ * @param msg - the SIP message
+ * @param user - user to fill into
+ * @returns 1 if found, 0 if not
+ */
+int get_originating_user( struct sip_msg * msg, str *user )
+{
+	struct to_body * from;
+	int i;
+	*user = get_asserted_identity(msg);
+	if (!user->len) {		
+		/* Fallback to From header */
+		if ( parse_from_header( msg ) == -1 ) {
+			LOG(L_ERR,"ERROR:enum:get_originating_user: unable to extract URI from FROM header\n" );
+			return 0;
+		}
+		if (!msg->from) return 0;
+		from = (struct to_body*) msg->from->parsed;
+		*user = from->uri;
+		//isc_strip_uri(uri);
+	}
+	for(i=0;i<user->len;i++)
+		if (user->s[i]==':'){
+			user->s+=i+1;
+			user->len-=i+1;
+			break;
+		}
+	for(i=0;i<user->len;i++)
+			if (user->s[i]=='@'||user->s[i]==';'||user->s[i]=='?'){
+				user->len=i;
+				break;
+			}
+	DBG("DEBUG:enum:get_originating_user: From %.*s\n", user->len,user->s );
+	return 1;
+}
+
+int set_dst_uri(struct sip_msg* msg, str* uri)
+{
+		/* change destination so it forwards to the app server */
+	if (msg->dst_uri.s) pkg_free(msg->dst_uri.s);
+	msg->dst_uri.s = pkg_malloc(uri->len);
+	if (!msg->dst_uri.s) {
+		LOG(L_ERR,"ERR:enum:set_dst_uri(): error allocating %d bytes\n",uri->len);
+		return -1;
+	}
+	msg->dst_uri.len = uri->len;
+	memcpy(msg->dst_uri.s,uri->s,uri->len);
+	return 0;
+}
+
+inline int add_route(struct sip_msg *msg,str uri)
+{
+	struct hdr_field *first;
+	struct lump* anchor;
+	str domain,route;
+	int i;
+	if (!uri.len) return -1;
+	
+	domain=uri;
+	for(i=0;i<uri.len;i++)
+		if (uri.s[i]=='@'){
+			domain.s = uri.s+i+1;
+			domain.len = uri.len-i-1;
+			break;
+		}
+	for(i=0;i<domain.len;i++)
+		if (domain.s[i]==';'||domain.s[i]=='?'){
+			domain.len = i;
+			break;
+		}
+			
+	parse_headers(msg,HDR_EOH_F,0);			
+	first = msg->headers;	
+	route.s = pkg_malloc(32+domain.len+tel_uri_params_orig.len);
+	if (!route.s){
+		LOG(L_ERR,"ERR:enum:add_route(): error allocating %d bytes\n",32+domain.len+tel_uri_params_orig.len);
+		return -1;
+	}
+	sprintf(route.s,"Route: <sip:%.*s%.*s;lr>\r\n",
+			domain.len,domain.s,
+			tel_uri_params_orig.len,tel_uri_params_orig.s);
+	
+	route.len =strlen(route.s);
+	LOG(L_DBG,"DEBUG:enum:add_route: <%.*s>\n",route.len,route.s);
+	
+	anchor = anchor_lump(msg, first->name.s - msg->buf, 0 , HDR_ROUTE_T);
+	if (anchor == NULL) {
+		LOG(L_ERR, "ERROR:enum:add_route: anchor_lump failed\n");
+		if (route.s) pkg_free(route.s);
+		return -1;
+	}
+	if (!insert_new_lump_before(anchor, route.s,route.len,HDR_ROUTE_T)){
+		LOG( L_ERR, "ERROR:enum:add_route: error creating lump for Route header\n" );
+		if (route.s) pkg_free(route.s);
+		return -1;
+	}	
+	return 0;
+}
+
+
+static int replace_from(struct sip_msg *msg,str replace)
+{
+	struct lump* anchor;
+	struct to_body *from = get_from(msg);
+	str new_from;
+	int i;
+	
+	parse_headers(msg,HDR_EOH_F,0);	
+	for(i=0;i<replace.len;i++)
+		if (replace.s[i]==';'||replace.s[i]=='?'){
+			replace.len = i;
+			break;
+		}	
+	
+	new_from.s = pkg_malloc(replace.len);
+	if (!new_from.s) 
+		return -1;
+	new_from.len = replace.len;
+	memcpy(new_from.s,replace.s,replace.len);
+	
+	anchor = anchor_lump(msg, from->uri.s - msg->buf, 0 , 0);
+	if (anchor == NULL) {
+		LOG(L_ERR, "ERR:enum:replace_from: anchor_lump failed\n");
+		pkg_free(new_from.s);
+		return -1;
+	}
+	
+	if (!insert_new_lump_after(anchor, new_from.s,new_from.len,HDR_OTHER_T)){
+		LOG(L_ERR, "ERR:enum:replace_from: error creating lump for string\n" );
+		pkg_free(new_from.s);
+		return -1;
+	}	
+	if (!del_lump(msg, from->uri.s - msg->buf, from->uri.len, 0)) {
+		LOG(L_ERR, "ERR:enum:replace_from: Can't remove string <%.*s>\n",
+			from->uri.len,from->uri.s);
+		pkg_free(new_from.s);
+		return -1;
+	}
+	return 1;
+}
+
+static str s_asserted_id={"P-Asserted-Identity",19};
+static int replace_asserted(struct sip_msg *msg,str replace)
+{
+	struct hdr_field *first,*h;
+	struct lump* anchor;
+	str asserted;
+	int i;
+	
+	for(i=0;i<replace.len;i++)
+		if (replace.s[i]==';'||replace.s[i]=='?'){
+			replace.len = i;
+			break;
+		}	
+	
+	parse_headers(msg,HDR_EOH_F,0);		
+	first = msg->headers;	
+	for(h=first;h;h=h->next)
+		if (h->name.len == s_asserted_id.len &&
+				strncasecmp(h->name.s,s_asserted_id.s,s_asserted_id.len)==0){
+			if (!del_lump(msg, h->name.s - msg->buf, h->len, 0)) {
+					LOG(L_ERR, "ERR:enum:replace_asserted: Can't remove P-Asserted-Identity header <%.*s>\n",
+							h->len,h->name.s);
+					return -1;
+				}
+		}
+	
+	asserted.s = pkg_malloc(32+replace.len);
+	if (!asserted.s){
+		LOG(L_ERR,"ERR:enum:replace_asserted(): error allocating %d bytes\n",32+replace.len);
+		return -1;
+	}
+	sprintf(asserted.s,"P-Asserted-Identity: <%.*s>\r\n",replace.len,replace.s);
+	
+	asserted.len =strlen(asserted.s);
+	LOG(L_DBG,"DEBUG:enum:add_asserted: <%.*s>\n",asserted.len,asserted.s);
+	
+	anchor = anchor_lump(msg, first->name.s - msg->buf, 0 , HDR_OTHER_T);
+	if (anchor == NULL) {
+		LOG(L_ERR, "ERROR:enum:add_asserted: anchor_lump failed\n");
+		if (asserted.s) pkg_free(asserted.s);
+		return -1;
+	}
+	if (!insert_new_lump_before(anchor, asserted.s,asserted.len,HDR_OTHER_T)){
+		LOG( L_ERR, "ERROR:enum:add_asserted: error creating lump for P-Asserted-Identity header\n" );
+		if (asserted.s) pkg_free(asserted.s);
+		return -1;
+	}	
+	return 1;
+}
+
+int enum_query_orig(struct sip_msg* msg, char* p1, char* p2)
+{
+	char *user_s;
+	int user_len, i, j, first;
+	char name[MAX_DOMAIN_SIZE];
+	char uri[MAX_URI_SIZE];
+	char new_uri[MAX_URI_SIZE];
+	unsigned int priority, curr_prio;
+	qvalue_t q;
+	str user={0,0};
+
+	struct rdata* head;
+	struct rdata* l;
+	struct naptr_rdata* naptr;
+
+	str pattern, replacement, result, new_result;
+
+	char string[17];
+
+	str suffix, service;
+
+	if (p1) {
+	    if (get_str_fparam(&suffix, msg, (fparam_t*)p1) < 0) {
+		ERR("Unable to get suffix value\n");
+		return -1;
+	    }
+	} else {
+	    suffix = domain_suffix;
+	}
+
+	if (p2) {
+	    if (get_str_fparam(&service, msg, (fparam_t*)p2) < 0) {
+		ERR("Unable to get service value\n");
+		return -1;
+	    }
+	} else {
+	    service = default_service;
+	}
+	
+	if (!get_originating_user(msg,&user)){
+		LOG(L_ERR, "enum_query_orig(): originating uri extraction failed\n");
+		return -1;
+	}
+
+	if (test_e164(&user) == -1) {
+		LOG(L_ERR, "enum_query_orig(): uri user is not an E164 number (%.*s)\n",
+				user.len,user.s);
+		return -1;
+	}
+
+	user_s = user.s;
+	user_len = user.len;
+
+	memcpy(&(string[0]), user_s, user_len);
+	string[user_len] = (char)0;
+
+	j = 0;
+	for (i = user_len - 1; i > 0; i--) {
+		name[j] = user_s[i];
+		name[j + 1] = '.';
+		j = j + 2;
+	}
+
+	memcpy(name + j, suffix.s, suffix.len + 1);
+
+	head = get_record(name, T_NAPTR, RES_ONLY_TYPE);
+
+	if (head == 0) {
+		DBG("enum_query_orig(): No NAPTR record found for %s.\n", name);
+		return -1;
+	}
+
+	naptr_sort(&head);
+
+	q = MAX_Q - 10;
+	curr_prio = 0;
+	first = 1;
+
+	for (l = head; l; l = l->next) {
+
+		if (l->type != T_NAPTR) continue; /*should never happen*/
+		naptr = (struct naptr_rdata*)l->rdata;
+		if (naptr == 0) {
+			LOG(L_CRIT, "enum_query_orig: BUG: null rdata\n");
+			continue;
+		}
+
+		DBG("enum_query_orig(): order %u, pref %u, flen %u, flags '%.*s', slen %u, "
+		    "services '%.*s', rlen %u, regexp '%.*s'\n", naptr->order, naptr->pref,
+		    naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags),
+		    naptr->services_len,
+		    (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len,
+		    (int)(naptr->regexp_len), ZSW(naptr->regexp));
+
+		if (sip_match(naptr, &service) == 0) continue;
+
+		if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len,
+				       &pattern, &replacement) < 0) {
+			LOG(L_ERR, "enum_query_orig(): parsing of NAPTR regexp failed\n");
+			continue;
+		}
+		result.s = &(uri[0]);
+		result.len = MAX_URI_SIZE;
+		/* Avoid making copies of pattern and replacement */
+		pattern.s[pattern.len] = (char)0;
+		replacement.s[replacement.len] = (char)0;
+		if (reg_replace(pattern.s, replacement.s, &(string[0]),
+				&result) < 0) {
+			pattern.s[pattern.len] = '!';
+			replacement.s[replacement.len] = '!';
+			LOG(L_ERR, "enum_query_orig(): regexp replace failed\n");
+			continue;
+		}
+		DBG("enum_query(): resulted in replacement: '%.*s'\n",
+		    result.len, ZSW(result.s));
+		pattern.s[pattern.len] = '!';
+		replacement.s[replacement.len] = '!';
+		
+		if (tel_uri_params_orig.len > 0) {
+			if (result.len + tel_uri_params_orig.len > MAX_URI_SIZE - 1) {
+				LOG(L_ERR, "ERROR: enum_query_orig(): URI is too long\n");
+				continue;
+			}
+			new_result.s = &(new_uri[0]);
+			new_result.len = MAX_URI_SIZE;
+			if (add_uri_param(&result, &tel_uri_params_orig, &new_result) == 0) {
+				LOG(L_ERR, "ERROR: enum_query_orig(): Parsing of URI failed\n");
+				continue;
+			}
+			if (new_result.len > 0) {
+				result = new_result;
+			}
+		}
+
+		if (first) {
+			replace_asserted(msg,result);
+			//replace_from(msg,result);
+			add_route(msg,result);
+			if (set_dst_uri(msg, &result) == -1) {
+				goto done;
+			}
+			/*if (rewrite_uri(msg, &result) == -1) {
+				goto done;
+			}
+			set_ruri_q(q);
+			*/
+			first = 0;
+			curr_prio = ((naptr->order) << 16) + naptr->pref;
+			
+		} else {
+			// Not supported yet
+			priority = ((naptr->order) << 16) + naptr->pref;
+			if (priority > curr_prio) {
+				q = q - 10;
+				curr_prio = priority;
+			}
+			/*
+			if (append_branch(msg, result.s, result.len, 0, 0, q, 0) == -1) {
+				goto done;
+			}*/
+		}
+	}
+
+done:
+	free_rdata_list(head);
+	return first ? -1 : 1;
+}
+
+
Index: enum_mod.c
===================================================================
--- enum_mod.c	(revision 25)
+++ enum_mod.c	(working copy)
@@ -45,6 +45,7 @@
 
 str domain_suffix = STR_STATIC_INIT("e164.arpa.");
 str tel_uri_params = STR_STATIC_INIT("");
+str tel_uri_params_orig = STR_STATIC_INIT(";orig");
 str default_service = STR_NULL;
 
 
@@ -55,6 +56,9 @@
 	{"enum_query", enum_query, 0, 0,                REQUEST_ROUTE},
 	{"enum_query", enum_query, 1, fixup_var_str_1,  REQUEST_ROUTE},
 	{"enum_query", enum_query, 2, fixup_var_str_12, REQUEST_ROUTE},
+	{"enum_query_orig", enum_query_orig, 0, 0,                REQUEST_ROUTE},
+	{"enum_query_orig", enum_query_orig, 1, fixup_var_str_1,  REQUEST_ROUTE},
+	{"enum_query_orig", enum_query_orig, 2, fixup_var_str_12, REQUEST_ROUTE},
 	{"is_e164",    is_e164,    1, fixup_var_str_1,  REQUEST_ROUTE},
 	{0, 0, 0, 0, 0}
 };
@@ -66,6 +70,7 @@
 static param_export_t params[] = {
         {"domain_suffix",   PARAM_STR, &domain_suffix },
         {"tel_uri_params",  PARAM_STR, &tel_uri_params},
+        {"tel_uri_params_orig",  PARAM_STR, &tel_uri_params_orig},
 	{"default_service", PARAM_STR, &default_service},
 	{0, 0, 0}
 };
Index: enum_mod.h
===================================================================
--- enum_mod.h	(revision 25)
+++ enum_mod.h	(working copy)
@@ -36,6 +36,7 @@
 
 extern str domain_suffix;
 extern str tel_uri_params;
+extern str tel_uri_params_orig;
 extern str default_service;
 
 
Index: enum.h
===================================================================
--- enum.h	(revision 25)
+++ enum.h	(working copy)
@@ -50,5 +50,11 @@
  */
 int enum_query(struct sip_msg* msg, char* p1, char* p2);
 
+/*
+ * Make enum query on the user in P-Asserted-Identity, with fallback to from.
+ * does not replace the Request-URI, only adds a Route header with an orig parameter
+ */
+int enum_query_orig(struct sip_msg* msg, char* p1, char* p2);
 
+
 #endif /* ENUM_H */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: trcf.cfg
Type: application/octet-stream
Size: 4401 bytes
Desc: not available
URL: <http://lists.sip-router.org/pipermail/sr-dev/attachments/20090724/2298c5e5/attachment-0001.obj>


More information about the sr-dev mailing list