瀏覽代碼

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

Alexandr Dubovikov 14 年之前
父節點
當前提交
72778ab8a5
共有 4 個文件被更改,包括 416 次插入48 次删除
  1. 102 16
      modules_k/siptrace/README
  2. 5 0
      modules_k/siptrace/doc/siptrace.xml
  3. 22 1
      modules_k/siptrace/doc/siptrace_admin.xml
  4. 287 31
      modules_k/siptrace/siptrace.c

+ 102 - 16
modules_k/siptrace/README

@@ -6,6 +6,12 @@ Daniel-Constantin Mierla
 
 Edited by
 
+Alexandr Dubovikov
+
+   <[email protected]>
+
+Edited by
+
 Daniel-Constantin Mierla
 
    <[email protected]>
@@ -34,8 +40,12 @@ Daniel-Constantin Mierla
               3.5. traced_user_avp (str)
               3.6. trace_table_avp (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
 
@@ -57,9 +67,13 @@ Daniel-Constantin Mierla
    1.5. Set traced_user_avp parameter
    1.6. Set trace_table_avp 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
 
@@ -80,8 +94,12 @@ Chapter 1. Admin Guide
         3.5. traced_user_avp (str)
         3.6. trace_table_avp (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
 
@@ -96,8 +114,9 @@ Chapter 1. Admin Guide
 
 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.
      * by calling explicitely the sip_trace() method in Kamailio
@@ -141,8 +160,12 @@ Chapter 1. Admin Guide
    3.5. traced_user_avp (str)
    3.6. trace_table_avp (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)
 
@@ -231,7 +254,21 @@ modparam("siptrace", "trace_table_avp", "$avp(s:siptrace_table)")
 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
    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".
 
-   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")
 ...
 
-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).
 
@@ -256,11 +293,60 @@ modparam("siptrace", "trace_local_ip", "10.1.1.1:5064")
 
    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)
 ...
 
+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.1. sip_trace()
@@ -273,7 +359,7 @@ modparam("siptrace", "trace_sl_acks", 0)
    This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
    ONREPLY_ROUTE, BRANCH_ROUTE.
 
-   Example 1.10. sip_trace() usage
+   Example 1.14. sip_trace() usage
 ...
 sip_trace();
 ...

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

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

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

@@ -16,7 +16,9 @@
 	<section>
 	<title>Overview</title>
 	<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>
 	There are two ways of storing information.
@@ -365,6 +367,25 @@ modparam("siptrace", "xheaders_read", 0)
 </programlisting>
 		</example>
 	</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>

+ 287 - 31
modules_k/siptrace/siptrace.c

@@ -50,6 +50,8 @@
 #include "../../str.h"
 #include "../../onsend.h"
 
+#include "../../modules/sipcapture/sipcapture.h"
+
 #ifdef STATISTICS
 #include "../../lib/kcore/statistics.h"
 #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_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 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};
 
+int hep_mode_on = 0;
+
 db1_con_t *db_con = NULL; 		/*!< database connection */
 db_func_t db_funcs;      		/*!< Database functions */
 
@@ -184,6 +192,7 @@ static param_export_t params[] = {
 	{"trace_sl_acks",      INT_PARAM, &trace_sl_acks        },
 	{"xheaders_write",     INT_PARAM, &xheaders_write       },
 	{"xheaders_read",      INT_PARAM, &xheaders_read        },
+	{"hep_mode_on",        INT_PARAM, &hep_mode_on          },	 
 	{0, 0, 0}
 };
 
@@ -276,19 +285,29 @@ static int mod_init(void)
 		return -1;
 	}
 	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;
 	}
+	
+	*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));
 	if(trace_on_flag==NULL) {
@@ -297,15 +316,7 @@ static int mod_init(void)
 	}
 	
 	*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_read_flag = (int*)shm_malloc(sizeof(int));
 	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)
 		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;
 }
@@ -436,10 +449,14 @@ static int child_init(int rank)
 
 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)
@@ -688,7 +705,8 @@ static int sip_trace_store(struct _siptrace_data *sto)
 	if (sip_trace_xheaders_write(sto) != 0)
 		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)
 		return -1;
@@ -1424,3 +1442,241 @@ error:
 	pkg_free(p);
 	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;
+}