diff --git a/modules/sipcapture/examples/kamailio.cfg b/modules/sipcapture/examples/kamailio.cfg index 0c4df4ae2d1..3d42a78f47f 100644 --- a/modules/sipcapture/examples/kamailio.cfg +++ b/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; + } +} + diff --git a/modules/sipcapture/hep.c b/modules/sipcapture/hep.c index 1ca29043535..e6022e413df 100644 --- a/modules/sipcapture/hep.c +++ b/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 @@ int parsing_hepv3_message(char *buf, unsigned int len) { } +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(lenhp_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; +} diff --git a/modules/sipcapture/hep.h b/modules/sipcapture/hep.h index 3135b6b689d..82c75fd09ae 100644 --- a/modules/sipcapture/hep.h +++ b/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 */ diff --git a/modules/sipcapture/sipcapture.c b/modules/sipcapture/sipcapture.c index ebbbd989cf8..ddce49ca11d 100644 --- a/modules/sipcapture/sipcapture.c +++ b/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; +} +