1 /*
2  * siptrace module - helper module to trace sip messages
3  *
4  * Copyright (C) 2017 kamailio.org
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "../../core/dprint.h"
29 #include "../../core/pvar.h"
30 #include "../../core/proxy.h"
31 #include "../../core/forward.h"
32 #include "../../core/resolve.h"
33 #include "../../core/socket_info.h"
34 #include "../../core/parser/parse_uri.h"
35 
36 #include "../../modules/sipcapture/hep.h"
37 
38 #include "siptrace_hep.h"
39 
40 extern int hep_version;
41 extern int hep_capture_id;
42 extern int hep_vendor_id;
43 extern str hep_auth_key_str;
44 extern str trace_send_sock_str;
45 extern sip_uri_t *trace_send_sock_uri;
46 extern str trace_send_sock_name_str;
47 extern socket_info_t *trace_send_sock_info;
48 extern str trace_dup_uri_str;
49 extern sip_uri_t *trace_dup_uri;
50 
51 /**
52  *
53  */
trace_send_hep_duplicate(str * body,str * from,str * to,struct dest_info * dst2,str * correlation_id_str)54 int trace_send_hep_duplicate(str *body, str *from, str *to,
55 		struct dest_info *dst2, str *correlation_id_str)
56 {
57 	switch(hep_version) {
58 		case 1:
59 		case 2:
60 			return trace_send_hep2_duplicate(body, from, to, dst2);
61 		case 3:
62 			return trace_send_hep3_duplicate(
63 					body, from, to, dst2, correlation_id_str);
64 		default:
65 			LM_ERR("Unsupported HEP version\n");
66 			return -1;
67 	}
68 }
69 
70 /**
71  *
72  */
trace_send_hep3_duplicate(str * body,str * from,str * to,struct dest_info * dst2,str * correlation_id_str)73 int trace_send_hep3_duplicate(str *body, str *from, str *to,
74 		struct dest_info *dst2, str *correlation_id_str)
75 {
76 	struct socket_info *si;
77 	void *buffer = NULL;
78 	unsigned int len, proto;
79 	struct dest_info dst;
80 	struct dest_info *dst_fin = NULL;
81 	struct proxy_l *p = NULL;
82 	union sockaddr_union from_su;
83 	union sockaddr_union to_su;
84 	struct timeval tvb;
85 	struct timezone tz;
86 
87 	gettimeofday(&tvb, &tz);
88 
89 	if(pipport2su(from->s, &from_su, &proto) == -1
90 			|| (pipport2su(to->s, &to_su, &proto) == -1))
91 		goto error;
92 
93 	if(from_su.s.sa_family != to_su.s.sa_family) {
94 		LM_ERR("interworking detected ?\n");
95 		goto error;
96 	}
97 
98 	len = sizeof(struct hep_ctrl);		   // header
99 	len += sizeof(struct hep_chunk_uint8); // proto_family
100 	len += sizeof(struct hep_chunk_uint8); // proto_id
101 	if(from_su.s.sa_family == AF_INET6) {
102 		len += sizeof(struct hep_chunk_ip6); // src IPv6 address
103 		len += sizeof(struct hep_chunk_ip6); // dst IPv6 address
104 	} else {
105 		len += sizeof(struct hep_chunk_ip4); // src IPv4 address
106 		len += sizeof(struct hep_chunk_ip4); // dst IPv4 address
107 	}
108 	len += sizeof(struct hep_chunk_uint16); // source port
109 	len += sizeof(struct hep_chunk_uint16); // destination port
110 	len += sizeof(struct hep_chunk_uint32); // timestamp
111 	len += sizeof(struct hep_chunk_uint32); // timestamp us
112 	len += sizeof(struct hep_chunk_uint8);  // proto_type (SIP)
113 	len += sizeof(struct hep_chunk_uint32); // capture ID
114 	len += sizeof(struct hep_chunk);		// payload
115 
116 	if(hep_auth_key_str.s && hep_auth_key_str.len > 0) {
117 		len += sizeof(struct hep_chunk) + hep_auth_key_str.len;
118 	}
119 
120 	if(correlation_id_str) {
121 		if(correlation_id_str->len > 0) {
122 			len += sizeof(struct hep_chunk) + correlation_id_str->len;
123 		}
124 	}
125 
126 	len += body->len;
127 
128 	if(unlikely(len > BUF_SIZE)) {
129 		goto error;
130 	}
131 
132 	buffer = (void *)pkg_malloc(len);
133 	if(!buffer) {
134 		LM_ERR("out of memory\n");
135 		goto error;
136 	}
137 
138 	HEP3_PACK_INIT(buffer);
139 	HEP3_PACK_CHUNK_UINT8(0, 0x0001, from_su.s.sa_family);
140 	HEP3_PACK_CHUNK_UINT8(0, 0x0002, proto);
141 	if(from_su.s.sa_family == AF_INET) {
142 		HEP3_PACK_CHUNK_UINT32_NBO(0, 0x0003, from_su.sin.sin_addr.s_addr);
143 		HEP3_PACK_CHUNK_UINT32_NBO(0, 0x0004, to_su.sin.sin_addr.s_addr);
144 		HEP3_PACK_CHUNK_UINT16_NBO(0, 0x0007, htons(from_su.sin.sin_port));
145 		HEP3_PACK_CHUNK_UINT16_NBO(0, 0x0008, htons(to_su.sin.sin_port));
146 	} else if(from_su.s.sa_family == AF_INET6) {
147 		HEP3_PACK_CHUNK_IP6(0, 0x0005, &from_su.sin6.sin6_addr);
148 		HEP3_PACK_CHUNK_IP6(0, 0x0006, &to_su.sin6.sin6_addr);
149 		HEP3_PACK_CHUNK_UINT16_NBO(0, 0x0007, htons(from_su.sin6.sin6_port));
150 		HEP3_PACK_CHUNK_UINT16_NBO(0, 0x0008, htons(to_su.sin6.sin6_port));
151 	} else {
152 		LM_ERR("unknown address family [%u]\n", from_su.s.sa_family);
153 		goto error;
154 	}
155 
156 	HEP3_PACK_CHUNK_UINT32(0, 0x0009, tvb.tv_sec);
157 	HEP3_PACK_CHUNK_UINT32(0, 0x000a, tvb.tv_usec);
158 	HEP3_PACK_CHUNK_UINT8(0, 0x000b, 0x01); /* protocol type: SIP */
159 	HEP3_PACK_CHUNK_UINT32(0, 0x000c, hep_capture_id);
160 
161 	if(correlation_id_str) {
162 		if(correlation_id_str->len > 0) {
163 			HEP3_PACK_CHUNK_DATA(
164 					0, 0x0011, correlation_id_str->s, correlation_id_str->len);
165 		}
166 	}
167 	if(hep_auth_key_str.s && hep_auth_key_str.len > 0) {
168 		HEP3_PACK_CHUNK_DATA(0, 0x000e, hep_auth_key_str.s, hep_auth_key_str.len);
169 	}
170 	HEP3_PACK_CHUNK_DATA(0, 0x000f, body->s, body->len);
171 	HEP3_PACK_FINALIZE(buffer, &len);
172 
173 	if(!dst2) {
174 		init_dest_info(&dst);
175 		dst.proto = trace_dup_uri->proto;
176 		p = mk_proxy(&trace_dup_uri->host, trace_dup_uri->port_no, dst.proto);
177 		if(p == 0) {
178 			LM_ERR("bad host name in uri\n");
179 			goto error;
180 		}
181 
182 		hostent2su(
183 				&dst.to, &p->host, p->addr_idx, (p->port) ? p->port : SIP_PORT);
184 		LM_DBG("setting up the socket_info\n");
185 		dst_fin = &dst;
186 	} else {
187 		dst_fin = dst2;
188 	}
189 
190 	if(trace_send_sock_str.s) {
191 		LM_DBG("send sock activated, grep for the sock_info\n");
192 		si = grep_sock_info(&trace_send_sock_uri->host,
193 				trace_send_sock_uri->port_no,
194 				trace_send_sock_uri->proto);
195 		if(!si) {
196 			LM_WARN("cannot grep socket info\n");
197 		} else {
198 			LM_DBG("found socket while grep: [%.*s] [%.*s]\n", si->name.len,
199 					si->name.s, si->address_str.len, si->address_str.s);
200 			dst_fin->send_sock = si;
201 		}
202 	}
203 
204 	if(dst_fin->send_sock == 0) {
205 		dst_fin->send_sock = get_send_socket(0, &dst_fin->to, dst_fin->proto);
206 		if(dst_fin->send_sock == 0) {
207 			LM_ERR("can't forward to af %d, proto %d no corresponding"
208 				   " listening socket\n",
209 					dst_fin->to.s.sa_family, dst_fin->proto);
210 			goto error;
211 		}
212 	}
213 
214 	if(msg_send_buffer(dst_fin, buffer, len, 1) < 0) {
215 		LM_ERR("cannot send hep duplicate message\n");
216 		goto error;
217 	}
218 
219 	if(p) {
220 		free_proxy(p); /* frees only p content, not p itself */
221 		pkg_free(p);
222 	}
223 	pkg_free(buffer);
224 	return 0;
225 error:
226 	if(p) {
227 		free_proxy(p); /* frees only p content, not p itself */
228 		pkg_free(p);
229 	}
230 	if(buffer)
231 		pkg_free(buffer);
232 	return -1;
233 }
234 
235 /**
236  *
237  */
trace_send_hep2_duplicate(str * body,str * from,str * to,struct dest_info * dst2)238 int trace_send_hep2_duplicate(
239 		str *body, str *from, str *to, struct dest_info *dst2)
240 {
241 	struct dest_info dst;
242 	struct socket_info *si;
243 	struct dest_info *dst_fin = NULL;
244 	struct proxy_l *p = NULL /* make gcc happy */;
245 	void *buffer = NULL;
246 	union sockaddr_union from_su;
247 	union sockaddr_union to_su;
248 	unsigned int len, buflen, proto;
249 	struct hep_hdr hdr;
250 	struct hep_iphdr hep_ipheader;
251 	struct hep_timehdr hep_time;
252 	struct timeval tvb;
253 	struct timezone tz;
254 
255 	struct hep_ip6hdr hep_ip6header;
256 
257 	if(body->s == NULL || body->len <= 0)
258 		return -1;
259 
260 	if(trace_dup_uri_str.s == 0 || trace_dup_uri == NULL)
261 		return 0;
262 
263 
264 	gettimeofday(&tvb, &tz);
265 
266 
267 	/* message length */
268 	len = body->len + sizeof(struct hep_ip6hdr) + sizeof(struct hep_hdr)
269 		  + sizeof(struct hep_timehdr);
270 	;
271 
272 
273 	/* The packet is too big for us */
274 	if(unlikely(len > BUF_SIZE)) {
275 		goto error;
276 	}
277 
278 	/* Convert proto:ip:port to sockaddress union SRC IP */
279 	if(pipport2su(from->s, &from_su, &proto) == -1
280 			|| (pipport2su(to->s, &to_su, &proto) == -1))
281 		goto error;
282 
283 	/* check if from and to are in the same family*/
284 	if(from_su.s.sa_family != to_su.s.sa_family) {
285 		LM_ERR("interworking detected ?\n");
286 		goto error;
287 	}
288 
289 	if(!dst2) {
290 		init_dest_info(&dst);
291 		/* create a temporary proxy*/
292 		dst.proto = trace_dup_uri->proto;
293 		p = mk_proxy(&trace_dup_uri->host, trace_dup_uri->port_no, dst.proto);
294 		if(p == 0) {
295 			LM_ERR("bad host name in uri\n");
296 			goto error;
297 		}
298 
299 		hostent2su(
300 				&dst.to, &p->host, p->addr_idx, (p->port) ? p->port : SIP_PORT);
301 		LM_DBG("setting up the socket_info\n");
302 		dst_fin = &dst;
303 	} else {
304 		dst_fin = dst2;
305 	}
306 
307 	if(trace_send_sock_str.s) {
308 		LM_DBG("send sock activated, grep for the sock_info\n");
309 		si = grep_sock_info(&trace_send_sock_uri->host,
310 				trace_send_sock_uri->port_no,
311 				trace_send_sock_uri->proto);
312 		if(!si) {
313 			LM_WARN("cannot grep socket info\n");
314 		} else {
315 			LM_DBG("found socket while grep: [%.*s] [%.*s]\n", si->name.len,
316 					si->name.s, si->address_str.len, si->address_str.s);
317 			dst_fin->send_sock = si;
318 		}
319 	}
320 
321 	if(dst_fin->send_sock == 0) {
322 		dst_fin->send_sock = get_send_socket(0, &dst_fin->to, dst_fin->proto);
323 		if(dst_fin->send_sock == 0) {
324 			LM_ERR("can't forward to af %d, proto %d no corresponding"
325 				   " listening socket\n",
326 					dst_fin->to.s.sa_family, dst_fin->proto);
327 			goto error;
328 		}
329 	}
330 
331 	/* Version && proto && length */
332 	hdr.hp_l = sizeof(struct hep_hdr);
333 	hdr.hp_v = hep_version;
334 	hdr.hp_p = proto;
335 
336 	/* AND the last */
337 	if(from_su.s.sa_family == AF_INET) {
338 		/* prepare the hep headers */
339 
340 		hdr.hp_f = AF_INET;
341 		hdr.hp_sport = htons(from_su.sin.sin_port);
342 		hdr.hp_dport = htons(to_su.sin.sin_port);
343 
344 		hep_ipheader.hp_src = from_su.sin.sin_addr;
345 		hep_ipheader.hp_dst = to_su.sin.sin_addr;
346 
347 		len = sizeof(struct hep_iphdr);
348 	} else if(from_su.s.sa_family == AF_INET6) {
349 		/* prepare the hep6 headers */
350 
351 		hdr.hp_f = AF_INET6;
352 
353 		hdr.hp_sport = htons(from_su.sin6.sin6_port);
354 		hdr.hp_dport = htons(to_su.sin6.sin6_port);
355 
356 		hep_ip6header.hp6_src = from_su.sin6.sin6_addr;
357 		hep_ip6header.hp6_dst = to_su.sin6.sin6_addr;
358 
359 		len = sizeof(struct hep_ip6hdr);
360 	} else {
361 		LM_ERR("Unsupported protocol family\n");
362 		goto error;
363 		;
364 	}
365 
366 	hdr.hp_l += len;
367 	if(hep_version == 2) {
368 		len += sizeof(struct hep_timehdr);
369 	}
370 	len += sizeof(struct hep_hdr) + body->len;
371 	buffer = (void *)pkg_malloc(len + 1);
372 	if(buffer == 0) {
373 		LM_ERR("out of memory\n");
374 		goto error;
375 	}
376 
377 	/* Copy job */
378 	memset(buffer, '\0', len + 1);
379 
380 	/* copy hep_hdr */
381 	memcpy((void *)buffer, &hdr, sizeof(struct hep_hdr));
382 	buflen = sizeof(struct hep_hdr);
383 
384 	/* hep_ip_hdr */
385 	if(from_su.s.sa_family == AF_INET) {
386 		memcpy((void *)buffer + buflen, &hep_ipheader,
387 				sizeof(struct hep_iphdr));
388 		buflen += sizeof(struct hep_iphdr);
389 	} else {
390 		memcpy((void *)buffer + buflen, &hep_ip6header,
391 				sizeof(struct hep_ip6hdr));
392 		buflen += sizeof(struct hep_ip6hdr);
393 	}
394 
395 	if(hep_version == 2) {
396 
397 		hep_time.tv_sec = to_le(tvb.tv_sec);
398 		hep_time.tv_usec = to_le(tvb.tv_usec);
399 		hep_time.captid = hep_capture_id;
400 
401 		memcpy((void *)buffer + buflen, &hep_time, sizeof(struct hep_timehdr));
402 		buflen += sizeof(struct hep_timehdr);
403 	}
404 
405 	/* PAYLOAD */
406 	memcpy((void *)(buffer + buflen), (void *)body->s, body->len);
407 	buflen += body->len;
408 
409 	if(msg_send_buffer(dst_fin, buffer, buflen, 1) < 0) {
410 		LM_ERR("cannot send hep duplicate message\n");
411 		goto error;
412 	}
413 
414 	if(p) {
415 		free_proxy(p); /* frees only p content, not p itself */
416 		pkg_free(p);
417 	}
418 	pkg_free(buffer);
419 	return 0;
420 error:
421 	if(p) {
422 		free_proxy(p); /* frees only p content, not p itself */
423 		pkg_free(p);
424 	}
425 	if(buffer)
426 		pkg_free(buffer);
427 	return -1;
428 }
429 
430 /*!
431  * \brief Convert a STR [proto:]ip[:port] into socket address.
432  * [proto:]ip[:port]
433  * \param pipport (udp:127.0.0.1:5060 or tcp:2001:0DB8:AC10:FE01:5060)
434  * \param tmp_su target structure
435  * \param proto uint protocol type
436  * \return success / unsuccess
437  */
pipport2su(char * pipport,union sockaddr_union * tmp_su,unsigned int * proto)438 int pipport2su(char *pipport, union sockaddr_union *tmp_su, unsigned int *proto)
439 {
440 	unsigned int port_no, cutlen = 4;
441 	struct ip_addr *ip;
442 	char *p, *host_s;
443 	str port_str, host_uri;
444 	unsigned len = 0;
445 	char tmp_piport[256];
446 
447 	/*parse protocol */
448 	if(strncmp(pipport, "udp:", 4) == 0)
449 		*proto = IPPROTO_UDP;
450 	else if(strncmp(pipport, "tcp:", 4) == 0)
451 		*proto = IPPROTO_TCP;
452 	else if(strncmp(pipport, "tls:", 4) == 0)
453 		*proto = IPPROTO_IDP; /* fake proto type */
454 	else if(strncmp(pipport, "ws:", 3) == 0)
455 		cutlen = 3, *proto = IPPROTO_IDP; /* fake proto type */
456 	else if(strncmp(pipport, "wss:", 4) == 0)
457 		*proto = IPPROTO_IDP; /* fake proto type */
458 #ifdef USE_SCTP
459 	else if(strncmp(pipport, "sctp:", 5) == 0)
460 		cutlen = 5, *proto = IPPROTO_SCTP;
461 #endif
462 	else if(strncmp(pipport, "any:", 4) == 0)
463 		*proto = IPPROTO_UDP;
464 	else {
465 		LM_ERR("bad protocol %s\n", pipport);
466 		return -1;
467 	}
468 
469 	if((len = strlen(pipport)) >= 256) {
470 		LM_ERR("too big pipport\n");
471 		goto error;
472 	}
473 
474 	/* our tmp string */
475 	strncpy(tmp_piport, pipport, len + 1);
476 
477 	len = 0;
478 
479 	/*separate proto and host */
480 	p = tmp_piport + cutlen;
481 	if((*(p)) == '\0') {
482 		LM_ERR("malformed ip address\n");
483 		goto error;
484 	}
485 	host_s = p;
486 
487 	if((p = strrchr(p + 1, ':')) == 0) {
488 		LM_DBG("no port specified\n");
489 		port_no = 0;
490 	} else {
491 		/*the address contains a port number*/
492 		*p = '\0';
493 		p++;
494 		port_str.s = p;
495 		port_str.len = strlen(p);
496 		LM_DBG("the port string is %s\n", p);
497 		if(str2int(&port_str, &port_no) != 0) {
498 			LM_ERR("there is not a valid number port\n");
499 			goto error;
500 		}
501 		*p = '\0';
502 	}
503 
504 	/* now IPv6 address has no brakets. It should be fixed! */
505 	if(host_s[0] == '[') {
506 		len = strlen(host_s + 1) - 1;
507 		if(host_s[len + 1] != ']') {
508 			LM_ERR("bracket not closed\n");
509 			goto error;
510 		}
511 		memmove(host_s, host_s + 1, len);
512 		host_s[len] = '\0';
513 	}
514 
515 	host_uri.s = host_s;
516 	host_uri.len = strlen(host_s);
517 
518 	/* check if it's an ip address */
519 	if(((ip = str2ip(&host_uri)) != 0) || ((ip = str2ip6(&host_uri)) != 0)) {
520 		ip_addr2su(tmp_su, ip, ntohs(port_no));
521 		return 0;
522 	}
523 
524 error:
525 	return -1;
526 }
527 
528 /**
529  *
530  */
hlog(struct sip_msg * msg,str * correlationid,str * message)531 int hlog(struct sip_msg *msg, str *correlationid, str *message)
532 {
533 	char *buf;
534 	size_t len;
535 	struct timeval tvb;
536 	struct timezone tz;
537 	struct dest_info dst;
538 	struct proxy_l *p = NULL;
539 
540 	if(!correlationid) {
541 		if(msg->callid == NULL && ((parse_headers(msg, HDR_CALLID_F, 0) == -1)
542 										  || (msg->callid == NULL))) {
543 			LM_ERR("cannot parse Call-Id header\n");
544 			return -1;
545 		}
546 		correlationid = &(msg->callid->body);
547 	}
548 
549 	len = sizeof(hep_ctrl_t)
550 		  + sizeof(hep_chunk_uint8_t)  /* ip protocol family */
551 		  + sizeof(hep_chunk_uint8_t)  /* ip protocol id */
552 		  + sizeof(hep_chunk_t) + 16   /* src address (enough space for ipv6) */
553 		  + sizeof(hep_chunk_t) + 16   /* dst address (ditto) */
554 		  + sizeof(hep_chunk_uint16_t) /* src port */
555 		  + sizeof(hep_chunk_uint16_t) /* dst port */
556 		  + sizeof(hep_chunk_uint32_t) /* timestamp */
557 		  + sizeof(hep_chunk_uint32_t) /* timestamp micro */
558 		  + sizeof(hep_chunk_uint32_t) /* capture id */
559 		  + sizeof(hep_chunk_uint8_t)  /* protocol type */
560 		  + sizeof(hep_chunk_t) + correlationid->len + sizeof(hep_chunk_t)
561 		  + message->len;
562 
563 	if(hep_auth_key_str.len) {
564 		len += sizeof(hep_chunk_t) + hep_auth_key_str.len;
565 	}
566 
567 	buf = pkg_malloc(len);
568 
569 	if(!buf) {
570 		LM_ERR("no more pkg memory\n");
571 		return -1;
572 	}
573 
574 	gettimeofday(&tvb, &tz);
575 
576 	init_dest_info(&dst);
577 	dst.proto = trace_dup_uri->proto;
578 	p = mk_proxy(&trace_dup_uri->host, trace_dup_uri->port_no, dst.proto);
579 	if(p == 0) {
580 		LM_ERR("bad host name in uri\n");
581 		goto error;
582 	}
583 
584 	hostent2su(&dst.to, &p->host, p->addr_idx, (p->port) ? p->port : SIP_PORT);
585 	LM_DBG("setting up the socket_info\n");
586 
587 	free_proxy(p); /* frees only p content, not p itself */
588 	pkg_free(p);
589 
590 	if(trace_send_sock_name_str.s) {
591 		dst.send_sock = trace_send_sock_info;
592 	} else if(trace_send_sock_str.s) {
593 		LM_DBG("send sock activated - find the sock info\n");
594 		if(trace_send_sock_info) {
595 			dst.send_sock = trace_send_sock_info;
596 		} else {
597 			dst.send_sock = grep_sock_info(&trace_send_sock_uri->host,
598 					trace_send_sock_uri->port_no,
599 					trace_send_sock_uri->proto);
600 		}
601 		if(!dst.send_sock) {
602 			LM_WARN("local socket not found for: [%.*s]\n",
603 					trace_send_sock_str.len, trace_send_sock_str.s);
604 		} else {
605 			LM_DBG("using local send socket: [%.*s] [%.*s]\n",
606 					dst.send_sock->name.len, dst.send_sock->name.s,
607 					dst.send_sock->address_str.len, dst.send_sock->address_str.s);
608 		}
609 	}
610 
611 	if(dst.send_sock == 0) {
612 		dst.send_sock = get_send_socket(0, &dst.to, dst.proto);
613 		if(dst.send_sock == 0) {
614 			LM_ERR("can't forward to af %d, proto %d no corresponding"
615 				   " listening socket\n",
616 					dst.to.s.sa_family, dst.proto);
617 			goto error;
618 		}
619 	}
620 
621 	HEP3_PACK_INIT(buf);
622 	HEP3_PACK_CHUNK_UINT8(0, 0x0001, dst.send_sock->address.af);
623 	HEP3_PACK_CHUNK_UINT8(0, 0x0002, 0x11);
624 	if(dst.send_sock->address.af == AF_INET) {
625 		HEP3_PACK_CHUNK_UINT32_NBO(
626 				0, 0x0003, dst.send_sock->address.u.addr32[0]);
627 		HEP3_PACK_CHUNK_UINT32_NBO(0, 0x0004, dst.to.sin.sin_addr.s_addr);
628 		HEP3_PACK_CHUNK_UINT16_NBO(0, 0x0008, dst.to.sin.sin_port);
629 	} else if(dst.send_sock->address.af == AF_INET6) {
630 		HEP3_PACK_CHUNK_IP6(0, 0x0005, dst.send_sock->address.u.addr);
631 		HEP3_PACK_CHUNK_IP6(0, 0x0006, &dst.to.sin6.sin6_addr);
632 		HEP3_PACK_CHUNK_UINT16_NBO(0, 0x0008, dst.to.sin6.sin6_port);
633 	} else {
634 		LM_ERR("unknown address family [%u]\n", dst.send_sock->address.af);
635 		goto error;
636 	}
637 	HEP3_PACK_CHUNK_UINT16(0, 0x0007, dst.send_sock->port_no);
638 
639 	HEP3_PACK_CHUNK_UINT32(0, 0x0009, tvb.tv_sec);
640 	HEP3_PACK_CHUNK_UINT32(0, 0x000a, tvb.tv_usec);
641 	HEP3_PACK_CHUNK_UINT8(0, 0x000b, 0x64); /* protocol type: log */
642 	HEP3_PACK_CHUNK_UINT32(0, 0x000c, hep_capture_id);
643 	HEP3_PACK_CHUNK_DATA(0, 0x0011, correlationid->s, correlationid->len);
644 	if(hep_auth_key_str.s && hep_auth_key_str.len > 0) {
645 		HEP3_PACK_CHUNK_DATA(0, 0x000e, hep_auth_key_str.s, hep_auth_key_str.len);
646 	}
647 	HEP3_PACK_CHUNK_DATA(0, 0x000f, message->s, message->len);
648 	HEP3_PACK_FINALIZE(buf, &len);
649 
650 	if(msg_send_buffer(&dst, buf, len, 1) < 0) {
651 		LM_ERR("cannot send hep log\n");
652 		goto error;
653 	}
654 
655 	pkg_free(buf);
656 	return 1;
657 
658 error:
659 	pkg_free(buf);
660 	return -1;
661 }
662