src/modules/sipcapture/hep.c
6eda5e28
 /*
  * hep related functions
  *
1708de3f
  * Copyright (C) 2011-2014 Alexandr Dubovikov <alexandr.dubovikov@gmail.com>
6eda5e28
  *
  * This file is part of Kamailio, a free SIP server.
  *
  * Kamailio is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version
  *
  * Kamailio is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
9e1ff448
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
6eda5e28
  *
  */
 
cf83221d
 #include "../../core/sr_module.h"
 #include "../../core/dprint.h"
 #include "../../core/events.h"
 #include "../../core/ut.h"
 #include "../../core/ip_addr.h"
 #include "../../core/mem/mem.h"
 #include "../../core/mem/shm_mem.h"
6eda5e28
 #include "../../lib/srdb1/db.h"
cf83221d
 #include "../../core/receive.h"
6eda5e28
 
 #include "hep.h"
94f1d28e
 #include "sipcapture.h"
 
 
6eda5e28
 static int count = 0;
 
16bc1515
 extern struct hep_timeinfo *heptime;
6eda5e28
 
 /* HEPv2 HEPv3 */
 int hepv2_received(char *buf, unsigned int len, struct receive_info *ri);
 int hepv3_received(char *buf, unsigned int len, struct receive_info *ri);
 int parsing_hepv3_message(char *buf, unsigned int len);
4e789387
 
6eda5e28
 /**
  * HEP message
  */
 /* int hep_msg_received(char * buf, unsigned int len, struct receive_info * ri) */
e67142d0
 int hep_msg_received(sr_event_param_t *evp)
6eda5e28
 {
1708de3f
 	void **srevp;
 	char *buf;
 	unsigned *len;
 	struct receive_info *ri;
 
 	if(!hep_capture_on) {
 		LOG(L_ERR, "sipcapture:hep_msg_received HEP is not enabled\n");
 		return -1;
 	}
6eda5e28
 
1708de3f
 	srevp = (void **)evp->data;
6eda5e28
 
1708de3f
 	buf = (char *)srevp[0];
 	len = (unsigned *)srevp[1];
 	ri = (struct receive_info *)srevp[2];
6eda5e28
 
b400123d
 	correlation_id = NULL;
 	authkey = NULL;
 
6eda5e28
 	count++;
1708de3f
 	struct hep_hdr *heph;
 	/* hep_hdr */
 	heph = (struct hep_hdr *)buf;
6eda5e28
 
1708de3f
 	/* Check version */
 	if(heph->hp_v == 1 || heph->hp_v == 2) {
6eda5e28
 
1708de3f
 		return hepv2_received(buf, *len, ri);
 	} else if(!memcmp(buf, "\x48\x45\x50\x33", 4)) {
6eda5e28
 
1708de3f
 		return hepv3_received(buf, *len, ri);
 	} else {
6eda5e28
 
1708de3f
 		LOG(L_ERR, "ERROR: sipcapture:hep_msg_received: not supported version "
 				   "or bad length: v:[%d] l:[%d]\n",
 				heph->hp_v, heph->hp_l);
 		return -1;
 	}
6eda5e28
 }
 
1708de3f
 int hepv2_received(char *buf, unsigned int len, struct receive_info *ri)
 {
6eda5e28
 
 	int hl;
1708de3f
 	struct hep_hdr *heph;
 	struct ip_addr dst_ip, src_ip;
 	char *hep_payload, *end, *hep_ip;
 	struct hep_iphdr *hepiph = NULL;
 
 	struct hep_timehdr *heptime_tmp = NULL;
 	memset(heptime, 0, sizeof(struct hep_timeinfo));
6eda5e28
 
1708de3f
 	struct hep_ip6hdr *hepip6h = NULL;
6eda5e28
 
b400123d
 	correlation_id = NULL;
 	authkey = NULL;
6eda5e28
 
1708de3f
 	hep_offset = 0;
 
6eda5e28
 	hl = hep_offset = sizeof(struct hep_hdr);
1708de3f
 	end = buf + len;
 	if(unlikely(len < hep_offset)) {
 		LOG(L_ERR, "ERROR: sipcapture:hep_msg_received len less than offset "
 				   "[%i] vs [%i]\n",
 				len, hep_offset);
 		return -1;
 	}
6eda5e28
 
 	/* hep_hdr */
1708de3f
 	heph = (struct hep_hdr *)buf;
6eda5e28
 
1708de3f
 	switch(heph->hp_f) {
 		case AF_INET:
 			hl += sizeof(struct hep_iphdr);
 			break;
6eda5e28
 		case AF_INET6:
1708de3f
 			hl += sizeof(struct hep_ip6hdr);
 			break;
6eda5e28
 		default:
1708de3f
 			LOG(L_ERR, "ERROR: sipcapture:hep_msg_received:  unsupported "
 					   "family [%d]\n",
 					heph->hp_f);
 			return -1;
6eda5e28
 	}
 
1708de3f
 	/* PROTO */
 	if(heph->hp_p == IPPROTO_UDP)
 		ri->proto = PROTO_UDP;
 	else if(heph->hp_p == IPPROTO_TCP)
 		ri->proto = PROTO_TCP;
 	else if(heph->hp_p == IPPROTO_IDP)
 		ri->proto = PROTO_TLS; /* fake protocol */
6eda5e28
 #ifdef USE_SCTP
1708de3f
 	else if(heph->hp_p == IPPROTO_SCTP)
 		ri->proto = PROTO_SCTP;
6eda5e28
 #endif
1708de3f
 	else {
 		LOG(L_ERR,
 				"ERROR: sipcapture:hep_msg_received: unknown protocol [%d]\n",
 				heph->hp_p);
 		ri->proto = PROTO_NONE;
6eda5e28
 	}
 
1708de3f
 	hep_ip = buf + sizeof(struct hep_hdr);
6eda5e28
 
1708de3f
 	if(unlikely(hep_ip > end)) {
 		LOG(L_ERR, "hep_ip is over buf+len\n");
 		return -1;
 	}
6eda5e28
 
1708de3f
 	switch(heph->hp_f) {
6eda5e28
 		case AF_INET:
1708de3f
 			hep_offset += sizeof(struct hep_iphdr);
 			hepiph = (struct hep_iphdr *)hep_ip;
 			break;
6eda5e28
 
 		case AF_INET6:
1708de3f
 			hep_offset += sizeof(struct hep_ip6hdr);
 			hepip6h = (struct hep_ip6hdr *)hep_ip;
 			break;
6eda5e28
 	}
 
 	/* VOIP payload */
1708de3f
 	hep_payload = buf + hep_offset;
6eda5e28
 
1708de3f
 	if(unlikely(hep_payload > end)) {
 		LOG(L_ERR, "hep_payload is over buf+len\n");
 		return -1;
6eda5e28
 	}
 
 	/* timming */
1708de3f
 	if(heph->hp_v == 2) {
 		hep_offset += sizeof(struct hep_timehdr);
 		heptime_tmp = (struct hep_timehdr *)hep_payload;
6eda5e28
 
1708de3f
 		heptime->tv_sec = to_le(heptime_tmp->tv_sec);
 		heptime->tv_usec = to_le(heptime_tmp->tv_usec);
 		heptime->captid = heptime_tmp->captid;
 	}
6eda5e28
 
 
 	/* fill ip from the packet to dst_ip && to */
1708de3f
 	switch(heph->hp_f) {
6eda5e28
 
 		case AF_INET:
1708de3f
 			dst_ip.af = src_ip.af = AF_INET;
 			dst_ip.len = src_ip.len = 4;
 			memcpy(&dst_ip.u.addr, &hepiph->hp_dst, 4);
 			memcpy(&src_ip.u.addr, &hepiph->hp_src, 4);
 			break;
6eda5e28
 
 		case AF_INET6:
1708de3f
 			dst_ip.af = src_ip.af = AF_INET6;
 			dst_ip.len = src_ip.len = 16;
 			memcpy(&dst_ip.u.addr, &hepip6h->hp6_dst, 16);
 			memcpy(&src_ip.u.addr, &hepip6h->hp6_src, 16);
 			break;
6eda5e28
 	}
 
1708de3f
 	ri->src_ip = src_ip;
 	ri->src_port = ntohs(heph->hp_sport);
6eda5e28
 
1708de3f
 	ri->dst_ip = dst_ip;
 	ri->dst_port = ntohs(heph->hp_dport);
6eda5e28
 
 	/* cut off the offset */
 	/* 
 	 *  len -= offset;
          *  p = buf + offset;
 	 *  memmove(buf, p, BUF_SIZE+1); 
 	*/
 
1708de3f
 	hep_payload = buf + hep_offset;
 
 	receive_msg(hep_payload, (unsigned int)(len - hep_offset), ri);
6eda5e28
 
 	return -1;
 }
 
 
 /**
  * HEP message
  */
 int hepv3_received(char *buf, unsigned int len, struct receive_info *ri)
 {
19c8f0ea
 	if(!parsing_hepv3_message(buf, len)) {
6eda5e28
 		LM_ERR("couldn't parse hepv3 message\n");
1708de3f
 		return -2;
 	}
6eda5e28
 
 	return -1;
 }
 
1708de3f
 int parsing_hepv3_message(char *buf, unsigned int len)
 {
6eda5e28
 
 	union sockaddr_union from;
 	union sockaddr_union to;
1708de3f
 	struct receive_info ri;
6eda5e28
 	char *tmp;
 	struct ip_addr dst_ip, src_ip;
1708de3f
 	struct socket_info *si = 0;
6eda5e28
 	int tmp_len, i;
 	char *payload = NULL;
 	unsigned int payload_len = 0;
1708de3f
 	struct hep_chunk *chunk;
 	struct hep_generic_recv *hg;
 	int totelem = 0;
 	int chunk_vendor = 0, chunk_type = 0, chunk_length = 0;
 	int total_length = 0;
 
 
 	hg = (struct hep_generic_recv *)pkg_malloc(sizeof(struct hep_generic_recv));
 	if(hg == NULL) {
 		LM_ERR("no more pkg memory left for hg\n");
 		return -1;
 	}
 
6eda5e28
 	memset(hg, 0, sizeof(struct hep_generic_recv));
 
1708de3f
 
 	memset(heptime, 0, sizeof(struct hep_timeinfo));
 
6eda5e28
 
 	/* HEADER */
1708de3f
 	hg->header = (hep_ctrl_t *)(buf);
6eda5e28
 
 	/*Packet size */
 	total_length = ntohs(hg->header->length);
 
 	ri.src_port = 0;
 	ri.dst_port = 0;
 	dst_ip.af = 0;
1708de3f
 	src_ip.af = 0;
 
6eda5e28
 	payload = NULL;
53cb8649
 	correlation_id = NULL;
 	authkey = NULL;
6eda5e28
 
1708de3f
 	i = sizeof(hep_ctrl_t);
 
6eda5e28
 	while(i < total_length) {
1708de3f
 
 		/*OUR TMP DATA */
 		tmp = buf + i;
 
 		chunk = (struct hep_chunk *)tmp;
 
 		chunk_vendor = ntohs(chunk->vendor_id);
 		chunk_type = ntohs(chunk->type_id);
 		chunk_length = ntohs(chunk->length);
 
 
 		/* if chunk_length */
 		if(chunk_length == 0) {
 			/* BAD LEN we drop this packet */
 			goto error;
 		}
 
 		/* SKIP not general Chunks */
 		if(chunk_vendor != 0) {
 			i += chunk_length;
 		} else {
 			switch(chunk_type) {
 
 				case 0:
 					goto error;
 					break;
 
 				case 1:
 					hg->ip_family = (hep_chunk_uint8_t *)(tmp);
 					i += chunk_length;
 					totelem++;
94f1d28e
 					break;
1708de3f
 				case 2:
 					hg->ip_proto = (hep_chunk_uint8_t *)(tmp);
 					i += chunk_length;
 					totelem++;
 					break;
 				case 3:
 					hg->hep_src_ip4 = (hep_chunk_ip4_t *)(tmp);
 					i += chunk_length;
 					src_ip.af = AF_INET;
 					src_ip.len = 4;
 					src_ip.u.addr32[0] = hg->hep_src_ip4->data.s_addr;
 					totelem++;
 					break;
 				case 4:
 					hg->hep_dst_ip4 = (hep_chunk_ip4_t *)(tmp);
 					i += chunk_length;
 					dst_ip.af = AF_INET;
 					dst_ip.len = 4;
 					dst_ip.u.addr32[0] = hg->hep_dst_ip4->data.s_addr;
 					totelem++;
94f1d28e
 
1708de3f
 					break;
 				case 5:
 					hg->hep_src_ip6 = (hep_chunk_ip6_t *)(tmp);
 					i += chunk_length;
 					src_ip.af = AF_INET6;
 					src_ip.len = 16;
 					memcpy(src_ip.u.addr, &hg->hep_src_ip6->data, 16);
 					totelem++;
 					break;
 				case 6:
 					hg->hep_dst_ip6 = (hep_chunk_ip6_t *)(tmp);
 					i += chunk_length;
 					dst_ip.af = AF_INET6;
 					dst_ip.len = 16;
 					memcpy(dst_ip.u.addr, &hg->hep_dst_ip6->data, 16);
 					totelem++;
 					break;
 
 				case 7:
 					hg->src_port = (hep_chunk_uint16_t *)(tmp);
 					ri.src_port = ntohs(hg->src_port->data);
 					i += chunk_length;
 					totelem++;
 					break;
 
 				case 8:
 					hg->dst_port = (hep_chunk_uint16_t *)(tmp);
 					ri.dst_port = ntohs(hg->dst_port->data);
 					i += chunk_length;
 					totelem++;
 					break;
 				case 9:
 					hg->time_sec = (hep_chunk_uint32_t *)(tmp);
 					heptime->tv_sec = ntohl(hg->time_sec->data);
 					i += chunk_length;
 					totelem++;
 					break;
 
 				case 10:
 					hg->time_usec = (hep_chunk_uint32_t *)(tmp);
 					heptime->tv_usec = ntohl(hg->time_usec->data);
 					i += chunk_length;
 					totelem++;
 					break;
 
 				case 11:
 					hg->proto_t = (hep_chunk_uint8_t *)(tmp);
 					i += chunk_length;
 					totelem++;
 					break;
 
 				case 12:
 					hg->capt_id = (hep_chunk_uint32_t *)(tmp);
 					heptime->captid = ntohl(hg->capt_id->data);
 					i += chunk_length;
 					totelem++;
 					break;
 
 				case 13:
 					hg->keep_tm = (hep_chunk_uint16_t *)(tmp);
 					i += chunk_length;
 					break;
 
 				case 14:
 					authkey = (char *)tmp + sizeof(hep_chunk_t);
 					i += chunk_length;
 					break;
 
 				case 15:
 					hg->payload_chunk = (hep_chunk_t *)(tmp);
 					payload = (char *)tmp + sizeof(hep_chunk_t);
 					payload_len = chunk_length - sizeof(hep_chunk_t);
 					i += chunk_length;
 					totelem++;
 					break;
 				case 17:
 
 					correlation_id = (char *)tmp + sizeof(hep_chunk_t);
 					i += chunk_length;
 					break;
 
 
 				default:
 					i += chunk_length;
 					break;
 			}
 		}
 	}
 
 	/* CHECK how much elements */
 	if(totelem < 9) {
 		LM_ERR("Not all elements [%d]\n", totelem);
 		goto done;
 	}
 
 	if(dst_ip.af == 0 || src_ip.af == 0) {
 		LM_ERR("NO IP's set\n");
 		goto done;
 	}
 
 
 	ip_addr2su(&to, &dst_ip, ri.dst_port);
 	ip_addr2su(&from, &src_ip, ri.src_port);
 
 	ri.src_su = from;
 	su2ip_addr(&ri.src_ip, &from);
 	su2ip_addr(&ri.dst_ip, &to);
 
 	if(hg->ip_proto->data == IPPROTO_TCP)
 		ri.proto = PROTO_TCP;
 	else if(hg->ip_proto->data == IPPROTO_UDP)
 		ri.proto = PROTO_UDP;
6eda5e28
 
 	/* a little bit memory */
1708de3f
 	si = (struct socket_info *)pkg_malloc(sizeof(struct socket_info));
 	if(si == 0) {
 		LOG(L_ERR, "ERROR: new_sock_info: memory allocation error\n");
 		goto error;
 	}
6eda5e28
 
 	memset(si, 0, sizeof(struct socket_info));
1708de3f
 	si->address = ri.dst_ip;
 	si->socket = -1;
6eda5e28
 
1708de3f
 	/* set port & proto */
 	si->port_no = ri.dst_port;
6eda5e28
 
1708de3f
 	if(hg->ip_proto->data == IPPROTO_TCP)
 		si->proto = PROTO_TCP;
 	else if(hg->ip_proto->data == IPPROTO_UDP)
 		si->proto = PROTO_UDP;
6eda5e28
 
1708de3f
 	si->flags = 0;
 	si->addr_info_lst = 0;
6eda5e28
 
1708de3f
 	si->address_str.s = ip_addr2a(&si->address);
cc1142fc
 
6eda5e28
 	si->address_str.len = strlen(si->address_str.s);
 
1708de3f
 	si->port_no_str.s = int2str(si->port_no, &tmp_len);
 	si->port_no_str.len = tmp_len;
 	si->address_str.len = strlen(si->address_str.s);
6eda5e28
 
1708de3f
 	si->name.len = si->address_str.len;
 	si->name.s = si->address_str.s;
 	ri.bind_address = si;
 
 	if(payload != NULL) {
d4d7a8bb
 		/* and now receive message */
1708de3f
 		if(hg->proto_t->data == 5)
 			receive_logging_json_msg(payload, payload_len, hg, "rtcp_capture");
 		else if(hg->proto_t->data == 32)
 			receive_logging_json_msg(
 					payload, payload_len, hg, "report_capture");
 		else if(hg->proto_t->data == 99)
 			receive_logging_json_msg(
 					payload, payload_len, hg, "report_capture");
 		else if(hg->proto_t->data == 100)
 			receive_logging_json_msg(payload, payload_len, hg, "logs_capture");
 		else
 			receive_msg(payload, payload_len, &ri);
 	}
94f1d28e
 
6eda5e28
 done:
1708de3f
 	if(si)
 		pkg_free(si);
 	if(hg)
 		pkg_free(hg);
 
 	return 1;
6eda5e28
 
 error:
 
1708de3f
 	if(si)
 		pkg_free(si);
 	if(hg)
 		pkg_free(hg);
 
 	return -1;
6eda5e28
 }
 
 
1708de3f
 int hepv3_message_parse(char *buf, unsigned int len, sip_msg_t *msg)
 {
4e789387
 
 	union sockaddr_union from;
 	union sockaddr_union to;
 	char *tmp;
 	struct ip_addr dst_ip, src_ip;
1708de3f
 	struct socket_info *si = 0;
4e789387
 	int i;
 	char *payload = NULL;
 	unsigned int payload_len = 0;
1708de3f
 	struct hep_chunk *chunk;
 	struct hep_generic_recv *hg;
 	int totelem = 0;
 	int chunk_vendor = 0, chunk_type = 0, chunk_length = 0;
 	int total_length = 0;
 	int ret = 0;
 
 	hg = (struct hep_generic_recv *)pkg_malloc(sizeof(struct hep_generic_recv));
 	if(hg == NULL) {
 		LM_ERR("no more pkg memory left for hg\n");
 		return -1;
 	}
 
4e789387
 	memset(hg, 0, sizeof(struct hep_generic_recv));
 
1708de3f
 
 	memset(heptime, 0, sizeof(struct hep_timeinfo));
 
4e789387
 
 	/* HEADER */
1708de3f
 	hg->header = (hep_ctrl_t *)(buf);
4e789387
 
 	/*Packet size */
 	total_length = ntohs(hg->header->length);
 
 	dst_ip.af = 0;
1708de3f
 	src_ip.af = 0;
 
4e789387
 	payload = NULL;
 	correlation_id = NULL;
 	authkey = NULL;
 
1708de3f
 	i = sizeof(hep_ctrl_t);
 
4e789387
 	while(i < total_length) {
1708de3f
 
 		/*OUR TMP DATA */
 		tmp = buf + i;
 
 		chunk = (struct hep_chunk *)tmp;
 
 		chunk_vendor = ntohs(chunk->vendor_id);
 		chunk_type = ntohs(chunk->type_id);
 		chunk_length = ntohs(chunk->length);
 
 		/* if chunk_length */
 		if(chunk_length == 0) {
 			/* BAD LEN we drop this packet */
 			goto error;
 		}
 
 		/* SKIP not general Chunks */
 		if(chunk_vendor != 0) {
 			i += chunk_length;
 		} else {
 			switch(chunk_type) {
 
 				case 0:
 					goto error;
 					break;
 
 				case 1:
 					hg->ip_family = (hep_chunk_uint8_t *)(tmp);
 					i += chunk_length;
 					totelem++;
 					break;
 				case 2:
 					hg->ip_proto = (hep_chunk_uint8_t *)(tmp);
 					i += chunk_length;
 					totelem++;
 					break;
 				case 3:
 					hg->hep_src_ip4 = (hep_chunk_ip4_t *)(tmp);
 					i += chunk_length;
 					src_ip.af = AF_INET;
 					src_ip.len = 4;
 					src_ip.u.addr32[0] = hg->hep_src_ip4->data.s_addr;
 					totelem++;
 					break;
 				case 4:
 					hg->hep_dst_ip4 = (hep_chunk_ip4_t *)(tmp);
 					i += chunk_length;
 					dst_ip.af = AF_INET;
 					dst_ip.len = 4;
 					dst_ip.u.addr32[0] = hg->hep_dst_ip4->data.s_addr;
 					totelem++;
 
 					break;
 				case 5:
 					hg->hep_src_ip6 = (hep_chunk_ip6_t *)(tmp);
 					i += chunk_length;
 					src_ip.af = AF_INET6;
 					src_ip.len = 16;
 					memcpy(src_ip.u.addr, &hg->hep_src_ip6->data, 16);
 					totelem++;
 					break;
 				case 6:
 					hg->hep_dst_ip6 = (hep_chunk_ip6_t *)(tmp);
 					i += chunk_length;
 					dst_ip.af = AF_INET6;
 					dst_ip.len = 16;
 					memcpy(dst_ip.u.addr, &hg->hep_dst_ip6->data, 16);
 					totelem++;
 					break;
 
 				case 7:
 					hg->src_port = (hep_chunk_uint16_t *)(tmp);
 					msg->rcv.src_port = ntohs(hg->src_port->data);
 					i += chunk_length;
 					totelem++;
 					break;
 
 				case 8:
 					hg->dst_port = (hep_chunk_uint16_t *)(tmp);
 					msg->rcv.dst_port = ntohs(hg->dst_port->data);
 					i += chunk_length;
 					totelem++;
 					break;
 				case 9:
 					hg->time_sec = (hep_chunk_uint32_t *)(tmp);
 					heptime->tv_sec = ntohl(hg->time_sec->data);
 					i += chunk_length;
 					totelem++;
 					break;
 
 				case 10:
 					hg->time_usec = (hep_chunk_uint32_t *)(tmp);
 					heptime->tv_usec = ntohl(hg->time_usec->data);
 					i += chunk_length;
 					totelem++;
 					break;
 
 				case 11:
 					hg->proto_t = (hep_chunk_uint8_t *)(tmp);
 					i += chunk_length;
 					totelem++;
 					break;
 
 				case 12:
 					hg->capt_id = (hep_chunk_uint32_t *)(tmp);
 					i += chunk_length;
 					heptime->captid = ntohl(hg->capt_id->data);
 					totelem++;
 					break;
 
 				case 13:
 					hg->keep_tm = (hep_chunk_uint16_t *)(tmp);
 					i += chunk_length;
 					break;
 
 				case 14:
 					authkey = (char *)tmp + sizeof(hep_chunk_t);
 					i += chunk_length;
 					break;
 
 				case 15:
 					hg->payload_chunk = (hep_chunk_t *)(tmp);
 					payload = (char *)tmp + sizeof(hep_chunk_t);
 					payload_len = chunk_length - sizeof(hep_chunk_t);
 					i += chunk_length;
 					totelem++;
 					break;
 				case 17:
 
 					correlation_id = (char *)tmp + sizeof(hep_chunk_t);
 					i += chunk_length;
4e789387
 					break;
 
 
1708de3f
 				default:
 					i += chunk_length;
 					break;
 			}
 		}
 	}
4e789387
 
1708de3f
 	/* CHECK how much elements */
 	if(totelem < 9) {
 		LM_ERR("Not all elements [%d]\n", totelem);
 		goto done;
 	}
4e789387
 
1708de3f
 	if(dst_ip.af == 0 || src_ip.af == 0) {
 		LM_ERR("NO IP's set\n");
 		goto done;
 	}
4e789387
 
 
1708de3f
 	ip_addr2su(&to, &dst_ip, msg->rcv.dst_port);
 	ip_addr2su(&from, &src_ip, msg->rcv.src_port);
6e43bf84
 
1708de3f
 	msg->rcv.src_su = from;
 	su2ip_addr(&msg->rcv.src_ip, &from);
 	su2ip_addr(&msg->rcv.dst_ip, &to);
6e43bf84
 
1708de3f
 	if(hg->ip_proto->data == IPPROTO_TCP)
 		msg->rcv.proto = PROTO_TCP;
 	else if(hg->ip_proto->data == IPPROTO_UDP)
 		msg->rcv.proto = PROTO_UDP;
6e43bf84
 
1708de3f
 	if(payload != NULL)
270af568
 	{
1708de3f
 		ret = len - payload_len;
270af568
 		msg->buf = payload;
                 msg->len = payload_len;
 	}
6e43bf84
 
4e789387
 
 done:
 
1708de3f
 	//if(si) pkg_free(si);
 	if(hg)
 		pkg_free(hg);
 
 	return ret;
 
4e789387
 error:
 
1708de3f
 	if(si)
 		pkg_free(si);
 	if(hg)
 		pkg_free(hg);
 
 	return -1;
4e789387
 }
 
1708de3f
 int hepv2_message_parse(char *buf, unsigned int len, sip_msg_t *msg)
 {
4e789387
 
 	int hl;
1708de3f
 	struct hep_hdr *heph;
 	struct ip_addr dst_ip, src_ip;
 	char *hep_payload, *end, *hep_ip;
 	struct hep_iphdr *hepiph = NULL;
4e789387
 
1708de3f
 	struct hep_timehdr *heptime_tmp = NULL;
 	memset(heptime, 0, sizeof(struct hep_timeinfo));
 
 	struct hep_ip6hdr *hepip6h = NULL;
4e789387
 
 	correlation_id = NULL;
 	authkey = NULL;
 
1708de3f
 	hep_offset = 0;
 
4e789387
 	hl = hep_offset = sizeof(struct hep_hdr);
1708de3f
 	end = buf + len;
 	if(unlikely(len < hep_offset)) {
 		LOG(L_ERR, "ERROR: sipcapture:hep_msg_received len less than offset "
 				   "[%i] vs [%i]\n",
 				len, hep_offset);
 		return -1;
 	}
4e789387
 
 	/* hep_hdr */
1708de3f
 	heph = (struct hep_hdr *)buf;
4e789387
 
1708de3f
 	switch(heph->hp_f) {
 		case AF_INET:
 			hl += sizeof(struct hep_iphdr);
 			break;
4e789387
 		case AF_INET6:
1708de3f
 			hl += sizeof(struct hep_ip6hdr);
 			break;
4e789387
 		default:
1708de3f
 			LOG(L_ERR, "ERROR: sipcapture:hep_msg_received:  unsupported "
 					   "family [%d]\n",
 					heph->hp_f);
 			return -1;
4e789387
 	}
 
1708de3f
 	/* PROTO */
 	if(heph->hp_p == IPPROTO_UDP)
 		msg->rcv.proto = PROTO_UDP;
 	else if(heph->hp_p == IPPROTO_TCP)
 		msg->rcv.proto = PROTO_TCP;
 	else if(heph->hp_p == IPPROTO_IDP)
 		msg->rcv.proto = PROTO_TLS; /* fake protocol */
4e789387
 #ifdef USE_SCTP
1708de3f
 	else if(heph->hp_p == IPPROTO_SCTP)
 		msg->rcv.proto = PROTO_SCTP;
4e789387
 #endif
1708de3f
 	else {
 		LOG(L_ERR,
 				"ERROR: sipcapture:hep_msg_received: unknown protocol [%d]\n",
 				heph->hp_p);
 		msg->rcv.proto = PROTO_NONE;
4e789387
 	}
 
1708de3f
 	hep_ip = buf + sizeof(struct hep_hdr);
4e789387
 
1708de3f
 	if(unlikely(hep_ip > end)) {
 		LOG(L_ERR, "hep_ip is over buf+len\n");
 		return -1;
 	}
4e789387
 
1708de3f
 	switch(heph->hp_f) {
4e789387
 		case AF_INET:
1708de3f
 			hep_offset += sizeof(struct hep_iphdr);
 			hepiph = (struct hep_iphdr *)hep_ip;
 			break;
4e789387
 
 		case AF_INET6:
1708de3f
 			hep_offset += sizeof(struct hep_ip6hdr);
 			hepip6h = (struct hep_ip6hdr *)hep_ip;
 			break;
4e789387
 	}
 
 	/* VOIP payload */
1708de3f
 	hep_payload = buf + hep_offset;
4e789387
 
1708de3f
 	if(unlikely(hep_payload > end)) {
 		LOG(L_ERR, "hep_payload is over buf+len\n");
 		return -1;
4e789387
 	}
 
 	/* timming */
1708de3f
 	if(heph->hp_v == 2) {
 		hep_offset += sizeof(struct hep_timehdr);
 		heptime_tmp = (struct hep_timehdr *)hep_payload;
4e789387
 
1708de3f
 		heptime->tv_sec = to_le(heptime_tmp->tv_sec);
 		heptime->tv_usec = to_le(heptime_tmp->tv_usec);
 		heptime->captid = heptime_tmp->captid;
 	}
4e789387
 
 
 	/* fill ip from the packet to dst_ip && to */
1708de3f
 	switch(heph->hp_f) {
4e789387
 
 		case AF_INET:
1708de3f
 			dst_ip.af = src_ip.af = AF_INET;
 			dst_ip.len = src_ip.len = 4;
 			memcpy(&dst_ip.u.addr, &hepiph->hp_dst, 4);
 			memcpy(&src_ip.u.addr, &hepiph->hp_src, 4);
 			break;
4e789387
 
 		case AF_INET6:
1708de3f
 			dst_ip.af = src_ip.af = AF_INET6;
 			dst_ip.len = src_ip.len = 16;
 			memcpy(&dst_ip.u.addr, &hepip6h->hp6_dst, 16);
 			memcpy(&src_ip.u.addr, &hepip6h->hp6_src, 16);
 			break;
4e789387
 	}
6eda5e28
 
1708de3f
 	msg->rcv.src_ip = src_ip;
 	msg->rcv.src_port = ntohs(heph->hp_sport);
6eda5e28
 
1708de3f
 	msg->rcv.dst_ip = dst_ip;
 	msg->rcv.dst_port = ntohs(heph->hp_dport);
4e789387
 
 	return hep_offset;
 }
 
 
1708de3f
 int hepv3_get_chunk(struct sip_msg *msg, char *buf, unsigned int len,
 		int req_chunk, pv_param_t *param, pv_value_t *res)
 {
4e789387
 
 	str tmpstr;
 	char *tmp;
 	int i;
1708de3f
 	struct hep_chunk *chunk;
 	struct hep_generic_recv *hg;
 	int chunk_vendor = 0, chunk_type = 0, chunk_length = 0;
 	int total_length = 0;
 	int ret = 0;
 	static char ipstr[INET6_ADDRSTRLEN];
 
 	if(memcmp(buf, "\x48\x45\x50\x33", 4)
 			&& !memcmp(buf, "\x45\x45\x50\x31", 4)) {
 
 		LM_ERR("not hep 3 protocol");
 		pv_get_uintval(msg, param, res, -1);
 		return -1;
 	}
 
 	hg = (struct hep_generic_recv *)pkg_malloc(sizeof(struct hep_generic_recv));
 	if(hg == NULL) {
 		LM_ERR("no more pkg memory left for hg\n");
 		return -1;
 	}
 
4e789387
 	memset(hg, 0, sizeof(struct hep_generic_recv));
1708de3f
 
4e789387
 	/* HEADER */
1708de3f
 	hg->header = (hep_ctrl_t *)(buf);
4e789387
 
 	/*Packet size */
 	total_length = ntohs(hg->header->length);
 
1708de3f
 	i = sizeof(hep_ctrl_t);
 
4e789387
 	while(i < total_length) {
1708de3f
 
 		/*OUR TMP DATA */
 		tmp = buf + i;
 
 		chunk = (struct hep_chunk *)tmp;
 
 		chunk_vendor = ntohs(chunk->vendor_id);
 		chunk_type = ntohs(chunk->type_id);
 		chunk_length = ntohs(chunk->length);
 
 		/* if chunk_length */
 		if(chunk_length == 0) {
 			/* BAD LEN we drop this packet */
 			goto error;
 		}
 
 		/* SKIP not general Chunks */
 		if(chunk_vendor != 0) {
 			i += chunk_length;
 		} else {
 			if(chunk_type != req_chunk) {
 				i += chunk_length;
 				continue;
 			}
 
 			switch(chunk_type) {
 
 				case 0:
 					goto error;
 					break;
 
 				case 1:
 					hg->ip_family = (hep_chunk_uint8_t *)(tmp);
 					ret = pv_get_uintval(msg, param, res, hg->ip_family->data);
 					goto done;
 				case 2:
 					hg->ip_proto = (hep_chunk_uint8_t *)(tmp);
 					ret = pv_get_uintval(msg, param, res, hg->ip_proto->data);
 					goto done;
 				case 3:
 					hg->hep_src_ip4 = (hep_chunk_ip4_t *)(tmp);
 					inet_ntop(AF_INET, &(hg->hep_src_ip4->data), ipstr,
 							INET_ADDRSTRLEN);
 					tmpstr.s = ipstr;
 					tmpstr.len = strlen(ipstr);
 					ret = pv_get_strval(msg, param, res, &tmpstr);
 					goto done;
 				case 4:
 					hg->hep_dst_ip4 = (hep_chunk_ip4_t *)(tmp);
 					inet_ntop(AF_INET, &(hg->hep_dst_ip4->data), ipstr,
 							INET_ADDRSTRLEN);
 					tmpstr.s = ipstr;
 					tmpstr.len = strlen(ipstr);
 					ret = pv_get_strval(msg, param, res, &tmpstr);
 					goto done;
 				case 5:
 					hg->hep_src_ip6 = (hep_chunk_ip6_t *)(tmp);
 					inet_ntop(AF_INET6, &(hg->hep_src_ip6->data), ipstr,
 							INET6_ADDRSTRLEN);
 					tmpstr.s = ipstr;
 					tmpstr.len = strlen(ipstr);
 					ret = pv_get_strval(msg, param, res, &tmpstr);
 					goto done;
 				case 6:
 					hg->hep_dst_ip6 = (hep_chunk_ip6_t *)(tmp);
 					inet_ntop(AF_INET6, &(hg->hep_dst_ip6->data), ipstr,
 							INET6_ADDRSTRLEN);
 					tmpstr.s = ipstr;
 					tmpstr.len = strlen(ipstr);
 					ret = pv_get_strval(msg, param, res, &tmpstr);
 					goto done;
 				case 7:
 					hg->src_port = (hep_chunk_uint16_t *)(tmp);
 					ret = pv_get_uintval(
 							msg, param, res, ntohs(hg->src_port->data));
 					goto done;
 				case 8:
 					hg->dst_port = (hep_chunk_uint16_t *)(tmp);
 					ret = pv_get_uintval(
 							msg, param, res, ntohs(hg->dst_port->data));
 					goto done;
 				case 9:
 					hg->time_sec = (hep_chunk_uint32_t *)(tmp);
 					ret = pv_get_uintval(
 							msg, param, res, ntohl(hg->time_sec->data));
 					goto done;
 
 				case 10:
 					hg->time_usec = (hep_chunk_uint32_t *)(tmp);
 					ret = pv_get_uintval(
 							msg, param, res, ntohl(hg->time_usec->data));
 					goto done;
 
 				case 11:
 					hg->proto_t = (hep_chunk_uint8_t *)(tmp);
 					ret = pv_get_uintval(msg, param, res, hg->proto_t->data);
 					goto done;
 
 				case 12:
 					hg->capt_id = (hep_chunk_uint32_t *)(tmp);
 					ret = pv_get_uintval(
 							msg, param, res, ntohl(hg->capt_id->data));
 					goto done;
 
 				case 13:
 					hg->keep_tm = (hep_chunk_uint16_t *)(tmp);
 					ret = pv_get_uintval(
 							msg, param, res, ntohs(hg->keep_tm->data));
 					goto done;
 
 				case 14:
 					tmpstr.s = (char *)tmp + sizeof(hep_chunk_t);
 					tmpstr.len = chunk_length - sizeof(hep_chunk_t);
 					ret = pv_get_strval(msg, param, res, &tmpstr);
 					goto done;
 
 				case 15:
 					hg->payload_chunk = (hep_chunk_t *)(tmp);
 					tmpstr.s = (char *)tmp + sizeof(hep_chunk_t);
 					tmpstr.len = chunk_length - sizeof(hep_chunk_t);
 					ret = pv_get_strval(msg, param, res, &tmpstr);
 					goto done;
 				case 17:
 					tmpstr.s = (char *)tmp + sizeof(hep_chunk_t);
 					tmpstr.len = chunk_length - sizeof(hep_chunk_t);
 					ret = pv_get_strval(msg, param, res, &tmpstr);
 					goto done;
 				default:
 					ret = pv_get_uintval(msg, param, res, -1);
 					goto done;
 			}
 		}
 	}
4e789387
 
 done:
1708de3f
 
 	//if(si) pkg_free(si);
 	if(hg)
 		pkg_free(hg);
 	return ret;
 
4e789387
 error:
 
1708de3f
 	if(hg)
 		pkg_free(hg);
 	ret = pv_get_uintval(msg, param, res, -1);
 	return -1;
4e789387
 }