Explorar o código

siptrace: adds optional addr param to sip_trace()

- address is a SIP uri which specifies the address
  of the capturing server. This parameter trumps
  duplicate_uri and allows tracing to more than one
  server.

  Credit goes to the 1&1 team.
lucian balanceanu %!s(int64=11) %!d(string=hai) anos
pai
achega
32a26c2592
Modificáronse 3 ficheiros con 156 adicións e 44 borrados
  1. 16 8
      modules/siptrace/README
  2. 15 1
      modules/siptrace/doc/siptrace_admin.xml
  3. 125 35
      modules/siptrace/siptrace.c

+ 16 - 8
modules/siptrace/README

@@ -16,9 +16,9 @@ Daniel-Constantin Mierla
 
 
    <[email protected]>
    <[email protected]>
 
 
-   Copyright © 2010 asipto.com
+   Copyright © 2010 asipto.com
 
 
-   Copyright © 2006 voice-system.ro
+   Copyright © 2006 voice-system.ro
      __________________________________________________________________
      __________________________________________________________________
 
 
    Table of Contents
    Table of Contents
@@ -52,7 +52,7 @@ Daniel-Constantin Mierla
 
 
         4. Functions
         4. Functions
 
 
-              4.1. sip_trace()
+              4.1. sip_trace([address])
 
 
         5. MI Commands
         5. MI Commands
 
 
@@ -116,7 +116,7 @@ Chapter 1. Admin Guide
 
 
    4. Functions
    4. Functions
 
 
-        4.1. sip_trace()
+        4.1. sip_trace([address])
 
 
    5. MI Commands
    5. MI Commands
 
 
@@ -406,20 +406,28 @@ modparam("siptrace", "trace_delayed", 1)
 
 
 4. Functions
 4. Functions
 
 
-   4.1. sip_trace()
+   4.1. sip_trace([address])
 
 
-4.1.  sip_trace()
+4.1.  sip_trace([address])
 
 
    Store current processed SIP message in database. It is stored in the
    Store current processed SIP message in database. It is stored in the
    form prior applying chages made to it.
    form prior applying chages made to it.
 
 
+   Meaning of the parameters is as follows:
+     * address - The address in form of SIP uri where to send a duplicate
+       of traced message. This parameter trumps duplicate_uri and allows
+       tracing to more than one server.
+
    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.
+   Default value is "NULL".
 
 
    Example 1.17. sip_trace() usage
    Example 1.17. sip_trace() usage
 ...
 ...
 sip_trace();
 sip_trace();
 ...
 ...
+sip_trace("sip:10.1.1.2:5085");
+...
 
 
 5. MI Commands
 5. MI Commands
 
 
@@ -434,7 +442,7 @@ sip_trace();
           + on
           + on
           + off
           + off
        The parameter is optional - if missing, the command will return the
        The parameter is optional - if missing, the command will return the
-       status of the SIP message tracing (as string "on" or "off" )
+       status of the SIP message tracing (as string “on� or “off� )
        without changing anything.
        without changing anything.
 
 
    MI FIFO Command Format:
    MI FIFO Command Format:
@@ -454,7 +462,7 @@ sip_trace();
      * on or off: turns on/off SIP message tracing.. Possible values are:
      * on or off: turns on/off SIP message tracing.. Possible values are:
           + on
           + on
           + off
           + off
-     * "check" does not change siptrace status, just reports the current
+     * “check� does not change siptrace status, just reports the current
        status.
        status.
 
 
 7. Database setup
 7. Database setup

+ 15 - 1
modules/siptrace/doc/siptrace_admin.xml

@@ -457,22 +457,36 @@ modparam("siptrace", "trace_delayed", 1)
 	<title>Functions</title>
 	<title>Functions</title>
 	<section>
 	<section>
 		<title>
 		<title>
-		<function moreinfo="none">sip_trace()</function>
+		<function moreinfo="none">sip_trace([address])</function>
 		</title>
 		</title>
 		<para>
 		<para>
 		Store current processed SIP message in database. It is stored in the
 		Store current processed SIP message in database. It is stored in the
 		form prior applying chages made to it.
 		form prior applying chages made to it.
 		</para>
 		</para>
+		<para>Meaning of the parameters is as follows:</para>
+		<itemizedlist>
+		<listitem>
+		<para><emphasis>address</emphasis> - The address in form of SIP uri
+		where to send a duplicate of traced message. This parameter trumps
+		duplicate_uri and allows tracing to more than one server.
+		</para>
+		</listitem>
+		</itemizedlist>
 		<para>
 		<para>
 		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.
 		</para>
 		</para>
+		<emphasis>
+			Default value is "NULL".
+		</emphasis>
 		<example>
 		<example>
 		<title><function>sip_trace()</function> usage</title>
 		<title><function>sip_trace()</function> usage</title>
 		<programlisting format="linespecific">
 		<programlisting format="linespecific">
 ...
 ...
 sip_trace();
 sip_trace();
 ...
 ...
+sip_trace("sip:10.1.1.2:5085");
+...
 </programlisting>
 </programlisting>
 		</example>
 		</example>
 	</section>
 	</section>

+ 125 - 35
modules/siptrace/siptrace.c

@@ -91,10 +91,11 @@ static int mod_init(void);
 static int siptrace_init_rpc(void);
 static int siptrace_init_rpc(void);
 static int child_init(int rank);
 static int child_init(int rank);
 static void destroy(void);
 static void destroy(void);
-static int sip_trace(struct sip_msg*, char*, char*);
+static int sip_trace(struct sip_msg*, struct dest_info*, char*);
+static int fixup_siptrace(void ** param, int param_no);
 
 
 static int sip_trace_store_db(struct _siptrace_data* sto);
 static int sip_trace_store_db(struct _siptrace_data* sto);
-static int trace_send_duplicate(char *buf, int len);
+static int trace_send_duplicate(char *buf, int len, struct dest_info*);
 
 
 static void trace_onreq_in(struct cell* t, int type, struct tmcb_params *ps);
 static void trace_onreq_in(struct cell* t, int type, struct tmcb_params *ps);
 static void trace_onreq_out(struct cell* t, int type, struct tmcb_params *ps);
 static void trace_onreq_out(struct cell* t, int type, struct tmcb_params *ps);
@@ -103,7 +104,7 @@ 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 trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_info*);
 static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int *proto);
 static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int *proto);
 
 
 
 
@@ -169,7 +170,7 @@ db_func_t db_funcs;      		/*!< Database functions */
  */
  */
 static cmd_export_t cmds[] = {
 static cmd_export_t cmds[] = {
 	{"sip_trace", (cmd_function)sip_trace, 0, 0, 0, ANY_ROUTE},
 	{"sip_trace", (cmd_function)sip_trace, 0, 0, 0, ANY_ROUTE},
-	{"sip_trace", (cmd_function)sip_trace, 1, 0, 0, ANY_ROUTE},
+    {"sip_trace", (cmd_function)sip_trace, 1, fixup_siptrace, 0, ANY_ROUTE},
 	{0, 0, 0, 0, 0, 0}
 	{0, 0, 0, 0, 0, 0}
 };
 };
 
 
@@ -687,7 +688,7 @@ static int sip_trace_xheaders_free(struct _siptrace_data *sto)
 	return 0;
 	return 0;
 }
 }
 
 
-static int sip_trace_store(struct _siptrace_data *sto)
+static int sip_trace_store(struct _siptrace_data *sto, struct dest_info *dst)
 {
 {
 	if(sto==NULL)
 	if(sto==NULL)
 	{
 	{
@@ -704,8 +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;
 
 
-	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(hep_mode_on) trace_send_hep_duplicate(&sto->body, &sto->fromip, &sto->toip, dst);
+    else trace_send_duplicate(sto->body.s, sto->body.len, dst);
 
 
 	if (sip_trace_xheaders_free(sto) != 0)
 	if (sip_trace_xheaders_free(sto) != 0)
 		return -1;
 		return -1;
@@ -844,11 +845,76 @@ error:
 	return -1;
 	return -1;
 }
 }
 
 
-static int sip_trace(struct sip_msg *msg, char *dir, char *s2)
+static int fixup_siptrace(void** param, int param_no) {
+	char *duri = (char*) *param;
+	struct sip_uri dup_uri;
+	struct dest_info *dst = NULL;
+	struct proxy_l * p = NULL;
+	str dup_uri_str = { 0, 0 };
+
+	if (param_no != 1) {
+		LM_DBG("params:%s\n", (char*)*param);
+		return 0;
+	}
+	if (!(*duri)) {
+		LM_ERR("invalid dup URI\n");
+		return -1;
+	}
+	LM_DBG("sip_trace URI:%s\n", (char*)*param);
+
+	dup_uri_str.s = duri;
+	dup_uri_str.len = strlen(dup_uri_str.s);
+	memset(&dup_uri, 0, sizeof(struct sip_uri));
+
+	if (parse_uri(dup_uri_str.s, dup_uri_str.len, &dup_uri) < 0) {
+		LM_ERR("bad dup uri\n");
+		return -1;
+	}
+
+	dst = (struct dest_info *) pkg_malloc(sizeof(struct dest_info));
+	if (dst == 0) {
+		LM_ERR("no more pkg memory left\n");
+		return -1;
+	}
+	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");
+		pkg_free(dst);
+		return -1;
+	}
+	hostent2su(&dst->to, &p->host, p->addr_idx, (p->port) ? p->port : SIP_PORT);
+
+	pkg_free(*param);
+	/* free temporary proxy*/
+	if (p) {
+		free_proxy(p); /* frees only p content, not p itself */
+		pkg_free(p);
+	}
+
+	*param = (void*) dst;
+	return 0;
+}
+
+static int sip_trace(struct sip_msg *msg, struct dest_info * dst, char *dir)
 {
 {
 	struct _siptrace_data sto;
 	struct _siptrace_data sto;
 	struct onsend_info *snd_inf = NULL;
 	struct onsend_info *snd_inf = NULL;
 
 
+	if (dst){
+	    if (dst->send_sock == 0){
+	        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);
+	            return -1;
+	        }
+	    }
+	}
+
 	if(msg==NULL) {
 	if(msg==NULL) {
 		LM_DBG("nothing to trace\n");
 		LM_DBG("nothing to trace\n");
 		return -1;
 		return -1;
@@ -934,7 +1000,7 @@ static int sip_trace(struct sip_msg *msg, char *dir, char *s2)
 		sto.stat = siptrace_req;
 		sto.stat = siptrace_req;
 	}
 	}
 #endif
 #endif
-	return sip_trace_store(&sto);
+	return sip_trace_store(&sto, dst);
 }
 }
 
 
 #define trace_is_off(_msg) \
 #define trace_is_off(_msg) \
@@ -1116,7 +1182,7 @@ static void trace_onreq_out(struct cell* t, int type, struct tmcb_params *ps)
 	sto.stat = siptrace_req;
 	sto.stat = siptrace_req;
 #endif
 #endif
 
 
-	sip_trace_store(&sto);
+	sip_trace_store(&sto, NULL);
 	return;
 	return;
 }
 }
 
 
@@ -1187,7 +1253,7 @@ static void trace_onreply_in(struct cell* t, int type, struct tmcb_params *ps)
 	sto.stat = siptrace_rpl;
 	sto.stat = siptrace_rpl;
 #endif
 #endif
 
 
-	sip_trace_store(&sto);
+	sip_trace_store(&sto, NULL);
 	return;
 	return;
 }
 }
 
 
@@ -1296,7 +1362,7 @@ static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps)
 	sto.stat = siptrace_rpl;
 	sto.stat = siptrace_rpl;
 #endif
 #endif
 
 
-	sip_trace_store(&sto);
+	sip_trace_store(&sto, NULL);
 	return;
 	return;
 }
 }
 
 
@@ -1382,7 +1448,7 @@ static void trace_sl_onreply_out(sl_cbp_t *slcbp)
 	sto.stat = siptrace_rpl;
 	sto.stat = siptrace_rpl;
 #endif
 #endif
 
 
-	sip_trace_store(&sto);
+	sip_trace_store(&sto, NULL);
 	return;
 	return;
 }
 }
 
 
@@ -1434,10 +1500,10 @@ static struct mi_root* sip_trace_mi(struct mi_root* cmd_tree, void* param )
 	}
 	}
 }
 }
 
 
-static int trace_send_duplicate(char *buf, int len)
+static int trace_send_duplicate(char *buf, int len, struct dest_info *dst2)
 {
 {
 	struct dest_info dst;
 	struct dest_info dst;
-	struct proxy_l * p;
+	struct proxy_l * p = NULL;
 
 
 	if(buf==NULL || len <= 0)
 	if(buf==NULL || len <= 0)
 		return -1;
 		return -1;
@@ -1456,34 +1522,49 @@ static int trace_send_duplicate(char *buf, int len)
 		return -1;
 		return -1;
 	}
 	}
 
 
-	hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT);
+	if (!dst2){
+	    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");
+	        return -1;
+	    }
+	    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;
+	    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;
+	    }
 	}
 	}
 
 
-	if (msg_send(&dst, buf, len)<0)
+	if (msg_send((dst2)?dst2:&dst, buf, len)<0)
 	{
 	{
 		LM_ERR("cannot send duplicate message\n");
 		LM_ERR("cannot send duplicate message\n");
 		goto error;
 		goto error;
 	}
 	}
 
 
-	free_proxy(p); /* frees only p content, not p itself */
-	pkg_free(p);
+	if (p){
+	    free_proxy(p); /* frees only p content, not p itself */
+	    pkg_free(p);
+	}
 	return 0;
 	return 0;
 error:
 error:
+    if (p){
 	free_proxy(p); /* frees only p content, not p itself */
 	free_proxy(p); /* frees only p content, not p itself */
 	pkg_free(p);
 	pkg_free(p);
+    }
 	return -1;
 	return -1;
 }
 }
 
 
-static int trace_send_hep_duplicate(str *body, str *from, str *to)
+static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_info * dst2)
 {
 {
 	struct dest_info dst;
 	struct dest_info dst;
+	struct dest_info* dst_fin = NULL;
 	struct proxy_l * p=NULL /* make gcc happy */;
 	struct proxy_l * p=NULL /* make gcc happy */;
 	void* buffer = NULL;
 	void* buffer = NULL;
 	union sockaddr_union from_su;
 	union sockaddr_union from_su;
@@ -1528,6 +1609,7 @@ static int trace_send_hep_duplicate(str *body, str *from, str *to)
 		goto error;
 		goto error;
 	}
 	}
 
 
+    if (!dst2){
 	init_dest_info(&dst);
 	init_dest_info(&dst);
 	/* create a temporary proxy*/
 	/* create a temporary proxy*/
 	dst.proto = PROTO_UDP;
 	dst.proto = PROTO_UDP;
@@ -1540,14 +1622,20 @@ static int trace_send_hep_duplicate(str *body, str *from, str *to)
 	}
 	}
 
 
 	hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT);
 	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;
-	}
+	LM_DBG("setting up the socket_info\n");
+	dst_fin = &dst;
+    } else {
+        dst_fin = dst2;
+    }
+
+    if (dst_fin->send_sock == 0) {
+        dst_fin->send_sock=get_send_socket(0, &dst_fin->to, dst_fin->proto);
+        if (dst_fin->send_sock == 0) {
+            LM_ERR("can't forward to af %d, proto %d no corresponding"
+                    " listening socket\n", dst_fin->to.s.sa_family, dst_fin->proto);
+            goto error;
+        }
+    }
 
 
 	/* Version && proto && length */
 	/* Version && proto && length */
 	hdr.hp_l = sizeof(struct hep_hdr);
 	hdr.hp_l = sizeof(struct hep_hdr);
@@ -1627,14 +1715,16 @@ static int trace_send_hep_duplicate(str *body, str *from, str *to)
 	memcpy((void*)(buffer + buflen) , (void*)body->s, body->len);
 	memcpy((void*)(buffer + buflen) , (void*)body->s, body->len);
 	buflen +=body->len;
 	buflen +=body->len;
 
 
-	if (msg_send(&dst, buffer, buflen)<0)
+	if (msg_send(dst_fin, buffer, buflen)<0)
 	{
 	{
 		LM_ERR("cannot send hep duplicate message\n");
 		LM_ERR("cannot send hep duplicate message\n");
 		goto error;
 		goto error;
 	}
 	}
 
 
+    if (p) {
 	free_proxy(p); /* frees only p content, not p itself */
 	free_proxy(p); /* frees only p content, not p itself */
 	pkg_free(p);
 	pkg_free(p);
+    }
 	pkg_free(buffer);
 	pkg_free(buffer);
 	return 0;
 	return 0;
 error:
 error: