Browse Source

modules/sipcapture: added nonsip_hook support. Now $hep variable available

Alexandr Dubovikov 9 years ago
parent
commit
4e789387f8

+ 24 - 0
modules/sipcapture/examples/kamailio.cfg

@@ -97,6 +97,8 @@ modparam("sipcapture", "capture_on", 1)
 modparam("sipcapture", "hep_capture_on", 1)
 modparam("sipcapture", "insert_retries", 5)
 modparam("sipcapture", "insert_retry_timeout", 10)
+#new event sipcapture socket 
+modparam("sipcapture", "nonsip_hook", 1)
 #modparam("sipcapture", "capture_node", "homer01")
 
 #!ifdef WITH_HOMER_GEO
@@ -902,3 +904,25 @@ event_route[xhttp:request] {
         exit;
 }
 #!endif
+
+
+event_route[sipcapture:request] {
+
+        xlog("HEP Request!\n");
+        xlog("received sipcapture request from $si:$sp\r\n");
+        xlog("HEP VERSION $hep(version) request from $si:$sp\r\n");
+        xlog("HEP CHUNK Source IP $hep(0x002) request from $si:$sp\r\n");
+	#Is it SIP ?
+	if($hep(0x00b) == 1){
+
+		#Do parsing internal
+		return 1;
+	}
+	else 
+	{
+		#If report lets proceed here with payload
+	        xlog("HEP CHUNK PAYLOAD $hep(0x00f) request from $si:$sp\r\n");
+        	return 0;   
+	}
+}
+

+ 528 - 0
modules/sipcapture/hep.c

@@ -44,6 +44,7 @@ struct hep_timehdr* heptime;
 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);
+
 /**
  * HEP message
  */
@@ -514,6 +515,533 @@ error:
 }
 
 
+int hepv3_message_parse(char *buf, unsigned int len, sip_msg_t* msg) {
+
+	union sockaddr_union from;
+	union sockaddr_union to;
+	char *tmp;
+	struct ip_addr dst_ip, src_ip;
+	struct socket_info* si = 0;
+	int i;
+	char *payload = NULL;
+	unsigned int payload_len = 0;
+        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;
+        }
+	                                                 		
+	memset(hg, 0, sizeof(struct hep_generic_recv));
+
+	
+        memset(heptime, 0, sizeof(struct hep_timehdr));	
+	        
+
+	/* HEADER */
+	hg->header  = (hep_ctrl_t *) (buf);
+
+	/*Packet size */
+	total_length = ntohs(hg->header->length);
+
+	dst_ip.af = 0;
+        src_ip.af = 0;
+                	        
+	payload = NULL;
+	correlation_id = NULL;
+	authkey = NULL;
+
+	i = sizeof(hep_ctrl_t);	        
+	        
+	while(i < total_length) {
+                
+	        /*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);
+                                        hg->time_sec->data = ntohl(hg->time_sec->data);
+                                        heptime->tv_sec = hg->time_sec->data;
+                                        i+=chunk_length;
+                                        totelem++;
+                                        break;                                                     
+                                                     
+                                case 10:
+                                        hg->time_usec  = (hep_chunk_uint32_t *) (tmp);
+                                        hg->time_usec->data = ntohl(hg->time_usec->data);
+                                        heptime->tv_usec = 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 = ntohs(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;                                                                            
+					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, msg->rcv.dst_port);
+        ip_addr2su(&from, &src_ip, msg->rcv.src_port);
+                        
+        msg->rcv.src_su=from;
+        su2ip_addr(&msg->rcv.src_ip, &from);
+        su2ip_addr(&msg->rcv.dst_ip, &to);
+
+	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;
+
+        if(payload != NULL) ret = len - payload_len;
+
+	/*TIME*/ 
+        heptime->tv_sec = hg->time_sec->data;
+        heptime->tv_usec = hg->time_usec->data;
+        heptime->captid = ntohs(hg->capt_id->data);
+
+done:
+          
+        //if(si) pkg_free(si);
+        if(hg) pkg_free(hg);                     
+
+        return ret;
+        
+error:
+
+        if(si) pkg_free(si);
+        if(hg) pkg_free(hg);
+                
+        return -1;           
+        
+}
+
+int hepv2_message_parse(char *buf, unsigned int len, sip_msg_t* msg) {
+
+	int hl;
+        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_timehdr));
+
+        struct hep_ip6hdr *hepip6h = NULL;
+            	        
+	correlation_id = NULL;
+	authkey = NULL;
+
+	hep_offset = 0; 
+	
+	hl = hep_offset = sizeof(struct hep_hdr);
+        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;
+        }
+
+	/* hep_hdr */
+        heph = (struct hep_hdr*) buf;
+
+        switch(heph->hp_f){
+        	case AF_INET:
+                	hl += sizeof(struct hep_iphdr);
+                        break;
+		case AF_INET6:
+                	hl += sizeof(struct hep_ip6hdr);
+                        break;
+		default:
+                        LOG(L_ERR, "ERROR: sipcapture:hep_msg_received:  unsupported family [%d]\n", heph->hp_f);
+                        return -1;
+	}
+
+        /* 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 */
+#ifdef USE_SCTP
+        else if(heph->hp_p == IPPROTO_SCTP) msg->rcv.proto=PROTO_SCTP;
+#endif
+        else {
+        	LOG(L_ERR, "ERROR: sipcapture:hep_msg_received: unknown protocol [%d]\n",heph->hp_p);
+                msg->rcv.proto = PROTO_NONE;
+	}
+
+        hep_ip = buf + sizeof(struct hep_hdr);
+
+        if (unlikely(hep_ip>end)){
+                LOG(L_ERR,"hep_ip is over buf+len\n");
+                return -1;
+        }
+
+	switch(heph->hp_f){
+		case AF_INET:
+                	hep_offset+=sizeof(struct hep_iphdr);
+                        hepiph = (struct hep_iphdr*) hep_ip;
+                        break;
+
+		case AF_INET6:
+                	hep_offset+=sizeof(struct hep_ip6hdr);
+                        hepip6h = (struct hep_ip6hdr*) hep_ip;
+                        break;
+
+	}
+
+	/* VOIP payload */
+        hep_payload = buf + hep_offset;
+
+        if (unlikely(hep_payload>end)){
+        	LOG(L_ERR,"hep_payload is over buf+len\n");
+                return -1;
+	}
+
+	/* timming */
+        if(heph->hp_v == 2) {
+                hep_offset+=sizeof(struct hep_timehdr);
+                heptime_tmp = (struct hep_timehdr*) hep_payload;
+
+                heptime->tv_sec = to_le(heptime_tmp->tv_sec);
+                heptime->tv_usec = to_le(heptime_tmp->tv_usec);
+                heptime->captid = heptime_tmp->captid;
+        }
+
+
+	/* fill ip from the packet to dst_ip && to */
+        switch(heph->hp_f){
+
+		case AF_INET:
+                	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;
+
+		case AF_INET6:
+                	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;
+
+	}
 
+        msg->rcv.src_ip = src_ip;
+        msg->rcv.src_port = ntohs(heph->hp_sport);
 
+        msg->rcv.dst_ip = dst_ip;
+        msg->rcv.dst_port = ntohs(heph->hp_dport);
+
+	return hep_offset;
+}
+
+
+int hepv3_get_chunk(struct sip_msg *msg, char *buf, unsigned int len, int req_chunk, pv_param_t *param, pv_value_t *res) {
+
+	str tmpstr;
+	char *tmp;
+	int i;
+        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;
+        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;
+        }
+	                                                 		
+	memset(hg, 0, sizeof(struct hep_generic_recv));
+	
+	/* HEADER */
+	hg->header  = (hep_ctrl_t *) (buf);
+
+	/*Packet size */
+	total_length = ntohs(hg->header->length);
+
+	i = sizeof(hep_ctrl_t);	        
+	        
+	while(i < total_length) {
+                
+	        /*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));
+                                        break;
+                                case 8:
+                                        hg->dst_port  = (hep_chunk_uint16_t *) (tmp);
+                                        ret = pv_get_uintval(msg, param, res, ntohs(hg->dst_port->data));
+                                        break;
+                                case 9:
+                                        hg->time_sec  = (hep_chunk_uint32_t *) (tmp);
+                                        hg->time_sec->data = ntohl(hg->time_sec->data);
+                                        ret = pv_get_uintval(msg, param, res, hg->time_sec->data);
+                                        goto done;
+                                                     
+                                case 10:
+                                        hg->time_usec  = (hep_chunk_uint32_t *) (tmp);
+                                        hg->time_usec->data = ntohl(hg->time_usec->data);
+                                        ret = pv_get_uintval(msg, param, res, 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, ntohs(hg->capt_id->data));
+                                        goto done;
+
+                                case 13:
+                                        hg->keep_tm  = (hep_chunk_uint16_t *) (tmp);
+                                        ret = pv_get_uintval(msg, param, res, 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;                                        
+                        }                                        
+                }
+        }	                                                                                                          
+
+done:
+          
+        //if(si) pkg_free(si);
+        if(hg) pkg_free(hg);                             
+        return ret;
+        
+error:
+
+        if(hg) pkg_free(hg);
+        ret = pv_get_uintval(msg, param, res, -1);                
+        return -1;                   
+}
 

+ 6 - 0
modules/sipcapture/hep.h

@@ -47,6 +47,12 @@ extern char *correlation_id;
 /* int hep_msg_received(char * buf, unsigned int len, struct receive_info * ri);*/
 int hep_msg_received(void *data);
 
+/* new method for events */
+int hepv3_message_parse(char *buf, unsigned int len, sip_msg_t* msg);
+int hepv2_message_parse(char *buf, unsigned int len, sip_msg_t* msg);
+int hepv3_get_chunk(struct sip_msg *msg, char *buf, unsigned int len, int req_chunk, pv_param_t *param, pv_value_t *res);
+
+
 
 struct hep_hdr{
     u_int8_t hp_v;            /* version */

+ 217 - 10
modules/sipcapture/sipcapture.c

@@ -137,6 +137,9 @@ static int sipcapture_fixup(void** param, int param_no);
 static int reportcapture_fixup(void** param, int param_no);
 static int float2int_fixup(void** param, int param_no);
 
+static int pv_get_hep(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
+static int pv_parse_hep_name (pv_spec_p sp, str *in);
+
 static int sip_capture(struct sip_msg *msg, str *dtable,  _capture_mode_data_t *cm_data);
 static int report_capture(struct sip_msg *msg, str *_table, str* _corr, str *_data);
 static int w_sip_capture(struct sip_msg* _m, char* _table, _capture_mode_data_t * _cm_data, char* s2);
@@ -150,11 +153,12 @@ int init_rawsock_children(void);
 int extract_host_port(void);
 int raw_capture_socket(struct ip_addr* ip, str* iface, int port_start, int port_end, int proto);
 int raw_capture_rcv_loop(int rsock, int port1, int port2, int ipip);
+static int nosip_hep_msg(void *data);
+static struct mi_root* sip_capture_mi(struct mi_root* cmd, void* param );
 
+static int hep_version(struct sip_msg *msg);
 
 
-static struct mi_root* sip_capture_mi(struct mi_root* cmd, void* param );
-
 static str db_url		= str_init(DEFAULT_DB_URL);
 static str table_name		= str_init("sip_capture");
 static str hash_source		= str_init("call_id");
@@ -229,6 +233,10 @@ int n_callid_aleg_headers = 0;
 
 struct ifreq ifr; 	/* interface structure */
 
+/* by default nonsip_hook is inactive */
+static int nonsip_hook = 0;
+static int hep_route_no=-1;
+
 static int sc_topoh_unmask = 0;
 static topoh_api_t thb = {0};
 
@@ -269,12 +277,19 @@ static cmd_export_t cmds[] = {
 	{"sip_capture", (cmd_function)w_sip_capture, 2, sipcapture_fixup, 0, ANY_ROUTE },
 	{"report_capture", (cmd_function)w_report_capture, 1, reportcapture_fixup, 0, ANY_ROUTE },
 	{"report_capture", (cmd_function)w_report_capture, 2, reportcapture_fixup, 0, ANY_ROUTE },
-	{"report_capture", (cmd_function)w_report_capture, 3, reportcapture_fixup, 0, ANY_ROUTE },
+	{"report_capture", (cmd_function)w_report_capture, 3, reportcapture_fixup, 0, ANY_ROUTE },	
 	{"float2int", (cmd_function)w_float2int, 2, float2int_fixup, 0, ANY_ROUTE },
 	{0, 0, 0, 0, 0, 0}
 };
 
 
+static pv_export_t mod_pvs[] = {
+        { {"hep", sizeof("hep")-1}, PVT_OTHER, pv_get_hep, 0,
+        pv_parse_hep_name, 0, 0, 0 },
+        { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
+};
+                                
+
 int capture_mode_param(modparam_t type, void *val);
 
 /*! \brief
@@ -342,7 +357,8 @@ static param_export_t params[] = {
 	{"insert_retries",   		INT_PARAM, &insert_retries },
 	{"insert_retry_timeout",	INT_PARAM, &insert_retry_timeout },
 	{"table_time_sufix",		PARAM_STR, &table_time_sufix },
-	{"topoh_unamsk",			PARAM_INT, &sc_topoh_unmask },
+	{"topoh_unamsk",		PARAM_INT, &sc_topoh_unmask },
+	{"nonsip_hook",			PARAM_INT, &nonsip_hook },
 	{0, 0, 0}
 };
 
@@ -383,7 +399,7 @@ struct module_exports exports = {
 	0,          /*!< exported statistics */
 #endif
 	mi_cmds,    /*!< exported MI functions */
-	0,          /*!< exported pseudo-variables */
+	mod_pvs,          /*!< exported pseudo-variables */
 	0,          /*!< extra processes */
 	mod_init,   /*!< module initialization function */
 	0,          /*!< response function */
@@ -767,6 +783,7 @@ static int mod_init(void)
 
 #ifdef STATISTICS
 
+	int route_no;
 	c = capture_modes_root;
 	while (c){
 		cnt++;
@@ -824,10 +841,36 @@ static int mod_init(void)
 
 	*capture_on_flag = capture_on;
 
-	/* register DGRAM event */
-	if(sr_event_register_cb(SREV_NET_DGRAM_IN, hep_msg_received) < 0) {
-		LM_ERR("failed to register SREV_NET_DGRAM_IN event\n");
-		return -1;
+	if(nonsip_hook)
+	{	        
+        	route_no=route_get(&event_rt, "sipcapture:request");
+	        if (route_no==-1)
+        	{
+                	LM_ERR("failed to find event_route[sipcapture:request]\n");
+	                return -1;
+        	}
+        	
+	        if (event_rt.rlist[route_no]==0)
+        	{
+                	LM_ERR("event_route[sipcapture:request] is empty\n");
+	                return -1;
+        	}
+
+	        hep_route_no=route_no;
+	
+		if(sr_event_register_cb(SREV_RCV_NOSIP, nosip_hep_msg) < 0) 
+		{
+			LM_ERR("failed to register SREV_RCV_NOSIP event\n");
+		  	return -1;		  	                         
+		}
+	}
+	else 
+	{
+		/* register DGRAM event */
+		if(sr_event_register_cb(SREV_NET_DGRAM_IN, hep_msg_received) < 0) {
+			LM_ERR("failed to register SREV_NET_DGRAM_IN event\n");
+			return -1;
+		}
 	}
 
 	if(ipip_capture_on && moni_capture_on) {
@@ -1050,7 +1093,6 @@ static int w_report_capture(struct sip_msg* _m, char* _table, char* _corr, char*
 	if(data.len > 0 && !strncmp(data.s, "report_capture", data.len)) data.len = 0;
 
 	return report_capture(_m, (table.len>0)?&table:NULL, (corr.len>0)?&corr:NULL ,(data.len>0)?&data:NULL );
-
 }
 
 
@@ -2614,3 +2656,168 @@ static int sipcapture_parse_aleg_callid_headers() {
 
 	return n_callid_aleg_headers;
 }
+
+
+static int nosip_hep_msg(void *data)
+{
+        sip_msg_t* msg;
+        char *buf;
+        unsigned int len = 0;
+        struct run_act_ctx ra_ctx;
+        int ret = 0;
+
+        msg = (sip_msg_t*)data;
+        
+        struct hep_hdr *heph;
+        
+        buf = msg->buf;
+        len = msg->len;
+        
+        /* first send to route */
+        init_run_actions_ctx(&ra_ctx);
+        ret = run_actions(&ra_ctx, event_rt.rlist[hep_route_no], msg);
+
+        if(ret != 1) return ret;
+
+        /* hep_hdr */
+        heph = (struct hep_hdr*) msg->buf;
+        
+	if(heph->hp_v == 1 || heph->hp_v == 2)  {
+
+		LOG(L_ERR, "ERROR: HEP v 1/2: v:[%d] l:[%d]\n",heph->hp_v, heph->hp_l);
+		if((len = hepv2_message_parse(buf, len, msg)) < 0) 
+		{		
+   		     LOG(L_ERR, "ERROR: during hepv2 parsing :[%d]\n", len);
+   		     return 0;
+                }
+                
+                buf = msg->buf+len;
+		len = msg->len - len;
+				
+		msg->buf = buf;
+                msg->len = len;
+        }
+        else if(!memcmp(msg->buf, "\x48\x45\x50\x33",4) || !memcmp(msg->buf, "\x45\x45\x50\x31",4)) {
+
+                if((len = hepv3_message_parse(buf, len, msg)) < 0) 
+		{		
+   		     LOG(L_ERR, "ERROR: during hepv3 parsing :[%d]\n", len);
+   		     return 0;
+                }
+                
+                buf = msg->buf+len;
+                len = msg->len - len;
+                
+                msg->buf = buf;
+                msg->len = len;
+        }
+        else {
+
+                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;
+        }
+
+        if (parse_msg(buf, len, msg)!=0) {
+             LOG(L_ERR, "couldn't parse sip message\n");               
+             return -1;
+        }
+        
+        return ret;
+}
+
+
+static int hep_version(struct sip_msg *msg)
+{
+        struct hep_hdr *heph;
+        /* hep_hdr */
+        heph = (struct hep_hdr*) msg->buf;
+        
+	if(heph->hp_v == 1 || heph->hp_v == 2) return heph->hp_v;
+        else if(!memcmp(msg->buf, "\x48\x45\x50\x33",4) || !memcmp(msg->buf, "\x45\x45\x50\x31",4)) return 3;
+                
+        return -1;
+}
+
+static int fix_hex_int(str *s)
+{
+
+	unsigned int retval=0;
+
+	if (!s->len || !s->s)
+		goto error;
+
+	if (s->len > 2)
+		if ((s->s[0] == '0') && ((s->s[1]|0x20) == 'x')) {
+			if (hexstr2int(s->s+2, s->len-2, &retval)!=0)
+				goto error;
+			else
+				return retval;
+		}
+
+	if (str2int(s, (unsigned int*)&retval)<0)
+		goto error;
+
+
+	return retval;
+
+error:
+	LM_ERR("Invalid value for hex: <%*s>!\n", s->len, s->s);
+	return -1;
+
+}
+
+
+static int pv_parse_hep_name (pv_spec_p sp, str *in)
+{
+	int valchunk = 0;
+
+	if(sp==NULL || in==NULL || in->len<=0)
+		return -1;
+
+        LM_ERR("REQUEST, PRE, %.*s", in->len, in->s);
+
+	switch(in->len)
+	{
+		case 5:
+		{
+			if((valchunk = fix_hex_int(in)) > 0) sp->pvp.pvn.u.isname.name.n = valchunk;
+			else goto error;
+		}
+		break;
+		case 7:
+		{
+		        if(!strncmp(in->s, "version", 7)) sp->pvp.pvn.u.isname.name.n = 0;
+			else goto error;
+		}
+		break;
+		default:
+			goto error;
+	}
+	sp->pvp.pvn.type = PV_NAME_INTSTR;
+	sp->pvp.pvn.u.isname.type = 0;
+
+	return 0;
+
+error:
+	LM_ERR("unknown hep name %.*s\n", in->len, in->s);
+	return -1;
+}
+
+
+static int pv_get_hep(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
+{
+	if(param==NULL) return -1;
+
+	switch(param->pvn.u.isname.name.n)
+	{
+		case 0:
+			return pv_get_uintval(msg, param, res, hep_version(msg));						
+		case 1: 
+		        return pv_get_uintval(msg, param, res, hep_version(msg));						
+		default:
+		        return  hepv3_get_chunk(msg, msg->buf, msg->len, param->pvn.u.isname.name.n, param, res);
+	}
+	return 0;
+}
+