Browse Source

siptrace: added support for HEP encapuslation. Disabled DB's check in the duplicate mode.

Alexandr Dubovikov 14 years ago
parent
commit
72778ab8a5

+ 102 - 16
modules_k/siptrace/README

@@ -6,6 +6,12 @@ Daniel-Constantin Mierla
 
 
 Edited by
 Edited by
 
 
+Alexandr Dubovikov
+
+   <[email protected]>
+
+Edited by
+
 Daniel-Constantin Mierla
 Daniel-Constantin Mierla
 
 
    <[email protected]>
    <[email protected]>
@@ -34,8 +40,12 @@ Daniel-Constantin Mierla
               3.5. traced_user_avp (str)
               3.5. traced_user_avp (str)
               3.6. trace_table_avp (str)
               3.6. trace_table_avp (str)
               3.7. duplicate_uri (str)
               3.7. duplicate_uri (str)
-              3.8. trace_local_ip (str)
-              3.9. trace_sl_acks (integer)
+              3.8. trace_to_database (integer)
+              3.9. trace_local_ip (str)
+              3.10. trace_sl_acks (integer)
+              3.11. xheaders_write (integer)
+              3.12. xheaders_read (integer)
+              3.13. hep_mode_on (integer)
 
 
         4. Exported Functions
         4. Exported Functions
 
 
@@ -57,9 +67,13 @@ Daniel-Constantin Mierla
    1.5. Set traced_user_avp parameter
    1.5. Set traced_user_avp parameter
    1.6. Set trace_table_avp parameter
    1.6. Set trace_table_avp parameter
    1.7. Set duplicate_uri parameter
    1.7. Set duplicate_uri parameter
-   1.8. Set trace_local_ip parameter
-   1.9. Set trace_sl_acks parameter
-   1.10. sip_trace() usage
+   1.8. Set trace_to_database parameter
+   1.9. Set trace_local_ip parameter
+   1.10. Set trace_sl_acks parameter
+   1.11. Set xheaders_write parameter
+   1.12. Set xheaders_read parameter
+   1.13. Set hep_mode_on parameter
+   1.14. sip_trace() usage
 
 
 Chapter 1. Admin Guide
 Chapter 1. Admin Guide
 
 
@@ -80,8 +94,12 @@ Chapter 1. Admin Guide
         3.5. traced_user_avp (str)
         3.5. traced_user_avp (str)
         3.6. trace_table_avp (str)
         3.6. trace_table_avp (str)
         3.7. duplicate_uri (str)
         3.7. duplicate_uri (str)
-        3.8. trace_local_ip (str)
-        3.9. trace_sl_acks (integer)
+        3.8. trace_to_database (integer)
+        3.9. trace_local_ip (str)
+        3.10. trace_sl_acks (integer)
+        3.11. xheaders_write (integer)
+        3.12. xheaders_read (integer)
+        3.13. hep_mode_on (integer)
 
 
    4. Exported Functions
    4. Exported Functions
 
 
@@ -96,8 +114,9 @@ Chapter 1. Admin Guide
 
 
 1. Overview
 1. Overview
 
 
-   Offer a possibility to store incoming/outgoing SIP messages in
-   database.
+   Offer a possibility to store incoming/outgoing SIP messages in database
+   and/or duplicate to the capturing server (homer encapsulation protocol
+   or plain sip mode)
 
 
    There are two ways of storing information.
    There are two ways of storing information.
      * by calling explicitely the sip_trace() method in Kamailio
      * by calling explicitely the sip_trace() method in Kamailio
@@ -141,8 +160,12 @@ Chapter 1. Admin Guide
    3.5. traced_user_avp (str)
    3.5. traced_user_avp (str)
    3.6. trace_table_avp (str)
    3.6. trace_table_avp (str)
    3.7. duplicate_uri (str)
    3.7. duplicate_uri (str)
-   3.8. trace_local_ip (str)
-   3.9. trace_sl_acks (integer)
+   3.8. trace_to_database (integer)
+   3.9. trace_local_ip (str)
+   3.10. trace_sl_acks (integer)
+   3.11. xheaders_write (integer)
+   3.12. xheaders_read (integer)
+   3.13. hep_mode_on (integer)
 
 
 3.1. db_url (str)
 3.1. db_url (str)
 
 
@@ -231,7 +254,21 @@ modparam("siptrace", "trace_table_avp", "$avp(s:siptrace_table)")
 modparam("siptrace", "duplicate_uri", "sip:10.1.1.1:5888")
 modparam("siptrace", "duplicate_uri", "sip:10.1.1.1:5888")
 ...
 ...
 
 
-3.8. trace_local_ip (str)
+3.8. trace_to_database (integer)
+
+   Parameter to enable/disable inserts to the Database from this Kamailio.
+
+   In case we only want to send the SIP-Messages to the duplicate_uri and
+   not store the information to the local database we can set this to "0".
+
+   Default value is "1".
+
+   Example 1.8. Set trace_to_database parameter
+...
+modparam("siptrace", "trace_to_database", 0)
+...
+
+3.9. trace_local_ip (str)
 
 
    The address to be used in fromip field for local generated messages. If
    The address to be used in fromip field for local generated messages. If
    not set, the module sets it to the address of the socket that will be
    not set, the module sets it to the address of the socket that will be
@@ -239,12 +276,12 @@ modparam("siptrace", "duplicate_uri", "sip:10.1.1.1:5888")
 
 
    Default value is "NULL".
    Default value is "NULL".
 
 
-   Example 1.8. Set trace_local_ip parameter
+   Example 1.9. Set trace_local_ip parameter
 ...
 ...
 modparam("siptrace", "trace_local_ip", "10.1.1.1:5064")
 modparam("siptrace", "trace_local_ip", "10.1.1.1:5064")
 ...
 ...
 
 
-3.9. trace_sl_acks (integer)
+3.10. trace_sl_acks (integer)
 
 
    Parameter to enable/disable tracing of SL-filtered ACKs (on=1 / off=0).
    Parameter to enable/disable tracing of SL-filtered ACKs (on=1 / off=0).
 
 
@@ -256,11 +293,60 @@ modparam("siptrace", "trace_local_ip", "10.1.1.1:5064")
 
 
    Default value is "1".
    Default value is "1".
 
 
-   Example 1.9. Set trace_sl_acks parameter
+   Example 1.10. Set trace_sl_acks parameter
 ...
 ...
 modparam("siptrace", "trace_sl_acks", 0)
 modparam("siptrace", "trace_sl_acks", 0)
 ...
 ...
 
 
+3.11. xheaders_write (integer)
+
+   Parameter to enable/disable writing of x-headers.
+
+   Stores fromip, toip, method and direction in X-Siptrace-* headers. This
+   allows to transmit them to a second kamailio server using the
+   duplicate_uri feature. Because the headers are added after the data is
+   written to the database, the headers only show up in the packets sent
+   by duplicate_uri.
+
+   See xheaders_read, it should be used on the receiving side.
+
+   Note: The headers are first read, then written. This allows to relay
+   the information over more then two kamailio servers by setting both
+   xheaders_write and xheaders_read to "1" on the servers in the middle.
+
+   Default value is "0".
+
+   Example 1.11. Set xheaders_write parameter
+...
+modparam("siptrace", "xheaders_write", 0)
+...
+
+3.12. xheaders_read (integer)
+
+   Parameter to enable/disable reading of x-headers.
+
+   Reads and removes the X-Siptrace-* headers. Packets not containing the
+   headers are neither stored to the database nor relayed (duplicate_uri).
+   See xheaders_write for further information.
+
+   Default value is "0".
+
+   Example 1.12. Set xheaders_read parameter
+...
+modparam("siptrace", "xheaders_read", 0)
+...
+
+3.13. hep_mode_on (integer)
+
+   Parameter to enable/disable homer encapsulate mode (on(1)/off(0))
+
+   Default value is "0".
+
+   Example 1.13. Set hep_mode_on parameter
+...
+modparam("siptrace", "hep_mode_on", 1)
+...
+
 4. Exported Functions
 4. Exported Functions
 
 
    4.1. sip_trace()
    4.1. sip_trace()
@@ -273,7 +359,7 @@ modparam("siptrace", "trace_sl_acks", 0)
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    ONREPLY_ROUTE, BRANCH_ROUTE.
    ONREPLY_ROUTE, BRANCH_ROUTE.
 
 
-   Example 1.10. sip_trace() usage
+   Example 1.14. sip_trace() usage
 ...
 ...
 sip_trace();
 sip_trace();
 ...
 ...

+ 5 - 0
modules_k/siptrace/doc/siptrace.xml

@@ -18,6 +18,11 @@
 		<surname>Mierla</surname>
 		<surname>Mierla</surname>
 		<email>[email protected]</email>
 		<email>[email protected]</email>
 	    </author>
 	    </author>
+	    <editor>
+                <firstname>Alexandr</firstname>
+                <surname>Dubovikov</surname>
+                    <email>[email protected]</email>
+            </editor>
 	    <editor>
 	    <editor>
 		<firstname>Daniel-Constantin</firstname>
 		<firstname>Daniel-Constantin</firstname>
 		<surname>Mierla</surname>
 		<surname>Mierla</surname>

+ 22 - 1
modules_k/siptrace/doc/siptrace_admin.xml

@@ -16,7 +16,9 @@
 	<section>
 	<section>
 	<title>Overview</title>
 	<title>Overview</title>
 	<para>
 	<para>
-		Offer a possibility to store incoming/outgoing SIP messages in database.
+		Offer a possibility to store incoming/outgoing SIP messages in database
+		and/or duplicate to the capturing server (homer encapsulation protocol 
+		or plain sip mode)
 	</para>
 	</para>
 	<para>
 	<para>
 	There are two ways of storing information.
 	There are two ways of storing information.
@@ -365,6 +367,25 @@ modparam("siptrace", "xheaders_read", 0)
 </programlisting>
 </programlisting>
 		</example>
 		</example>
 	</section>
 	</section>
+	<section>
+                <title><varname>hep_mode_on</varname> (integer)</title>
+                <para>
+                Parameter to enable/disable homer encapsulate mode (on(1)/off(0))
+                </para>
+                <para>
+                <emphasis>
+                        Default value is "0".
+                </emphasis>
+                </para>
+                <example>
+                <title>Set <varname>hep_mode_on</varname> parameter</title>
+                <programlisting format="linespecific">
+...
+modparam("siptrace", "hep_mode_on", 1)
+...
+</programlisting>
+                </example>
+        </section>
 	</section>
 	</section>
 	
 	
 	<section>
 	<section>

+ 287 - 31
modules_k/siptrace/siptrace.c

@@ -50,6 +50,8 @@
 #include "../../str.h"
 #include "../../str.h"
 #include "../../onsend.h"
 #include "../../onsend.h"
 
 
+#include "../../modules/sipcapture/sipcapture.h"
+
 #ifdef STATISTICS
 #ifdef STATISTICS
 #include "../../lib/kcore/statistics.h"
 #include "../../lib/kcore/statistics.h"
 #endif
 #endif
@@ -97,6 +99,10 @@ static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps);
 static void trace_sl_onreply_out(sl_cbp_t *slcb);
 static void trace_sl_onreply_out(sl_cbp_t *slcb);
 static void trace_sl_ack_in(sl_cbp_t *slcb);
 static void trace_sl_ack_in(sl_cbp_t *slcb);
 
 
+static int trace_send_hep_duplicate(str *body, str *from, str *to);
+static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int proto);
+
+
 static struct mi_root* sip_trace_mi(struct mi_root* cmd, void* param );
 static struct mi_root* sip_trace_mi(struct mi_root* cmd, void* param );
 
 
 static str db_url             = str_init(DEFAULT_RODB_URL);
 static str db_url             = str_init(DEFAULT_RODB_URL);
@@ -145,6 +151,8 @@ static str trace_table_avp_str = {NULL, 0};
 
 
 static str trace_local_ip = {NULL, 0};
 static str trace_local_ip = {NULL, 0};
 
 
+int hep_mode_on = 0;
+
 db1_con_t *db_con = NULL; 		/*!< database connection */
 db1_con_t *db_con = NULL; 		/*!< database connection */
 db_func_t db_funcs;      		/*!< Database functions */
 db_func_t db_funcs;      		/*!< Database functions */
 
 
@@ -184,6 +192,7 @@ static param_export_t params[] = {
 	{"trace_sl_acks",      INT_PARAM, &trace_sl_acks        },
 	{"trace_sl_acks",      INT_PARAM, &trace_sl_acks        },
 	{"xheaders_write",     INT_PARAM, &xheaders_write       },
 	{"xheaders_write",     INT_PARAM, &xheaders_write       },
 	{"xheaders_read",      INT_PARAM, &xheaders_read        },
 	{"xheaders_read",      INT_PARAM, &xheaders_read        },
+	{"hep_mode_on",        INT_PARAM, &hep_mode_on          },	 
 	{0, 0, 0}
 	{0, 0, 0}
 };
 };
 
 
@@ -276,19 +285,29 @@ static int mod_init(void)
 		return -1;
 		return -1;
 	}
 	}
 	trace_flag = 1<<trace_flag;
 	trace_flag = 1<<trace_flag;
-
-	/* Find a database module */
-	if (db_bind_mod(&db_url, &db_funcs))
-	{
-		LM_ERR("unable to bind database module\n");
-		return -1;
-	}
-	if (!DB_CAPABILITY(db_funcs, DB_CAP_INSERT))
-	{
-		LM_ERR("database modules does not provide all functions needed"
-				" by module\n");
+	
+	trace_to_database_flag = (int*)shm_malloc(sizeof(int));
+	if(trace_to_database_flag==NULL) {
+		LM_ERR("no more shm memory left\n");
 		return -1;
 		return -1;
 	}
 	}
+	
+	*trace_to_database_flag = trace_to_database;
+
+	/* Find a database module if needed */
+	if(trace_to_database_flag!=NULL && *trace_to_database_flag!=0) {
+    	        if (db_bind_mod(&db_url, &db_funcs))
+        	{
+	        	LM_ERR("unable to bind database module\n");
+        		return -1;
+                }
+        	if (trace_to_database_flag && !DB_CAPABILITY(db_funcs, DB_CAP_INSERT))
+                {
+		        LM_ERR("database modules does not provide all functions needed"
+    				" by module\n");
+        		return -1;
+        	}
+        }
 
 
 	trace_on_flag = (int*)shm_malloc(sizeof(int));
 	trace_on_flag = (int*)shm_malloc(sizeof(int));
 	if(trace_on_flag==NULL) {
 	if(trace_on_flag==NULL) {
@@ -297,15 +316,7 @@ static int mod_init(void)
 	}
 	}
 	
 	
 	*trace_on_flag = trace_on;
 	*trace_on_flag = trace_on;
-	
-	trace_to_database_flag = (int*)shm_malloc(sizeof(int));
-	if(trace_to_database_flag==NULL) {
-		LM_ERR("no more shm memory left\n");
-		return -1;
-	}
-	
-	*trace_to_database_flag = trace_to_database;
-	
+		
 	xheaders_write_flag = (int*)shm_malloc(sizeof(int));
 	xheaders_write_flag = (int*)shm_malloc(sizeof(int));
 	xheaders_read_flag = (int*)shm_malloc(sizeof(int));
 	xheaders_read_flag = (int*)shm_malloc(sizeof(int));
 	if (!(xheaders_write_flag && xheaders_read_flag)) {
 	if (!(xheaders_write_flag && xheaders_read_flag)) {
@@ -423,12 +434,14 @@ static int child_init(int rank)
 	if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
 	if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
 		return 0; /* do nothing for the main process */
 		return 0; /* do nothing for the main process */
 
 
-	db_con = db_funcs.init(&db_url);
-	if (!db_con)
-	{
-		LM_ERR("unable to connect to database. Please check configuration.\n");
-		return -1;
-	}
+        if(trace_to_database_flag!=NULL && *trace_to_database_flag!=0) {
+        	db_con = db_funcs.init(&db_url);
+        	if (!db_con)
+        	{
+	        	LM_ERR("unable to connect to database. Please check configuration.\n");
+        		return -1;
+                }
+        }
 
 
 	return 0;
 	return 0;
 }
 }
@@ -436,10 +449,14 @@ static int child_init(int rank)
 
 
 static void destroy(void)
 static void destroy(void)
 {
 {
-	if (db_con!=NULL)
-		db_funcs.close(db_con);
-	if (trace_on_flag)
-		shm_free(trace_on_flag);
+        if(trace_to_database_flag!=NULL && *trace_to_database_flag!=0) {
+        	if (db_con!=NULL)
+	        	db_funcs.close(db_con);
+        }
+        
+        if (trace_on_flag)
+	     shm_free(trace_on_flag);
+        
 }
 }
 
 
 static inline int siptrace_copy_proto(int proto, char *buf)
 static inline int siptrace_copy_proto(int proto, char *buf)
@@ -688,7 +705,8 @@ static int sip_trace_store(struct _siptrace_data *sto)
 	if (sip_trace_xheaders_write(sto) != 0)
 	if (sip_trace_xheaders_write(sto) != 0)
 		return -1;
 		return -1;
 	
 	
-	trace_send_duplicate(sto->body.s, sto->body.len);
+	if(hep_mode_on) trace_send_hep_duplicate(&sto->body, &sto->fromip, &sto->toip);
+	else trace_send_duplicate(sto->body.s, sto->body.len);
 
 
 	if (sip_trace_xheaders_free(sto) != 0)
 	if (sip_trace_xheaders_free(sto) != 0)
 		return -1;
 		return -1;
@@ -1424,3 +1442,241 @@ error:
 	pkg_free(p);
 	pkg_free(p);
 	return -1;
 	return -1;
 }
 }
+
+static int trace_send_hep_duplicate(str *body, str *from, str *to)
+{
+        struct dest_info dst;
+        struct proxy_l * p=NULL /* make gcc happy */;
+        void* buffer;
+        union sockaddr_union from_su;
+        union sockaddr_union to_su;
+        unsigned int len, buflen, proto;
+        struct hep_hdr hdr;
+	struct hep_iphdr hep_ipheader;
+#if USE_IPV6
+        struct hep_ip6hdr hep_ip6header;
+#endif
+
+        if(body->s==NULL || body->len <= 0)
+                return -1;
+
+        if(dup_uri_str.s==0 || dup_uri==NULL)
+                return 0;
+
+
+        /* message length */
+        len = body->len 
+#if USE_IPV6
+                + sizeof(struct hep_ip6hdr)
+#else
+                + sizeof(struct hep_iphdr)          
+#endif
+                + sizeof(struct hep_hdr);
+           
+
+        /* The packet is too big for us */
+        if (unlikely(len>BUF_SIZE)){
+                goto error;
+        }
+
+        /* Convert proto:ip:port to sockaddress union SRC IP */
+        if (pipport2su(from->s, &from_su, proto)==-1 || (pipport2su(to->s, &to_su, proto)==-1))
+                goto error;
+
+	/* check if from and to are in the same family*/
+	if(from_su.s.sa_family != to_su.s.sa_family) {
+                LOG(L_ERR, "ERROR: trace_send_hep_duplicate: interworking detected ?\n");
+		goto error;
+	}
+
+        init_dest_info(&dst);
+        /* create a temporary proxy*/
+        dst.proto = PROTO_UDP;
+        p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT,
+                        dst.proto);
+        if (p==0)
+        {
+                LM_ERR("bad host name in uri\n");
+                goto error;
+        }
+
+        hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT);
+
+        dst.send_sock=get_send_socket(0, &dst.to, dst.proto);
+        if (dst.send_sock==0)
+        {
+                LM_ERR("can't forward to af %d, proto %d no corresponding"
+                                " listening socket\n", dst.to.s.sa_family, dst.proto);
+                goto error;
+        }
+
+	/* Version && proto && length */
+	hdr.hp_l = sizeof(struct hep_hdr);
+	hdr.hp_v = 1;
+	hdr.hp_p = proto;
+
+	/* AND the last */
+	if (from_su.s.sa_family==AF_INET){
+        	/* prepare the hep headers */
+
+		hdr.hp_f = AF_INET;
+		hdr.hp_sport = htons(from_su.sin.sin_port);
+		hdr.hp_dport = htons(to_su.sin.sin_port);
+
+		hep_ipheader.hp_src = from_su.sin.sin_addr;
+		hep_ipheader.hp_dst = to_su.sin.sin_addr;
+
+		len = sizeof(struct hep_iphdr);
+	}
+#ifdef USE_IPV6
+        else if (from_su.s.sa_family==AF_INET6){
+        	/* prepare the hep6 headers */
+
+		hdr.hp_f = AF_INET6;
+
+		hdr.hp_sport = htons(from_su.sin6.sin6_port);
+                hdr.hp_dport = htons(to_su.sin6.sin6_port);
+
+		hep_ip6header.hp6_src = from_su.sin6.sin6_addr;
+		hep_ip6header.hp6_dst = to_su.sin6.sin6_addr;
+
+		len = sizeof(struct hep_ip6hdr);
+	}
+#endif /* USE_IPV6 */
+        else {
+                LOG(L_ERR, "ERROR: trace_send_hep_duplicate: Unsupported protocol family\n");
+                goto error;;
+        }
+
+        hdr.hp_l +=len;
+        len += sizeof(struct hep_hdr) + body->len;
+        buffer = (void *)pkg_malloc(len+1);
+        if (buffer==0){
+                LOG(L_ERR, "ERROR: trace_send_hep_duplicate: out of memory\n");
+                goto error;
+        }
+
+	/* Copy job */
+        memset(buffer, '\0', len+1);
+
+        /* copy hep_hdr */
+        memcpy((void*)buffer, &hdr, sizeof(struct hep_hdr));
+        buflen = sizeof(struct hep_hdr);
+
+	/* hep_ip_hdr */
+	if(from_su.s.sa_family==AF_INET) {
+		memcpy((void*)buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr));
+		buflen += sizeof(struct hep_iphdr);
+	}
+#if USE_IPV6
+	else {
+		memcpy((void*)buffer+buflen, &hep_ip6header, sizeof(struct hep_ip6hdr));
+		buflen += sizeof(struct hep_ip6hdr);
+	}
+#endif /* USE_IPV6 */
+
+        /* PAYLOAD */
+        memcpy((void*)(buffer + buflen) , (void*)body->s, body->len);
+        buflen +=body->len;
+
+        if (msg_send(&dst, buffer, buflen)<0)
+        {
+                LM_ERR("cannot send hep duplicate message\n");
+                goto error;
+        }
+
+        free_proxy(p); /* frees only p content, not p itself */
+        pkg_free(p);
+        pkg_free(buffer);
+        return 0;
+error:
+        free_proxy(p); /* frees only p content, not p itself */
+        pkg_free(p);
+        pkg_free(buffer);
+        return -1;
+}
+
+/*!
+ * \brief Convert a STR [proto:]ip[:port] into socket address.
+ * [proto:]ip[:port]
+ * \param pipport (udp:127.0.0.1:5060 or tcp:2001:0DB8:AC10:FE01:5060)
+ * \param tmp_su target structure
+ * \param proto uint protocol type
+ * \return success / unsuccess
+ */
+static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int proto)
+{
+        unsigned int port_no, cutlen = 4;
+        struct ip_addr *ip;
+        char *p, *host_s;
+        str port_str, host_uri;
+        unsigned len = 0;
+
+        /*parse protocol */
+        if(strncmp(pipport, "udp:",4) == 0) proto = IPPROTO_UDP;
+        else if(strncmp(pipport, "tcp:",4) == 0) proto = IPPROTO_TCP;
+        else if(strncmp(pipport, "tls:",4) == 0) proto = IPPROTO_IDP; /* fake proto type */
+        else if(strncmp(pipport, "sctp:",5) == 0) cutlen = 5, proto = IPPROTO_SCTP;
+        else if(strncmp(pipport, "any:",4) == 0) proto = IPPROTO_UDP;
+        else {
+                LM_ERR("bad protocol %s\n", pipport);
+                return -1;
+        }
+
+        /*separate proto and host */
+        p = pipport+cutlen;
+        if( (*(p)) == '\0') {
+                LM_ERR("malformed ip address\n");
+                return -1;
+        }
+        host_s=p;
+
+        if( (p = strrchr(p+1, ':')) == 0 ) {
+                LM_ERR("no port specified\n");
+                return -1;
+        }
+       /*the address contains a port number*/
+        *p = '\0';
+        p++;
+        port_str.s = p;
+        port_str.len = strlen(p);
+        LM_DBG("the port string is %s\n", p);
+        if(str2int(&port_str, &port_no) != 0 ) {
+                LM_ERR("there is not a valid number port\n");
+                return -1;
+        }
+        *p = '\0';
+        if (port_no<1024  || port_no>65536)
+        {
+                LM_ERR("invalid port number; must be in [1024,65536]\n");
+                return -1;
+        }
+	
+	/* now IPv6 address has no brakets. It should be fixed! */
+	if (host_s[0] == '[') {
+              len = strlen(host_s + 1) - 1;
+              if(host_s[len+1] != ']') {
+                LM_ERR("bracket not closed\n");
+                return -1;
+            }
+            memmove(host_s, host_s + 1, len);
+            host_s[len] = '\0';
+        }
+
+        host_uri.s = host_s;
+        host_uri.len = strlen(host_s);
+
+
+	/* check if it's an ip address */
+        if (((ip=str2ip(&host_uri))!=0)
+#ifdef  USE_IPV6
+               || ((ip=str2ip6(&host_uri))!=0)
+#endif
+         ) {
+		ip_addr2su(tmp_su, ip, ntohs(port_no));
+		return 0;	
+
+          }
+
+        return -1;
+}