Sfoglia il codice sorgente

topoh: uses socket IP when no mask_ip is defined (#3341)

* topoh: uses socket IP when no mask_ip is defined

If the parameter mask_ip is not defined the module finds the socket IP
and uses that as mask IP for the message.
If the socket has an advertised IP it is used, otherwise the socket IP is used.
TorPetterson 1 anno fa
parent
commit
8bfe55c68a

+ 3 - 1
src/modules/topoh/doc/topoh_admin.xml

@@ -92,11 +92,13 @@ modparam("topoh", "mask_key", "some secret here")
 		SIP URIs. Can be any IP address, even a private-space or non-existing
 		SIP URIs. Can be any IP address, even a private-space or non-existing
 		IP address (e.g., 192.168.1.1, 127.0.0.2), including the SIP server
 		IP address (e.g., 192.168.1.1, 127.0.0.2), including the SIP server
 		address, but must not be an address potentially used by clients.
 		address, but must not be an address potentially used by clients.
+		If not set, the advertised IP of the incoming or outgoing socket is used.
+		If there is no advertised IP, the IP of the socket is used.
 		It is not used at all for SIP routing.
 		It is not used at all for SIP routing.
 		</para>
 		</para>
 		<para>
 		<para>
 		<emphasis>
 		<emphasis>
-			Default value is "127.0.0.8".
+			Default value is empty.
 		</emphasis>
 		</emphasis>
 		</para>
 		</para>
 		<example>
 		<example>

+ 36 - 38
src/modules/topoh/th_msg.c

@@ -45,11 +45,8 @@
 
 
 extern str th_cookie_name;
 extern str th_cookie_name;
 extern str th_cookie_value;
 extern str th_cookie_value;
-extern str th_via_prefix;
-extern str th_uri_prefix;
 extern str th_callid_prefix;
 extern str th_callid_prefix;
 
 
-extern str th_ip;
 extern str th_uparam_name;
 extern str th_uparam_name;
 extern str th_uparam_prefix;
 extern str th_uparam_prefix;
 extern str th_vparam_name;
 extern str th_vparam_name;
@@ -121,7 +118,7 @@ int th_get_uri_param_value(str *uri, str *name, str *value)
 	return th_get_param_value(&puri.params, name, value);
 	return th_get_param_value(&puri.params, name, value);
 }
 }
 
 
-int th_get_uri_type(str *uri, int *mode, str *value)
+int th_get_uri_type(str *uri, int *mode, str *ip, str *value)
 {
 {
 	sip_uri_t puri;
 	sip_uri_t puri;
 	int ret;
 	int ret;
@@ -133,8 +130,8 @@ int th_get_uri_type(str *uri, int *mode, str *value)
 		return -1;
 		return -1;
 
 
 	LM_DBG("PARAMS [%.*s]\n", puri.params.len, puri.params.s);
 	LM_DBG("PARAMS [%.*s]\n", puri.params.len, puri.params.s);
-	if(puri.host.len == th_ip.len
-			&& strncasecmp(puri.host.s, th_ip.s, th_ip.len) == 0) {
+	if(puri.host.len == ip->len
+			&& strncasecmp(puri.host.s, ip->s, ip->len) == 0) {
 		/* host matches TH ip */
 		/* host matches TH ip */
 		ret = th_get_param_value(&puri.params, &th_uparam_name, value);
 		ret = th_get_param_value(&puri.params, &th_uparam_name, value);
 		if(ret < 0)
 		if(ret < 0)
@@ -162,7 +159,7 @@ int th_get_uri_type(str *uri, int *mode, str *value)
 	return 1; /* encode */
 	return 1; /* encode */
 }
 }
 
 
-int th_mask_via(sip_msg_t *msg)
+int th_mask_via(sip_msg_t *msg, str *via_prefix)
 {
 {
 	hdr_field_t *hdr;
 	hdr_field_t *hdr;
 	struct via_body *via;
 	struct via_body *via;
@@ -181,8 +178,9 @@ int th_mask_via(sip_msg_t *msg)
 			LM_DBG("body: %d: [%.*s]\n", vlen, vlen, via->name.s);
 			LM_DBG("body: %d: [%.*s]\n", vlen, vlen, via->name.s);
 			if(i != 1) {
 			if(i != 1) {
 				out.s = th_mask_encode(
 				out.s = th_mask_encode(
-						via->name.s, vlen, &th_via_prefix, &out.len);
-				if(out.s == NULL) {
+				        via->name.s, vlen, via_prefix, &out.len);
+				if(out.s == NULL)
+				{
 					LM_ERR("cannot encode via %d\n", i);
 					LM_ERR("cannot encode via %d\n", i);
 					return -1;
 					return -1;
 				}
 				}
@@ -240,7 +238,7 @@ int th_mask_callid(sip_msg_t *msg)
 	return 0;
 	return 0;
 }
 }
 
 
-int th_mask_contact(sip_msg_t *msg)
+int th_mask_contact(sip_msg_t *msg, str *uri_prefix)
 {
 {
 	struct lump *l;
 	struct lump *l;
 	str out;
 	str out;
@@ -265,7 +263,7 @@ int th_mask_contact(sip_msg_t *msg)
 	}
 	}
 	in = c->uri;
 	in = c->uri;
 
 
-	out.s = th_mask_encode(in.s, in.len, &th_uri_prefix, &out.len);
+	out.s = th_mask_encode(in.s, in.len, uri_prefix, &out.len);
 	if(out.s == NULL) {
 	if(out.s == NULL) {
 		LM_ERR("cannot encode contact uri\n");
 		LM_ERR("cannot encode contact uri\n");
 		return -1;
 		return -1;
@@ -302,7 +300,7 @@ int th_mask_contact(sip_msg_t *msg)
 	return 0;
 	return 0;
 }
 }
 
 
-int th_mask_record_route(sip_msg_t *msg)
+int th_mask_record_route(sip_msg_t *msg, str *uri_prefix)
 {
 {
 	hdr_field_t *hdr;
 	hdr_field_t *hdr;
 	struct lump *l;
 	struct lump *l;
@@ -327,7 +325,7 @@ int th_mask_record_route(sip_msg_t *msg)
 			i++;
 			i++;
 			if(i != 1) {
 			if(i != 1) {
 				out.s = th_mask_encode(rr->nameaddr.uri.s, rr->nameaddr.uri.len,
 				out.s = th_mask_encode(rr->nameaddr.uri.s, rr->nameaddr.uri.len,
-						&th_uri_prefix, &out.len);
+						uri_prefix, &out.len);
 				if(out.s == NULL) {
 				if(out.s == NULL) {
 					LM_ERR("cannot encode r-r %d\n", i);
 					LM_ERR("cannot encode r-r %d\n", i);
 					return -1;
 					return -1;
@@ -353,7 +351,7 @@ int th_mask_record_route(sip_msg_t *msg)
 	return 0;
 	return 0;
 }
 }
 
 
-int th_unmask_via(sip_msg_t *msg, str *cookie)
+int th_unmask_via(sip_msg_t *msg, str *ip, str *cookie)
 {
 {
 	hdr_field_t *hdr;
 	hdr_field_t *hdr;
 	struct via_body *via;
 	struct via_body *via;
@@ -374,11 +372,11 @@ int th_unmask_via(sip_msg_t *msg, str *cookie)
 			LM_DBG("body: %d: [%.*s]\n", vlen, vlen, via->name.s);
 			LM_DBG("body: %d: [%.*s]\n", vlen, vlen, via->name.s);
 			if(i != 1) {
 			if(i != 1) {
 				/* Skip if via is not encoded */
 				/* Skip if via is not encoded */
-				if(th_uri_prefix_checks
-						&& (via->host.len != th_ip.len
-								|| strncasecmp(via->host.s, th_ip.s, th_ip.len)
-										   != 0)) {
-					LM_DBG("via %d is not encoded - skip\n", i);
+				if (th_uri_prefix_checks 
+				        && (via->host.len != ip->len
+	   					        || strncasecmp(via->host.s, ip->s, ip->len)
+								           != 0)) {
+					LM_DBG("via %d is not encoded - skip\n",i);
 					continue;
 					continue;
 				}
 				}
 
 
@@ -554,7 +552,7 @@ int th_unmask_callid_str(str *icallid, str *ocallid)
 	return 0;
 	return 0;
 }
 }
 
 
-int th_flip_record_route(sip_msg_t *msg, int mode)
+int th_flip_record_route(sip_msg_t *msg, str *uri_prefix, str *ip, int mode)
 {
 {
 	hdr_field_t *hdr;
 	hdr_field_t *hdr;
 	struct lump *l;
 	struct lump *l;
@@ -585,7 +583,7 @@ int th_flip_record_route(sip_msg_t *msg, int mode)
 		while(rr) {
 		while(rr) {
 			i++;
 			i++;
 			r2 = 0;
 			r2 = 0;
-			utype = th_get_uri_type(&rr->nameaddr.uri, &r2, &pval);
+			utype = th_get_uri_type(&rr->nameaddr.uri, &r2, ip, &pval);
 			if(utype == 0 && mode == 1) {
 			if(utype == 0 && mode == 1) {
 				if(r2 == 1) {
 				if(r2 == 1) {
 					act--;
 					act--;
@@ -601,7 +599,7 @@ int th_flip_record_route(sip_msg_t *msg, int mode)
 				case 1: /* encode */
 				case 1: /* encode */
 					if(act != 0 && mode == 1) {
 					if(act != 0 && mode == 1) {
 						out.s = th_mask_encode(rr->nameaddr.uri.s,
 						out.s = th_mask_encode(rr->nameaddr.uri.s,
-								rr->nameaddr.uri.len, &th_uri_prefix, &out.len);
+							rr->nameaddr.uri.len, uri_prefix, &out.len);
 						if(out.s == NULL) {
 						if(out.s == NULL) {
 							LM_ERR("cannot encode r-r %d\n", i);
 							LM_ERR("cannot encode r-r %d\n", i);
 							return -1;
 							return -1;
@@ -641,7 +639,7 @@ int th_flip_record_route(sip_msg_t *msg, int mode)
 	return 0;
 	return 0;
 }
 }
 
 
-int th_unmask_route(sip_msg_t *msg)
+int th_unmask_route(sip_msg_t *msg, str *uri_prefix)
 {
 {
 	hdr_field_t *hdr;
 	hdr_field_t *hdr;
 	struct lump *l;
 	struct lump *l;
@@ -667,10 +665,10 @@ int th_unmask_route(sip_msg_t *msg)
 			i++;
 			i++;
 			if(i != 1) {
 			if(i != 1) {
 				/* Skip if route is not encoded */
 				/* Skip if route is not encoded */
-				if(th_uri_prefix_checks
-						&& ((rr->nameaddr.uri.len < th_uri_prefix.len)
-								|| (strncasecmp(rr->nameaddr.uri.s,
-											th_uri_prefix.s, th_uri_prefix.len)
+				if (th_uri_prefix_checks
+						&& ((rr->nameaddr.uri.len<uri_prefix->len) 
+						        || (strncasecmp(rr->nameaddr.uri.s,
+								            uri_prefix->s, uri_prefix->len)
 										!= 0))) {
 										!= 0))) {
 					LM_DBG("rr %d is not encoded: [%.*s] - missing prefix\n", i,
 					LM_DBG("rr %d is not encoded: [%.*s] - missing prefix\n", i,
 							rr->nameaddr.uri.len, rr->nameaddr.uri.s);
 							rr->nameaddr.uri.len, rr->nameaddr.uri.s);
@@ -716,19 +714,19 @@ int th_unmask_route(sip_msg_t *msg)
 	return 0;
 	return 0;
 }
 }
 
 
-int th_unmask_ruri(sip_msg_t *msg)
+int th_unmask_ruri(sip_msg_t *msg, str *uri_prefix)
 {
 {
 	str eval;
 	str eval;
 	struct lump *l;
 	struct lump *l;
 	str out;
 	str out;
 
 
 	/* Do nothing if ruri is not encoded */
 	/* Do nothing if ruri is not encoded */
-	if(th_uri_prefix_checks
-			&& ((REQ_LINE(msg).uri.len < th_uri_prefix.len)
-					|| (strncasecmp(REQ_LINE(msg).uri.s, th_uri_prefix.s,
-								th_uri_prefix.len)
+	if (th_uri_prefix_checks
+			&& ((REQ_LINE(msg).uri.len<uri_prefix->len)
+					|| (strncasecmp(REQ_LINE(msg).uri.s, uri_prefix->s,
+								uri_prefix->len)
 							!= 0))) {
 							!= 0))) {
-		LM_DBG("ruri [%.*s] is not encoded", REQ_LINE(msg).uri.len,
+		LM_DBG("ruri [%.*s] is not encoded",REQ_LINE(msg).uri.len,
 				REQ_LINE(msg).uri.s);
 				REQ_LINE(msg).uri.s);
 		return 0;
 		return 0;
 	}
 	}
@@ -763,7 +761,7 @@ int th_unmask_ruri(sip_msg_t *msg)
 	return 0;
 	return 0;
 }
 }
 
 
-int th_unmask_refer_to(sip_msg_t *msg)
+int th_unmask_refer_to(sip_msg_t *msg, str *uri_prefix)
 {
 {
 	str eval;
 	str eval;
 	str *uri;
 	str *uri;
@@ -786,11 +784,11 @@ int th_unmask_refer_to(sip_msg_t *msg)
 	uri = &(get_refer_to(msg)->uri);
 	uri = &(get_refer_to(msg)->uri);
 
 
 	/* Do nothing if refer_to is not encoded */
 	/* Do nothing if refer_to is not encoded */
-	if(th_uri_prefix_checks
-			&& ((uri->len < th_uri_prefix.len)
-					|| (strncasecmp(uri->s, th_uri_prefix.s, th_uri_prefix.len)
+	if (th_uri_prefix_checks
+			&& ((uri->len<uri_prefix->len)
+					|| (strncasecmp(uri->s, uri_prefix->s, uri_prefix->len)
 							!= 0))) {
 							!= 0))) {
-		LM_DBG("refer-to [%.*s] is not encoded", uri->len, uri->s);
+		LM_DBG("refer-to [%.*s] is not encoded",uri->len,uri->s);
 		return 0;
 		return 0;
 	}
 	}
 
 

+ 8 - 8
src/modules/topoh/th_msg.h

@@ -29,18 +29,18 @@
 
 
 #include "../../core/parser/msg_parser.h"
 #include "../../core/parser/msg_parser.h"
 
 
-int th_mask_via(sip_msg_t *msg);
+int th_mask_via(sip_msg_t *msg, str *via_prefix);
 int th_mask_callid(sip_msg_t *msg);
 int th_mask_callid(sip_msg_t *msg);
 int th_mask_callid_str(str *icallid, str *ocallid);
 int th_mask_callid_str(str *icallid, str *ocallid);
-int th_mask_contact(sip_msg_t *msg);
-int th_mask_record_route(sip_msg_t *msg);
-int th_unmask_via(sip_msg_t *msg, str *cookie);
+int th_mask_contact(sip_msg_t *msg, str *uri_prefix);
+int th_mask_record_route(sip_msg_t *msg, str *uri_prefix);
+int th_unmask_via(sip_msg_t *msg, str *ip, str *cookie);
 int th_unmask_callid(sip_msg_t *msg);
 int th_unmask_callid(sip_msg_t *msg);
 int th_unmask_callid_str(str *icallid, str *ocallid);
 int th_unmask_callid_str(str *icallid, str *ocallid);
-int th_flip_record_route(sip_msg_t *msg, int mode);
-int th_unmask_ruri(sip_msg_t *msg);
-int th_unmask_route(sip_msg_t *msg);
-int th_unmask_refer_to(sip_msg_t *msg);
+int th_flip_record_route(sip_msg_t *msg, str *uri_prefix, str *ip, int mode);
+int th_unmask_ruri(sip_msg_t *msg, str *uri_prefix);
+int th_unmask_route(sip_msg_t *msg, str *uri_prefix);
+int th_unmask_refer_to(sip_msg_t *msg, str *uri_prefix);
 int th_update_hdr_replaces(sip_msg_t *msg);
 int th_update_hdr_replaces(sip_msg_t *msg);
 char *th_msg_update(sip_msg_t *msg, unsigned int *olen);
 char *th_msg_update(sip_msg_t *msg, unsigned int *olen);
 int th_add_via_cookie(sip_msg_t *msg, struct via_body *via);
 int th_add_via_cookie(sip_msg_t *msg, struct via_body *via);

+ 255 - 82
src/modules/topoh/topoh_mod.c

@@ -46,6 +46,7 @@
 #include "../../core/fmsg.h"
 #include "../../core/fmsg.h"
 #include "../../core/onsend.h"
 #include "../../core/onsend.h"
 #include "../../core/kemi.h"
 #include "../../core/kemi.h"
+#include "../../core/str_hash.h"
 #include "../../core/parser/msg_parser.h"
 #include "../../core/parser/msg_parser.h"
 #include "../../core/parser/parse_uri.h"
 #include "../../core/parser/parse_uri.h"
 #include "../../core/parser/parse_to.h"
 #include "../../core/parser/parse_to.h"
@@ -61,12 +62,13 @@ MODULE_VERSION
 
 
 
 
 #define TH_MASKMODE_SLIP3XXCONTACT 1
 #define TH_MASKMODE_SLIP3XXCONTACT 1
+#define TH_HT_SIZE 10
 
 
 /** module parameters */
 /** module parameters */
 str _th_key = str_init("aL9.n8~Hm]Z");
 str _th_key = str_init("aL9.n8~Hm]Z");
 str th_cookie_name = str_init("TH"); /* lost parameter? */
 str th_cookie_name = str_init("TH"); /* lost parameter? */
-str th_cookie_value = {0, 0};		 /* lost parameter? */
-str th_ip = str_init("127.0.0.8");
+str th_cookie_value = {0, 0};        /* lost parameter? */
+str th_ip = STR_NULL;
 str th_uparam_name = str_init("line");
 str th_uparam_name = str_init("line");
 str th_uparam_prefix = str_init("sr-");
 str th_uparam_prefix = str_init("sr-");
 str th_vparam_name = str_init("branch");
 str th_vparam_name = str_init("branch");
@@ -84,12 +86,17 @@ int th_uri_prefix_checks = 0;
 int th_mask_addr_myself = 0;
 int th_mask_addr_myself = 0;
 int _th_use_mode = 0;
 int _th_use_mode = 0;
 
 
+struct str_hash_table *th_socket_hash_table;
+
 sanity_api_t scb;
 sanity_api_t scb;
 
 
 int th_msg_received(sr_event_param_t *evp);
 int th_msg_received(sr_event_param_t *evp);
 int th_msg_sent(sr_event_param_t *evp);
 int th_msg_sent(sr_event_param_t *evp);
 int th_execute_event_route(sip_msg_t *msg, sr_event_param_t *evp, int evtype,
 int th_execute_event_route(sip_msg_t *msg, sr_event_param_t *evp, int evtype,
 		int evidx, str *evname);
 		int evidx, str *evname);
+int th_build_via_prefix(str *via_prefix, str *ip);
+int th_build_uri_prefix(str *uri_prefix, str *ip);
+int th_parse_socket_list(socket_info_t *socket);
 
 
 /** module functions */
 /** module functions */
 static int mod_init(void);
 static int mod_init(void);
@@ -103,20 +110,20 @@ static str _th_eventrt_outgoing_name = str_init("topoh:msg-outgoing");
 static int _th_eventrt_sending = -1;
 static int _th_eventrt_sending = -1;
 static str _th_eventrt_sending_name = str_init("topoh:msg-sending");
 static str _th_eventrt_sending_name = str_init("topoh:msg-sending");
 
 
-static param_export_t params[] = {{"mask_key", PARAM_STR, &_th_key},
-		{"mask_ip", PARAM_STR, &th_ip},
-		{"mask_callid", PARAM_INT, &th_param_mask_callid},
-		{"mask_mode", PARAM_INT, &th_param_mask_mode},
-		{"uparam_name", PARAM_STR, &th_uparam_name},
-		{"uparam_prefix", PARAM_STR, &th_uparam_prefix},
-		{"vparam_name", PARAM_STR, &th_vparam_name},
-		{"vparam_prefix", PARAM_STR, &th_vparam_prefix},
-		{"callid_prefix", PARAM_STR, &th_callid_prefix},
-		{"sanity_checks", PARAM_INT, &th_sanity_checks},
-		{"uri_prefix_checks", PARAM_INT, &th_uri_prefix_checks},
-		{"event_callback", PARAM_STR, &_th_eventrt_callback},
-		{"event_mode", PARAM_INT, &_th_eventrt_mode},
-		{"use_mode", PARAM_INT, &_th_use_mode}, {0, 0, 0}};
+static param_export_t params[]={{"mask_key",		PARAM_STR, &_th_key},
+	{"mask_ip",		PARAM_STR, &th_ip},
+	{"mask_callid",		PARAM_INT, &th_param_mask_callid},
+	{"mask_mode",		PARAM_INT, &th_param_mask_mode},
+	{"uparam_name",		PARAM_STR, &th_uparam_name},
+	{"uparam_prefix",	PARAM_STR, &th_uparam_prefix},
+	{"vparam_name",		PARAM_STR, &th_vparam_name},
+	{"vparam_prefix",	PARAM_STR, &th_vparam_prefix},
+	{"callid_prefix",	PARAM_STR, &th_callid_prefix},
+	{"sanity_checks",	PARAM_INT, &th_sanity_checks},
+	{"uri_prefix_checks",	PARAM_INT, &th_uri_prefix_checks},
+	{"event_callback",	PARAM_STR, &_th_eventrt_callback},
+	{"event_mode",		PARAM_INT, &_th_eventrt_mode},
+	{"use_mode",		PARAM_INT, &_th_use_mode}, {0, 0, 0}};
 
 
 static cmd_export_t cmds[] = {
 static cmd_export_t cmds[] = {
 		{"bind_topoh", (cmd_function)bind_topoh, 0, 0, 0, 0},
 		{"bind_topoh", (cmd_function)bind_topoh, 0, 0, 0, 0},
@@ -136,6 +143,12 @@ struct module_exports exports = {
 		0				 /* module destroy function */
 		0				 /* module destroy function */
 };
 };
 
 
+struct th_socket_strings {
+	str ip;
+	str via_prefix;
+	str uri_prefix;
+};
+
 /**
 /**
  * init module function
  * init module function
  */
  */
@@ -171,79 +184,223 @@ static int mod_init(void)
 			goto error;
 			goto error;
 		}
 		}
 	}
 	}
-	if(th_ip.len <= 0) {
-		LM_ERR("mask IP parameter is invalid\n");
-		goto error;
-	}
 
 
-	if(th_ip.len + 32 >= MAX_URI_SIZE) {
-		LM_ERR("mask address is too long\n");
-		goto error;
-	}
-	memcpy(buri, "sip:", 4);
-	memcpy(buri + 4, th_ip.s, th_ip.len);
-	buri[th_ip.len + 8] = '\0';
+	if(th_ip.len != 0) {
+		if(th_ip.len + 32 >= MAX_URI_SIZE) {
+			LM_ERR("mask address is too long\n");
+			goto error;
+		}
+		memcpy(buri, "sip:", 4);
+		memcpy(buri+4, th_ip.s, th_ip.len);
+		buri[th_ip.len+8] = '\0';
+
+		if(parse_uri(buri, th_ip.len+4, &puri) < 0) {
+			LM_ERR("mask uri is invalid\n");
+			goto error;
+		}
+		if(check_self(&puri.host, puri.port_no, 0) == 1) {
+			th_mask_addr_myself = 1;
+			LM_INFO("mask address matches myself [%.*s]\n",
+					th_ip.len, th_ip.s);
+		}
+
+		if(th_build_via_prefix(&th_via_prefix, &th_ip)) {
+			goto error;
+		}
+		if(th_build_uri_prefix(&th_uri_prefix, &th_ip)) {
+			goto error;
+		}
+	} else {
+		th_socket_hash_table = pkg_malloc(sizeof(struct str_hash_table));
+		if(th_socket_hash_table == NULL){
+			PKG_MEM_ERROR_FMT("th_socket_hash_table\n");
+			goto error;
+		}
+		if(str_hash_alloc(th_socket_hash_table, TH_HT_SIZE))
+			goto error;
+
+		str_hash_init(th_socket_hash_table);
+		if(th_parse_socket_list(*get_sock_info_list(PROTO_UDP)) != 0 ||
+		   th_parse_socket_list(*get_sock_info_list(PROTO_TCP)) != 0 ||
+		   th_parse_socket_list(*get_sock_info_list(PROTO_TLS)) != 0 ||
+		   th_parse_socket_list(*get_sock_info_list(PROTO_SCTP)) !=0)
+			goto error;
 
 
-	if(parse_uri(buri, th_ip.len + 4, &puri) < 0) {
-		LM_ERR("mask uri is invalid\n");
-		goto error;
-	}
-	if(check_self(&puri.host, puri.port_no, 0) == 1) {
-		th_mask_addr_myself = 1;
-		LM_INFO("mask address matches myself [%.*s]\n", th_ip.len, th_ip.s);
 	}
 	}
 
 
+	th_mask_init();
+	sr_event_register_cb(SREV_NET_DATA_IN, th_msg_received);
+	sr_event_register_cb(SREV_NET_DATA_OUT, th_msg_sent);
+#ifdef USE_TCP
+	tcp_set_clone_rcvbuf(1);
+#endif
+	return 0;
+error:
+	if(th_socket_hash_table != NULL && th_socket_hash_table->table)
+		pkg_free(th_socket_hash_table->table);
+
+	if(th_socket_hash_table != NULL)
+		pkg_free( th_socket_hash_table );
+	return -1;
+}
+
+/**
+ *
+ */
+int th_build_via_prefix(str *via_prefix, str *ip)
+{
 	/* 'SIP/2.0/UDP ' + ip + ';' + param + '=' + prefix (+ '\0') */
 	/* 'SIP/2.0/UDP ' + ip + ';' + param + '=' + prefix (+ '\0') */
-	th_via_prefix.len =
-			12 + th_ip.len + 1 + th_vparam_name.len + 1 + th_vparam_prefix.len;
-	th_via_prefix.s = (char *)pkg_malloc(th_via_prefix.len + 1);
-	if(th_via_prefix.s == NULL) {
-		PKG_MEM_ERROR_FMT("via prefix parameter\n");
-		goto error;
-	}
-	/* 'sip:' + ip + ';' + param + '=' + prefix (+ '\0') */
-	th_uri_prefix.len =
-			4 + th_ip.len + 1 + th_uparam_name.len + 1 + th_uparam_prefix.len;
-	th_uri_prefix.s = (char *)pkg_malloc(th_uri_prefix.len + 1);
-	if(th_uri_prefix.s == NULL) {
-		pkg_free(th_via_prefix.s);
-		PKG_MEM_ERROR_FMT("uri prefix parameter\n");
-		goto error;
+	via_prefix->len = 12 + ip->len + 1 + th_vparam_name.len + 1
+		+ th_vparam_prefix.len;
+	via_prefix->s = (char*)pkg_malloc(via_prefix->len+1);
+	if(via_prefix->s == NULL) {
+		PKG_MEM_ERROR_FMT("via prefix\n");
+		return 1;
 	}
 	}
+
 	/* build via prefix */
 	/* build via prefix */
-	memcpy(th_via_prefix.s, "SIP/2.0/UDP ", 12);
-	memcpy(th_via_prefix.s + 12, th_ip.s, th_ip.len);
-	th_via_prefix.s[12 + th_ip.len] = ';';
-	memcpy(th_via_prefix.s + 12 + th_ip.len + 1, th_vparam_name.s,
+	memcpy(via_prefix->s, "SIP/2.0/UDP ", 12);
+	memcpy(via_prefix->s+12, ip->s, ip->len);
+	via_prefix->s[12+ip->len] = ';';
+	memcpy(via_prefix->s+12+ip->len+1, th_vparam_name.s,
 			th_vparam_name.len);
 			th_vparam_name.len);
-	th_via_prefix.s[12 + th_ip.len + 1 + th_vparam_name.len] = '=';
-	memcpy(th_via_prefix.s + 12 + th_ip.len + 1 + th_vparam_name.len + 1,
+	via_prefix->s[12+ip->len+1+th_vparam_name.len] = '=';
+	memcpy(via_prefix->s+12+ip->len+1+th_vparam_name.len+1,
 			th_vparam_prefix.s, th_vparam_prefix.len);
 			th_vparam_prefix.s, th_vparam_prefix.len);
-	th_via_prefix.s[th_via_prefix.len] = '\0';
-	LM_DBG("VIA prefix: [%s]\n", th_via_prefix.s);
+	via_prefix->s[via_prefix->len] = '\0';
+	LM_DBG("VIA prefix: [%s]\n", via_prefix->s);
+
+	return 0;
+}
+
+/**
+ *
+ */
+int th_build_uri_prefix(str *uri_prefix, str *ip)
+{
+	/* 'sip:' + ip + ';' + param + '=' + prefix (+ '\0') */
+	uri_prefix->len = 4 + ip->len + 1 + th_uparam_name.len + 1
+		+ th_uparam_prefix.len;
+	uri_prefix->s = (char*)pkg_malloc(uri_prefix->len+1);
+	if(uri_prefix->s == NULL) {
+		PKG_MEM_ERROR_FMT("uri prefix\n");
+		return 1;
+	}
+
 	/* build uri prefix */
 	/* build uri prefix */
-	memcpy(th_uri_prefix.s, "sip:", 4);
-	memcpy(th_uri_prefix.s + 4, th_ip.s, th_ip.len);
-	th_uri_prefix.s[4 + th_ip.len] = ';';
-	memcpy(th_uri_prefix.s + 4 + th_ip.len + 1, th_uparam_name.s,
-			th_uparam_name.len);
-	th_uri_prefix.s[4 + th_ip.len + 1 + th_uparam_name.len] = '=';
-	memcpy(th_uri_prefix.s + 4 + th_ip.len + 1 + th_uparam_name.len + 1,
+	memcpy(uri_prefix->s, "sip:", 4);
+	memcpy(uri_prefix->s+4, ip->s, ip->len);
+	uri_prefix->s[4+ip->len] = ';';
+	memcpy(uri_prefix->s+4+ip->len+1, th_uparam_name.s, th_uparam_name.len);
+	uri_prefix->s[4+ip->len+1+th_uparam_name.len] = '=';
+	memcpy(uri_prefix->s+4+ip->len+1+th_uparam_name.len+1,
 			th_uparam_prefix.s, th_uparam_prefix.len);
 			th_uparam_prefix.s, th_uparam_prefix.len);
-	th_uri_prefix.s[th_uri_prefix.len] = '\0';
-	LM_DBG("URI prefix: [%s]\n", th_uri_prefix.s);
+	uri_prefix->s[uri_prefix->len] = '\0';
+	LM_DBG("URI prefix: [%s]\n", uri_prefix->s);
+
+	return 0;
+}
+
+/**
+ *
+ */
+int th_build_socket_strings(socket_info_t *socket)
+{
+	struct th_socket_strings *socket_strings;
+	struct str_hash_entry *table_entry;
+	str *socket_ip;
+
+	if(str_hash_get(th_socket_hash_table, socket->sockname.s, socket->sockname.len) != 0)
+		return 0;
+
+	socket_strings = pkg_malloc(sizeof(struct th_socket_strings));
+	if(socket_strings == NULL) {
+		PKG_MEM_ERROR_FMT("socket_strings\n");
+		goto error;
+	}
+	table_entry = pkg_malloc(sizeof(struct str_hash_entry));
+	if(table_entry == NULL) {
+		PKG_MEM_ERROR_FMT("table_entry\n");
+		goto error;
+	}
+	if(pkg_str_dup(&table_entry->key, &socket->sockname)) {
+		PKG_MEM_ERROR_FMT("table_entry.key.s\n");
+		goto error;
+	}
+	table_entry->u.p = socket_strings;
+
+	if(socket->useinfo.address_str.len > 0) {
+		LM_DBG("Using socket %s advertised ip %s\n", socket->sockname.s, socket->useinfo.address_str.s);
+		socket_ip = &socket->useinfo.address_str;
+	} else {
+		LM_DBG("using socket %s ip %s\n", socket->sockname.s, socket->address_str.s);
+		socket_ip = &socket->address_str;
+	}
+	if(pkg_str_dup(&socket_strings->ip, socket_ip)) {
+		PKG_MEM_ERROR_FMT("socket_strings.ip\n");
+		goto error;
+	}
+	th_build_via_prefix(&socket_strings->via_prefix, socket_ip);
+	th_build_uri_prefix(&socket_strings->uri_prefix, socket_ip);
+	str_hash_add(th_socket_hash_table, table_entry);
 
 
-	th_mask_init();
-	sr_event_register_cb(SREV_NET_DATA_IN, th_msg_received);
-	sr_event_register_cb(SREV_NET_DATA_OUT, th_msg_sent);
-#ifdef USE_TCP
-	tcp_set_clone_rcvbuf(1);
-#endif
 	return 0;
 	return 0;
+
 error:
 error:
+	if(socket_strings->ip.s!=NULL)
+		pkg_free(socket_strings->ip.s);
+	if(table_entry->key.s != NULL)
+		pkg_free(table_entry->key.s);
+	if(table_entry != NULL)
+		pkg_free(table_entry);
+	if(socket_strings != NULL)
+		pkg_free(socket_strings);
 	return -1;
 	return -1;
 }
 }
 
 
+/**
+ *
+ */
+int th_parse_socket_list(socket_info_t *socket)
+{
+	while(socket != NULL) {
+		if(th_build_socket_strings(socket) != 0)
+			return -1;
+		socket = socket->next;
+	}
+
+	return 0;
+}
+
+/**
+ *
+ */
+int th_get_socket_strings(socket_info_t *socket, str **ip, str **via_prefix, str **uri_prefix)
+{
+	struct th_socket_strings *socket_strings;
+	struct str_hash_entry *table_entry;
+
+	if(th_ip.len > 0){
+		*ip = &th_ip;
+		*via_prefix = &th_via_prefix;
+		*uri_prefix = &th_uri_prefix;
+	} else {
+		table_entry = str_hash_get(th_socket_hash_table, socket->sockname.s, socket->sockname.len);
+		if(table_entry==0) {
+			LM_DBG("No entry for socket %s", socket->sockname.s);
+			return -1;
+		} else {
+			socket_strings = table_entry->u.p;
+		}
+
+		*ip = &socket_strings->ip;
+		*via_prefix = &socket_strings->via_prefix;
+		*uri_prefix = &socket_strings->uri_prefix;
+	}
+
+	return 0;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -314,6 +471,14 @@ int th_msg_received(sr_event_param_t *evp)
 	char *nbuf = NULL;
 	char *nbuf = NULL;
 	int direction;
 	int direction;
 	int dialog;
 	int dialog;
+	str *ip;
+	str *via_prefix;
+	str *uri_prefix;
+
+	if(th_get_socket_strings(evp->rcv->bind_address, &ip, &via_prefix, &uri_prefix)) {
+		LM_ERR("Socket address handling failed\n");
+		return -1;
+	}
 
 
 	obuf = (str *)evp->data;
 	obuf = (str *)evp->data;
 	memset(&msg, 0, sizeof(sip_msg_t));
 	memset(&msg, 0, sizeof(sip_msg_t));
@@ -351,9 +516,9 @@ int th_msg_received(sr_event_param_t *evp)
 		}
 		}
 		if(dialog) {
 		if(dialog) {
 			/* dialog request */
 			/* dialog request */
-			th_unmask_ruri(&msg);
-			th_unmask_route(&msg);
-			th_unmask_refer_to(&msg);
+			th_unmask_ruri(&msg, uri_prefix);
+			th_unmask_route(&msg, uri_prefix);
+			th_unmask_refer_to(&msg, uri_prefix);
 			if(direction == 1) {
 			if(direction == 1) {
 				th_unmask_callid(&msg);
 				th_unmask_callid(&msg);
 			}
 			}
@@ -367,8 +532,8 @@ int th_msg_received(sr_event_param_t *evp)
 				goto done;
 				goto done;
 		}
 		}
 
 
-		th_unmask_via(&msg, &th_cookie_value);
-		th_flip_record_route(&msg, 0);
+		th_unmask_via(&msg, ip, &th_cookie_value);
+		th_flip_record_route(&msg, uri_prefix, ip, 0);
 		if(th_cookie_value.s[0] == 'u') {
 		if(th_cookie_value.s[0] == 'u') {
 			th_cookie_value.s = "dc";
 			th_cookie_value.s = "dc";
 		} else {
 		} else {
@@ -409,6 +574,14 @@ int th_msg_sent(sr_event_param_t *evp)
 	int dialog;
 	int dialog;
 	int local;
 	int local;
 	str nbuf = STR_NULL;
 	str nbuf = STR_NULL;
+	str *ip;
+	str *via_prefix;
+	str *uri_prefix;
+
+	if(th_get_socket_strings(evp->dst->send_sock, &ip, &via_prefix, &uri_prefix)) {
+		LM_ERR("Socket address handling failed\n");
+		return -1;
+	}
 
 
 	obuf = (str *)evp->data;
 	obuf = (str *)evp->data;
 
 
@@ -472,9 +645,9 @@ int th_msg_sent(sr_event_param_t *evp)
 				goto done;
 				goto done;
 			}
 			}
 		}
 		}
-		th_mask_via(&msg);
-		th_mask_contact(&msg);
-		th_mask_record_route(&msg);
+		th_mask_via(&msg, via_prefix);
+		th_mask_contact(&msg, uri_prefix);
+		th_mask_record_route(&msg, uri_prefix);
 		if(dialog) {
 		if(dialog) {
 			/* dialog request */
 			/* dialog request */
 			if(direction == 0) {
 			if(direction == 0) {
@@ -498,11 +671,11 @@ int th_msg_sent(sr_event_param_t *evp)
 				th_mask_callid(&msg);
 				th_mask_callid(&msg);
 			}
 			}
 		} else {
 		} else {
-			th_flip_record_route(&msg, 1);
+			th_flip_record_route(&msg, uri_prefix, ip, 1);
 			if(!(th_param_mask_mode & TH_MASKMODE_SLIP3XXCONTACT)
 			if(!(th_param_mask_mode & TH_MASKMODE_SLIP3XXCONTACT)
 					|| msg.first_line.u.reply.statuscode < 300
 					|| msg.first_line.u.reply.statuscode < 300
 					|| msg.first_line.u.reply.statuscode > 399) {
 					|| msg.first_line.u.reply.statuscode > 399) {
-				th_mask_contact(&msg);
+				th_mask_contact(&msg, uri_prefix);
 			}
 			}
 			if(th_cookie_value.s[0] == 'd') {
 			if(th_cookie_value.s[0] == 'd') {
 				th_mask_callid(&msg);
 				th_mask_callid(&msg);