Browse code

Merge branch '5.0' of https://github.com/kamailio/kamailio into 5.0

# By Giacomo Vacca
# Via Giacomo Vacca
* '5.0' of https://github.com/kamailio/kamailio:
siptrace: update doc with editor
siptrace: update doc with support for HEPv3
siptrace: add support for HEPv3
sipcapture: add macros to pack HEPv3 chunks

The Root authored on 23/02/2017 17:31:08
Showing 4 changed files
... ...
@@ -177,5 +177,52 @@ struct hep_generic_recv {
177 177
 
178 178
 typedef struct hep_generic_recv hep_generic_recv_t;
179 179
 
180
+#define HEP3_PACK_INIT(buf) \
181
+		union { \
182
+			hep_chunk_uint8_t chunk8; \
183
+			hep_chunk_uint16_t chunk16; \
184
+			hep_chunk_uint32_t chunk32; \
185
+			hep_chunk_t chunkpl; \
186
+			uint16_t len; \
187
+		} _tmpu; \
188
+		char *_tmp_p = (buf); \
189
+		memcpy(_tmp_p, "HEP3", 4); \
190
+		_tmp_p += 4 + 2/* skip length */;
191
+
192
+#define HEP3_PACK_FINALIZE(buf, lenp) \
193
+		do { \
194
+			_tmpu.len = htons(_tmp_p - (char *)(buf)); \
195
+			memcpy((void *)(&(((hep_ctrl_t *)(buf))->length)), (void*)&_tmpu.len, 2); \
196
+			*lenp = _tmp_p - (char *)(buf); \
197
+		} while (0)
198
+
199
+#define _HEP3_PACK_CHUNK_GENERIC(type, tmpvar, vid, tid, val) \
200
+		do { \
201
+			(tmpvar).chunk.vendor_id = htons(vid); \
202
+			(tmpvar).chunk.type_id = htons(tid); \
203
+			(tmpvar).chunk.length = htons(sizeof(type)); \
204
+			(tmpvar).data = (val); \
205
+			memcpy(_tmp_p, (void *) &(tmpvar), sizeof(type)); \
206
+			_tmp_p += sizeof(type); \
207
+		} while (0)
208
+
209
+#define HEP3_PACK_CHUNK_UINT8(vid, tid, val) _HEP3_PACK_CHUNK_GENERIC(hep_chunk_uint8_t, _tmpu.chunk8, vid, tid, val)
210
+#define HEP3_PACK_CHUNK_UINT16(vid, tid, val) _HEP3_PACK_CHUNK_GENERIC(hep_chunk_uint16_t, _tmpu.chunk16, vid, tid, htons(val))
211
+#define HEP3_PACK_CHUNK_UINT16_NBO(vid, tid, val) _HEP3_PACK_CHUNK_GENERIC(hep_chunk_uint16_t, _tmpu.chunk16, vid, tid, (val))
212
+#define HEP3_PACK_CHUNK_UINT32(vid, tid, val) _HEP3_PACK_CHUNK_GENERIC(hep_chunk_uint32_t, _tmpu.chunk32, vid, tid, htonl(val))
213
+#define HEP3_PACK_CHUNK_UINT32_NBO(vid, tid, val) _HEP3_PACK_CHUNK_GENERIC(hep_chunk_uint32_t, _tmpu.chunk32, vid, tid, (val))
214
+
215
+#define HEP3_PACK_CHUNK_DATA(vid, tid, val, len) \
216
+		do { \
217
+			_tmpu.chunkpl.vendor_id = htons(vid); \
218
+			_tmpu.chunkpl.type_id = htons(tid); \
219
+			_tmpu.chunkpl.length = htons(sizeof(hep_chunk_t) + (len)); \
220
+			memcpy(_tmp_p, (void *) &_tmpu.chunkpl, sizeof(hep_chunk_t)); \
221
+			_tmp_p += sizeof(hep_chunk_t); \
222
+			memcpy(_tmp_p, (void *) (val), len); \
223
+			_tmp_p += len; \
224
+		} while (0)
225
+
226
+#define HEP3_PACK_CHUNK_IP6(vid, tid, paddr) HEP3_PACK_CHUNK_DATA(vid, tid, paddr, sizeof(struct in6_addr))
180 227
 
181 228
 #endif
... ...
@@ -28,6 +28,11 @@
28 28
 		<surname>Mierla</surname>
29 29
 		    <email>miconda@gmail.com</email>
30 30
 	    </editor>
31
+	<editor>
32
+		<firstname>Giacomo</firstname>
33
+		<surname>Vacca</surname>
34
+		<email>giacomo.vacca@gmail.com</email>
35
+	</editor>
31 36
 	</authorgroup>
32 37
 	<copyright>
33 38
 	    <year>2010</year>
... ...
@@ -17,8 +17,8 @@
17 17
 	<title>Overview</title>
18 18
 	<para>
19 19
 		The SIPtrace module offer a possibility to store incoming and outgoing SIP
20
-		messages in a database and/or duplicate to the capturing server (using <acronym>HEP</acronym>
21
-		the Homer encapsulation protocol or plain SIP mode)
20
+		messages in a database and/or duplicate to the capturing server (using <acronym>HEP</acronym>,
21
+		the Homer encapsulation protocol, or plain SIP mode)
22 22
 	</para>
23 23
 	<para>
24 24
 		There are two ways of storing information:
... ...
@@ -42,8 +42,7 @@
42 42
 	</para>
43 43
 
44 44
 	<para>
45
-	The tracing can be turned on/off using Kamailio <acronym>mi</acronym> or <acronym>RPC</acronym>
46
-	commands.
45
+	The tracing can be turned on/off using Kamailio <acronym>RPC</acronym> commands.
47 46
 	</para>
48 47
 	<para>
49 48
 	&ctltool; fifo sip_trace on
... ...
@@ -57,12 +56,12 @@
57 57
 	<section>
58 58
 		<title>&kamailio; Modules</title>
59 59
 		<para>
60
-		The following modules must be loaded before this module:
60
+		The following modules must be conditionally loaded before this module:
61 61
 			<itemizedlist>
62 62
 			<listitem>
63 63
 			<para>
64 64
 				<emphasis>A database module</emphasis> - Mysql, Postgres,
65
-				dbtext, unixODBC...
65
+				dbtext, unixODBC... Optional, if tracing to DB is enabled.
66 66
 			</para>
67 67
 			</listitem>
68 68
 			<listitem>
... ...
@@ -199,7 +198,7 @@ modparam("siptrace", "traced_user_avp", "$avp(s:user)")
199 199
 		store the SIP messages. If it is not set, the value of
200 200
 		<quote>table</quote> parameter is used. In this way one can select
201 201
 		dynamically where to store the traced messages. The table
202
-		must exists, and must have the same structure as the <quote>sip_trace</quote>
202
+		must exist, and must have the same structure as the <quote>sip_trace</quote>
203 203
 		table.
204 204
 		</para>
205 205
 		<para>
... ...
@@ -395,8 +394,9 @@ modparam("siptrace", "hep_mode_on", 1)
395 395
                 <title><varname>hep_version</varname> (integer)</title>
396 396
                 <para>
397 397
                 The parameter indicate the version of the HEP protocol.
398
-                Can be <quote>1</quote> or <quote>2</quote>. In HEPv2 the timestamp and capture agent ID
399
-                will be included to HEP header.
398
+                Can be <quote>1</quote>, <quote>2</quote> or <quote>3</quote>.
399
+                In HEPv2 and HEPv3 the timestamp and capture agent ID will be
400
+                included in the HEP header.
400 401
                 </para>
401 402
                 <para>
402 403
                 <emphasis>
... ...
@@ -407,7 +407,7 @@ modparam("siptrace", "hep_mode_on", 1)
407 407
                 <title>Set <varname>hep_version</varname> parameter</title>
408 408
                 <programlisting format="linespecific">
409 409
 ...
410
-modparam("siptrace", "hep_version", 2)
410
+modparam("siptrace", "hep_version", 3)
411 411
 ...
412 412
 </programlisting>
413 413
                 </example>
... ...
@@ -416,8 +416,8 @@ modparam("siptrace", "hep_version", 2)
416 416
                 <title><varname>hep_capture_id</varname> (integer)</title>
417 417
                 <para>
418 418
                 The parameter indicate the capture agent ID for the <acronym>HEPv2</acronym>
419
-                protocol.
420
-                Limitation: 16-bit integer.
419
+                or <acronym>HEPv3</acronym> protocol.
420
+                Limitation: 16-bit integer for HEPv2, 32-bit for HEPv3.
421 421
                 </para>
422 422
                 <para>
423 423
                 <emphasis>
... ...
@@ -425,8 +425,7 @@ modparam("siptrace", "hep_version", 2)
425 425
                 </emphasis>
426 426
                 </para>
427 427
                 <example>
428
-                <title>Set <varname>hep_capture_id</varname>
429
-                parameter</title>
428
+                <title>Set <varname>hep_capture_id</varname> parameter</title>
430 429
                 <programlisting format="linespecific">
431 430
 ...
432 431
 modparam("siptrace", "hep_capture_id", 234)
... ...
@@ -456,7 +455,7 @@ modparam("siptrace", "trace_delayed", 1)
456 456
 	<section id="siptrace.p.force_send_sock">
457 457
                 <title><varname>force_send_sock</varname> (str)</title>
458 458
                 <para>
459
-			The local interface in the form of SIP uri from where to send
459
+			The local interface in the form of SIP URI from where to send
460 460
 			the duplicated traffic. In the absence of this parameter
461 461
 			&kamailio; automatically picks an interface.
462 462
                 </para>
... ...
@@ -493,13 +492,32 @@ modparam("siptrace", "trace_mode", 1)
493 493
 </programlisting>
494 494
                 </example>
495 495
         </section>
496
+	<section id="siptrace.p.auth_key">
497
+                <title><varname>auth_key</varname> (integer)</title>
498
+                <para>
499
+A string with an authorization key.
500
+Supported on HEPv3 only.
501
+                </para>
502
+                <para>
503
+                Default value is empty.
504
+                </para>
505
+                <example>
506
+                <title>Set <varname>auth_key</varname>
507
+                parameter</title>
508
+                <programlisting format="linespecific">
509
+...
510
+modparam("siptrace", "auth_key", "spoihepuirthpeuia")
511
+...
512
+</programlisting>
513
+                </example>
514
+        </section>
496 515
 	</section>
497 516
 	
498 517
 	<section>
499 518
 	<title>Functions</title>
500 519
 	<section id="siptrace.f.sip_trace">
501 520
 		<title>
502
-		<function moreinfo="none">sip_trace([address])</function>
521
+		<function moreinfo="none">sip_trace([address][, correlation_id])</function>
503 522
 		</title>
504 523
 		<para>
505 524
 		Store or forward the current processed SIP message in database. It is stored in the
... ...
@@ -508,10 +526,14 @@ modparam("siptrace", "trace_mode", 1)
508 508
 		<para>Meaning of the parameters is as follows:</para>
509 509
 		<itemizedlist>
510 510
 		<listitem>
511
-		<para><emphasis>address</emphasis> - The address in form of SIP uri
511
+		<para><emphasis>address</emphasis> - The address in form of SIP URI
512 512
 		where to send a duplicate of traced message. This parameter trumps
513 513
 		duplicate_uri and allows tracing to more than one server.
514 514
 		</para>
515
+		<para><emphasis>correlation_id</emphasis> - A string with a correlation ID
516
+		to be added to the HEP header when using HEPv3.
517
+		It's possible to use PVs.
518
+		</para>
515 519
 		</listitem>
516 520
 		</itemizedlist>
517 521
 		<para>
... ...
@@ -529,6 +551,8 @@ sip_trace();
529 529
 ...
530 530
 sip_trace("sip:10.1.1.2:5085");
531 531
 ...
532
+sip_trace("sip:10.1.1.2:5085", "$ci-abc");
533
+...
532 534
 </programlisting>
533 535
 		</example>
534 536
 	</section>
... ...
@@ -549,7 +573,7 @@ sip_trace("sip:10.1.1.2:5085");
549 549
 		</para>
550 550
 		<para>Parameters: </para>
551 551
 		<itemizedlist>
552
-			<listitem><para>on or off: turns on/off SIP message tracing..
552
+			<listitem><para>on or off: turns on/off SIP message tracing.
553 553
 			Possible values are:</para>
554 554
 			<itemizedlist>
555 555
 				<listitem><para>on</para></listitem>
... ...
@@ -33,6 +33,7 @@
33 33
 #include <string.h>
34 34
 #include <time.h>
35 35
 #include "../../core/sr_module.h"
36
+#include "../../core/mod_fix.h"
36 37
 #include "../../core/dprint.h"
37 38
 #include "../../core/ut.h"
38 39
 #include "../../core/ip_addr.h"
... ...
@@ -90,7 +91,8 @@ static int mod_init(void);
90 90
 static int siptrace_init_rpc(void);
91 91
 static int child_init(int rank);
92 92
 static void destroy(void);
93
-static int sip_trace(struct sip_msg*, struct dest_info*, char*);
93
+static int sip_trace(struct sip_msg*, struct dest_info*, str *correlation_id_str, char*);
94
+static int sip_trace2(struct sip_msg *, char *dest, char *correlation_id);
94 95
 static int fixup_siptrace(void ** param, int param_no);
95 96
 
96 97
 static int sip_trace_store_db(struct _siptrace_data* sto);
... ...
@@ -103,7 +105,9 @@ static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps);
103 103
 static void trace_sl_onreply_out(sl_cbp_t *slcb);
104 104
 static void trace_sl_ack_in(sl_cbp_t *slcb);
105 105
 
106
-static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_info*);
106
+static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_info*, str *correlation_id);
107
+static int trace_send_hep2_duplicate(str *body, str *from, str *to, struct dest_info*);
108
+static int trace_send_hep3_duplicate(str *body, str *from, str *to, struct dest_info*, str *correlation_id);
107 109
 static int pipport2su (char *pipport, union sockaddr_union *tmp_su, unsigned int *proto);
108 110
 
109 111
 int siptrace_net_data_recv(void *data);
... ...
@@ -140,6 +144,8 @@ int trace_delayed = 0;
140 140
 
141 141
 int hep_version = 1;
142 142
 int hep_capture_id = 1;
143
+int hep_vendor_id = 0;
144
+str auth_key_str = {0, 0};
143 145
 
144 146
 int xheaders_write = 0;
145 147
 int xheaders_read = 0;
... ...
@@ -177,6 +183,7 @@ db_func_t db_funcs;      		/*!< Database functions */
177 177
 static cmd_export_t cmds[] = {
178 178
 	{"sip_trace", (cmd_function)sip_trace, 0, 0, 0, ANY_ROUTE},
179 179
 	{"sip_trace", (cmd_function)sip_trace, 1, fixup_siptrace, 0, ANY_ROUTE},
180
+	{"sip_trace", (cmd_function)sip_trace2, 2, fixup_spve_spve, 0, ANY_ROUTE},
180 181
 	{0, 0, 0, 0, 0, 0}
181 182
 };
182 183
 
... ...
@@ -185,6 +192,7 @@ static cmd_export_t cmds[] = {
185 185
  * Exported parameters
186 186
  */
187 187
 static param_export_t params[] = {
188
+	{"auth_key",           PARAM_STR, &auth_key_str       },
188 189
 	{"db_url",             PARAM_STR, &db_url            },
189 190
 	{"table",              PARAM_STR, &siptrace_table     },
190 191
 	{"date_column",        PARAM_STR, &date_column        },
... ...
@@ -285,7 +293,7 @@ static int mod_init(void)
285 285
 
286 286
 	*trace_to_database_flag = trace_to_database;
287 287
 
288
-	if(hep_version != 1 && hep_version != 2) {
288
+	if(hep_version != 1 && hep_version != 2 && hep_version != 3) {
289 289
 		LM_ERR("unsupported version of HEP");
290 290
 		return -1;
291 291
 	}
... ...
@@ -305,8 +313,7 @@ static int mod_init(void)
305 305
 		}
306 306
 	}
307 307
 
308
-	if(hep_version != 1 && hep_version != 2) {
309
-
308
+	if(hep_version != 1 && hep_version != 2 && hep_version != 3) {
310 309
 		LM_ERR("unsupported version of HEP");
311 310
 		return -1;
312 311
 	}
... ...
@@ -726,7 +733,7 @@ static int sip_trace_xheaders_free(struct _siptrace_data *sto)
726 726
 	return 0;
727 727
 }
728 728
 
729
-static int sip_trace_store(struct _siptrace_data *sto, struct dest_info *dst)
729
+static int sip_trace_store(struct _siptrace_data *sto, struct dest_info *dst, str *correlation_id_str)
730 730
 {
731 731
 	if(sto==NULL)
732 732
 	{
... ...
@@ -743,7 +750,7 @@ static int sip_trace_store(struct _siptrace_data *sto, struct dest_info *dst)
743 743
 	if (sip_trace_xheaders_write(sto) != 0)
744 744
 		return -1;
745 745
 
746
-	if(hep_mode_on) trace_send_hep_duplicate(&sto->body, &sto->fromip, &sto->toip, dst);
746
+	if(hep_mode_on) trace_send_hep_duplicate(&sto->body, &sto->fromip, &sto->toip, dst, correlation_id_str);
747 747
 	else trace_send_duplicate(sto->body.s, sto->body.len, dst);
748 748
 
749 749
 	if (sip_trace_xheaders_free(sto) != 0)
... ...
@@ -894,8 +901,8 @@ error:
894 894
 }
895 895
 
896 896
 static int fixup_siptrace(void** param, int param_no) {
897
-	char *duri = (char*) *param;
898
-	struct sip_uri dup_uri;
897
+	char *duri;
898
+	struct sip_uri uri;
899 899
 	struct dest_info *dst = NULL;
900 900
 	struct proxy_l * p = NULL;
901 901
 	str dup_uri_str = { 0, 0 };
... ...
@@ -904,19 +911,35 @@ static int fixup_siptrace(void** param, int param_no) {
904 904
 		LM_DBG("params:%s\n", (char*)*param);
905 905
 		return 0;
906 906
 	}
907
-	if (!(*duri)) {
908
-		LM_ERR("invalid dup URI\n");
909
-		return -1;
907
+
908
+	if (((char*)(*param))[0] == '\0') {
909
+		// Empty URI, use the URI set at module level (dup_uri)
910
+		if (dup_uri) {
911
+			uri = *dup_uri;
912
+		}
913
+		else {
914
+			LM_ERR("Missing duplicate URI\n");
915
+			return -1;
916
+		}
910 917
 	}
911
-	LM_DBG("sip_trace URI:%s\n", (char*)*param);
918
+	else {
919
+		duri = (char*) *param;
912 920
 
913
-	dup_uri_str.s = duri;
914
-	dup_uri_str.len = strlen(dup_uri_str.s);
915
-	memset(&dup_uri, 0, sizeof(struct sip_uri));
921
+		if (!(*duri)) {
922
+			LM_ERR("invalid dup URI\n");
923
+			return -1;
924
+		}
916 925
 
917
-	if (parse_uri(dup_uri_str.s, dup_uri_str.len, &dup_uri) < 0) {
918
-		LM_ERR("bad dup uri\n");
919
-		return -1;
926
+		LM_DBG("sip_trace URI:%s\n", duri);
927
+
928
+		dup_uri_str.s = duri;
929
+		dup_uri_str.len = strlen(dup_uri_str.s);
930
+		memset(&uri, 0, sizeof(struct sip_uri));
931
+
932
+		if (parse_uri(dup_uri_str.s, dup_uri_str.len, &uri) < 0) {
933
+			LM_ERR("bad dup uri\n");
934
+			return -1;
935
+		}
920 936
 	}
921 937
 
922 938
 	dst = (struct dest_info *) pkg_malloc(sizeof(struct dest_info));
... ...
@@ -927,7 +950,7 @@ static int fixup_siptrace(void** param, int param_no) {
927 927
 	init_dest_info(dst);
928 928
 	/* create a temporary proxy*/
929 929
 	dst->proto = PROTO_UDP;
930
-	p = mk_proxy(&dup_uri.host, (dup_uri.port_no) ? dup_uri.port_no : SIP_PORT,
930
+	p = mk_proxy(&uri.host, (uri.port_no) ? uri.port_no : SIP_PORT,
931 931
 			dst->proto);
932 932
 	if (p == 0) {
933 933
 		LM_ERR("bad host name in uri\n");
... ...
@@ -947,7 +970,71 @@ static int fixup_siptrace(void** param, int param_no) {
947 947
 	return 0;
948 948
 }
949 949
 
950
-static int sip_trace(struct sip_msg *msg, struct dest_info * dst, char *dir)
950
+static int sip_trace2(struct sip_msg *msg, char *dest, char *correlation_id)
951
+{
952
+	struct dest_info *dst = NULL;
953
+	struct sip_uri uri;
954
+	struct proxy_l * p = NULL;
955
+	str dup_uri_str = { 0, 0 };
956
+	str correlation_id_str = {0, 0};;
957
+
958
+	if(fixup_get_svalue(msg, (gparam_t*)dest, &dup_uri_str)!=0) {
959
+		LM_ERR("unable to parse the dest URI string\n");
960
+		return -1;
961
+	}
962
+
963
+	// If the dest is empty, use the module parameter, if set
964
+	if (dup_uri_str.len == 0) {
965
+		if (dup_uri) {
966
+			uri = *dup_uri;
967
+		}
968
+		else {
969
+			LM_ERR("Missing duplicate URI\n");
970
+			return -1;
971
+		}
972
+	}
973
+	else {
974
+		memset(&uri, 0, sizeof(struct sip_uri));
975
+		if (parse_uri(dup_uri_str.s, dup_uri_str.len, &uri) < 0) {
976
+			LM_ERR("bad dup uri\n");
977
+			return -1;
978
+		}
979
+	}
980
+
981
+	dst = (struct dest_info *)pkg_malloc(sizeof(struct dest_info));
982
+	if (dst == 0) {
983
+		LM_ERR("no more pkg memory left\n");
984
+		return -1;
985
+	}
986
+	init_dest_info(dst);
987
+
988
+	/* create a temporary proxy*/
989
+	dst->proto = PROTO_UDP;
990
+	p = mk_proxy(&uri.host, (uri.port_no) ? uri.port_no : SIP_PORT,
991
+			dst->proto);
992
+	if (p == 0) {
993
+		LM_ERR("bad host name in uri\n");
994
+		pkg_free(dst);
995
+		return -1;
996
+	}
997
+
998
+	hostent2su(&dst->to, &p->host, p->addr_idx, (p->port) ? p->port : SIP_PORT);
999
+
1000
+	/* free temporary proxy*/
1001
+	if (p) {
1002
+		free_proxy(p); /* frees only p content, not p itself */
1003
+		pkg_free(p);
1004
+	}
1005
+
1006
+	if(fixup_get_svalue(msg, (gparam_t*)correlation_id, &correlation_id_str)!=0) {
1007
+		LM_ERR("unable to parse the correlation id\n");
1008
+		return -1;
1009
+	}
1010
+
1011
+	return sip_trace(msg, dst, &correlation_id_str, NULL);
1012
+}
1013
+
1014
+static int sip_trace(struct sip_msg *msg, struct dest_info * dst, str *correlation_id_str, char *dir)
951 1015
 {
952 1016
 	struct _siptrace_data sto;
953 1017
 	struct onsend_info *snd_inf = NULL;
... ...
@@ -1061,7 +1148,7 @@ static int sip_trace(struct sip_msg *msg, struct dest_info * dst, char *dir)
1061 1061
 		sto.stat = siptrace_req;
1062 1062
 	}
1063 1063
 #endif
1064
-	return sip_trace_store(&sto, dst);
1064
+	return sip_trace_store(&sto, dst, correlation_id_str);
1065 1065
 }
1066 1066
 
1067 1067
 #define trace_is_off(_msg) \
... ...
@@ -1244,7 +1331,7 @@ static void trace_onreq_out(struct cell* t, int type, struct tmcb_params *ps)
1244 1244
 	sto.stat = siptrace_req;
1245 1245
 #endif
1246 1246
 
1247
-	sip_trace_store(&sto, NULL);
1247
+	sip_trace_store(&sto, NULL, NULL);
1248 1248
 	return;
1249 1249
 }
1250 1250
 
... ...
@@ -1316,7 +1403,7 @@ static void trace_onreply_in(struct cell* t, int type, struct tmcb_params *ps)
1316 1316
 	sto.stat = siptrace_rpl;
1317 1317
 #endif
1318 1318
 
1319
-	sip_trace_store(&sto, NULL);
1319
+	sip_trace_store(&sto, NULL, NULL);
1320 1320
 	return;
1321 1321
 }
1322 1322
 
... ...
@@ -1426,7 +1513,7 @@ static void trace_onreply_out(struct cell* t, int type, struct tmcb_params *ps)
1426 1426
 	sto.stat = siptrace_rpl;
1427 1427
 #endif
1428 1428
 
1429
-	sip_trace_store(&sto, NULL);
1429
+	sip_trace_store(&sto, NULL, NULL);
1430 1430
 	return;
1431 1431
 }
1432 1432
 
... ...
@@ -1435,7 +1522,7 @@ static void trace_sl_ack_in(sl_cbp_t *slcbp)
1435 1435
 	sip_msg_t *req;
1436 1436
 	LM_DBG("storing ack...\n");
1437 1437
 	req = slcbp->req;
1438
-	sip_trace(req, 0, 0);
1438
+	sip_trace(req, 0, NULL, 0);
1439 1439
 }
1440 1440
 
1441 1441
 static void trace_sl_onreply_out(sl_cbp_t *slcbp)
... ...
@@ -1513,7 +1600,7 @@ static void trace_sl_onreply_out(sl_cbp_t *slcbp)
1513 1513
 	sto.stat = siptrace_rpl;
1514 1514
 #endif
1515 1515
 
1516
-	sip_trace_store(&sto, NULL);
1516
+	sip_trace_store(&sto, NULL, NULL);
1517 1517
 	return;
1518 1518
 }
1519 1519
 
... ...
@@ -1579,7 +1666,181 @@ error:
1579 1579
 	return -1;
1580 1580
 }
1581 1581
 
1582
-static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_info * dst2)
1582
+static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_info * dst2, str *correlation_id_str)
1583
+{
1584
+	switch (hep_version) {
1585
+		case 1:
1586
+		case 2:
1587
+			return trace_send_hep2_duplicate(body, from, to, dst2);
1588
+		case 3:
1589
+			return trace_send_hep3_duplicate(body, from, to, dst2, correlation_id_str);
1590
+		default:
1591
+			LM_ERR("Unsupported HEP version\n");
1592
+			return -1;
1593
+	}
1594
+}
1595
+
1596
+static int trace_send_hep3_duplicate(str *body, str *from, str *to, struct dest_info * dst2, str *correlation_id_str)
1597
+{
1598
+	struct socket_info *si;
1599
+	void* buffer = NULL;
1600
+	unsigned int len, proto;
1601
+	struct dest_info dst;
1602
+	struct dest_info* dst_fin = NULL;
1603
+	struct proxy_l* p = NULL;
1604
+	union sockaddr_union from_su;
1605
+	union sockaddr_union to_su;
1606
+	struct timeval tvb;
1607
+	struct timezone tz;
1608
+
1609
+	gettimeofday( &tvb, &tz );
1610
+
1611
+	if (pipport2su(from->s, &from_su, &proto)==-1 || (pipport2su(to->s, &to_su, &proto)==-1))
1612
+		goto error;
1613
+
1614
+	if(from_su.s.sa_family != to_su.s.sa_family) {
1615
+		LM_ERR("interworking detected ?\n");
1616
+		goto error;
1617
+	}
1618
+
1619
+	len = sizeof(struct hep_ctrl);         // header
1620
+	len += sizeof(struct hep_chunk_uint8); // proto_family
1621
+	len += sizeof(struct hep_chunk_uint8); // proto_id
1622
+	if (from_su.s.sa_family == AF_INET6) {
1623
+		len += sizeof(struct hep_chunk_ip6); // src IPv6 address
1624
+		len += sizeof(struct hep_chunk_ip6); // dst IPv6 address
1625
+	}
1626
+	else {
1627
+		len += sizeof(struct hep_chunk_ip4); // src IPv4 address
1628
+		len += sizeof(struct hep_chunk_ip4); // dst IPv4 address
1629
+	}
1630
+	len += sizeof(struct hep_chunk_uint16); // source port
1631
+	len += sizeof(struct hep_chunk_uint16); // destination port
1632
+	len += sizeof(struct hep_chunk_uint32); // timestamp
1633
+	len += sizeof(struct hep_chunk_uint32); // timestamp us
1634
+	len += sizeof(struct hep_chunk_uint8); // proto_type (SIP)
1635
+	len += sizeof(struct hep_chunk_uint32); // capture ID
1636
+	len += sizeof(struct hep_chunk); // payload
1637
+
1638
+	if (auth_key_str.s && auth_key_str.len > 0) {
1639
+		len += sizeof(struct hep_chunk) + auth_key_str.len;
1640
+	}
1641
+
1642
+	if (correlation_id_str) {
1643
+		if (correlation_id_str->len > 0) {
1644
+			len += sizeof(struct hep_chunk) + correlation_id_str->len;
1645
+		}
1646
+	}
1647
+
1648
+	len += body->len;
1649
+
1650
+	if (unlikely(len>BUF_SIZE)){
1651
+		goto error;
1652
+	}
1653
+
1654
+	buffer = (void *)pkg_malloc(len);
1655
+	if (!buffer) {
1656
+		LM_ERR("out of memory\n");
1657
+		goto error;
1658
+	}
1659
+
1660
+	HEP3_PACK_INIT(buffer);
1661
+	HEP3_PACK_CHUNK_UINT8 (0, 0x0001, from_su.s.sa_family);
1662
+	HEP3_PACK_CHUNK_UINT8 (0, 0x0002, proto);
1663
+	if (from_su.s.sa_family == AF_INET) {
1664
+		HEP3_PACK_CHUNK_UINT32_NBO(0, 0x0003, from_su.sin.sin_addr.s_addr);
1665
+		HEP3_PACK_CHUNK_UINT32_NBO(0, 0x0004, to_su.sin.sin_addr.s_addr);
1666
+		HEP3_PACK_CHUNK_UINT16_NBO(0, 0x0007, htons(from_su.sin.sin_port));
1667
+		HEP3_PACK_CHUNK_UINT16_NBO(0, 0x0008, htons(to_su.sin.sin_port));
1668
+	} else if (from_su.s.sa_family == AF_INET6) {
1669
+		HEP3_PACK_CHUNK_IP6 (0, 0x0005, &from_su.sin6.sin6_addr);
1670
+		HEP3_PACK_CHUNK_IP6 (0, 0x0006, &to_su.sin6.sin6_addr);
1671
+		HEP3_PACK_CHUNK_UINT16_NBO(0, 0x0007, htons(from_su.sin6.sin6_port));
1672
+		HEP3_PACK_CHUNK_UINT16_NBO(0, 0x0008, htons(to_su.sin6.sin6_port));
1673
+	} else {
1674
+		LM_ERR("unknown address family [%u]\n", dst.send_sock->address.af);
1675
+		goto error;
1676
+	}
1677
+
1678
+	HEP3_PACK_CHUNK_UINT32(0, 0x0009, tvb.tv_sec);
1679
+	HEP3_PACK_CHUNK_UINT32(0, 0x000a, tvb.tv_usec);
1680
+	HEP3_PACK_CHUNK_UINT8 (0, 0x000b, 0x01); /* protocol type: SIP */
1681
+	HEP3_PACK_CHUNK_UINT32(0, 0x000c, hep_capture_id);
1682
+
1683
+	if (correlation_id_str) {
1684
+		if (correlation_id_str->len > 0) {
1685
+			HEP3_PACK_CHUNK_DATA (0, 0x0011, correlation_id_str->s, correlation_id_str->len);
1686
+		}
1687
+	}
1688
+	if (auth_key_str.len) {
1689
+		HEP3_PACK_CHUNK_DATA(0, 0x000e, auth_key_str.s, auth_key_str.len);
1690
+	}
1691
+	HEP3_PACK_CHUNK_DATA (0, 0x000f, body->s, body->len);
1692
+	HEP3_PACK_FINALIZE(buffer, &len);
1693
+
1694
+	if (!dst2){
1695
+		init_dest_info(&dst);
1696
+		dst.proto = PROTO_UDP;
1697
+		p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT,
1698
+		dst.proto);
1699
+		if (p==0)
1700
+		{
1701
+			LM_ERR("bad host name in uri\n");
1702
+			goto error;
1703
+		}
1704
+
1705
+		hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT);
1706
+		LM_DBG("setting up the socket_info\n");
1707
+		dst_fin = &dst;
1708
+	} else {
1709
+		dst_fin = dst2;
1710
+	}
1711
+
1712
+	if (force_send_sock_str.s) {
1713
+		LM_DBG("force_send_sock activated, grep for the sock_info\n");
1714
+		si = grep_sock_info(&force_send_sock_uri->host,
1715
+				(force_send_sock_uri->port_no)?force_send_sock_uri->port_no:SIP_PORT,
1716
+				PROTO_UDP);
1717
+		if (!si) {
1718
+			LM_WARN("cannot grep socket info\n");
1719
+		} else {
1720
+			LM_DBG("found socket while grep: [%.*s] [%.*s]\n", si->name.len, si->name.s, si->address_str.len, si->address_str.s);
1721
+			dst_fin->send_sock = si;
1722
+		}
1723
+	}
1724
+
1725
+	if (dst_fin->send_sock == 0) {
1726
+		dst_fin->send_sock=get_send_socket(0, &dst_fin->to, dst_fin->proto);
1727
+		if (dst_fin->send_sock == 0) {
1728
+			LM_ERR("can't forward to af %d, proto %d no corresponding"
1729
+					" listening socket\n", dst_fin->to.s.sa_family, dst_fin->proto);
1730
+			goto error;
1731
+		}
1732
+	}
1733
+
1734
+	if (msg_send_buffer(dst_fin, buffer, len, 1)<0)
1735
+	{
1736
+		LM_ERR("cannot send hep duplicate message\n");
1737
+		goto error;
1738
+	}
1739
+
1740
+	if (p) {
1741
+		free_proxy(p); /* frees only p content, not p itself */
1742
+		pkg_free(p);
1743
+	}
1744
+	pkg_free(buffer);
1745
+	return 0;
1746
+error:
1747
+	if(p)
1748
+	{
1749
+		free_proxy(p); /* frees only p content, not p itself */
1750
+		pkg_free(p);
1751
+	}
1752
+	if(buffer) pkg_free(buffer);
1753
+	return -1;
1754
+}
1755
+
1756
+static int trace_send_hep2_duplicate(str *body, str *from, str *to, struct dest_info * dst2)
1583 1757
 {
1584 1758
 	struct dest_info dst;
1585 1759
 	struct socket_info *si;
... ...
@@ -1901,7 +2162,7 @@ int siptrace_net_data_recv(void *data)
1901 1901
 
1902 1902
 	sto.dir = "in";
1903 1903
 
1904
-	trace_send_hep_duplicate(&sto.body, &sto.fromip, &sto.toip, NULL);
1904
+	trace_send_hep_duplicate(&sto.body, &sto.fromip, &sto.toip, NULL, NULL);
1905 1905
 	return 0;
1906 1906
 
1907 1907
 }
... ...
@@ -1949,7 +2210,7 @@ int siptrace_net_data_send(void *data)
1949 1949
 
1950 1950
 	sto.dir = "out";
1951 1951
 
1952
-	trace_send_hep_duplicate(&sto.body, &sto.fromip, &sto.toip, NULL);
1952
+	trace_send_hep_duplicate(&sto.body, &sto.fromip, &sto.toip, NULL, NULL);
1953 1953
 	return 0;
1954 1954
 }
1955 1955