123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511 |
- /*
- * $Id$
- *
- * hep related functions
- *
- * Copyright (C) 2011-14 Alexandr Dubovikov <[email protected]>
- *
- * 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
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
- #include "../../sr_module.h"
- #include "../../dprint.h"
- #include "../../events.h"
- #include "../../ut.h"
- #include "../../ip_addr.h"
- #include "../../mem/mem.h"
- #include "../../mem/shm_mem.h"
- #include "../../lib/srdb1/db.h"
- #include "../../receive.h"
- #include "hep.h"
- #include "sipcapture.h"
- static int count = 0;
- struct hep_timehdr* heptime;
- /* 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);
- /**
- * HEP message
- */
- /* int hep_msg_received(char * buf, unsigned int len, struct receive_info * ri) */
- int hep_msg_received(void *data)
- {
- 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;
- }
- srevp = (void**)data;
- buf = (char *)srevp[0];
- len = (unsigned *)srevp[1];
- ri = (struct receive_info *)srevp[2];
- count++;
- struct hep_hdr *heph;
- /* hep_hdr */
- heph = (struct hep_hdr*) buf;
- /* Check version */
- if(heph->hp_v == 1 || heph->hp_v == 2) {
- return hepv2_received(buf, *len, ri);
- }
- else if(!memcmp(buf, "\x48\x45\x50\x33",4)) {
- return hepv3_received(buf, *len, ri);
- }
- 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;
- }
- }
- int hepv2_received(char *buf, unsigned int len, struct receive_info *ri){
- 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;
- 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) 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 */
- #ifdef USE_SCTP
- else if(heph->hp_p == IPPROTO_SCTP) ri->proto=PROTO_SCTP;
- #endif
- else {
- LOG(L_ERR, "ERROR: sipcapture:hep_msg_received: unknow protocol [%d]\n",heph->hp_p);
- ri->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 = heptime_tmp->tv_sec;
- heptime->tv_usec = 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;
- }
- ri->src_ip = src_ip;
- ri->src_port = ntohs(heph->hp_sport);
- ri->dst_ip = dst_ip;
- ri->dst_port = ntohs(heph->hp_dport);
- /* cut off the offset */
- /*
- * len -= offset;
- * p = buf + offset;
- * memmove(buf, p, BUF_SIZE+1);
- */
- hep_payload = buf + hep_offset;
- receive_msg(hep_payload,(unsigned int)(len - hep_offset), ri);
-
- return -1;
- }
- /**
- * HEP message
- */
- int hepv3_received(char *buf, unsigned int len, struct receive_info *ri)
- {
- if(!parsing_hepv3_message(buf, len)) {
- LM_ERR("couldn't parse hepv3 message\n");
- return -2;
- }
- return -1;
- }
- int parsing_hepv3_message(char *buf, unsigned int len) {
- union sockaddr_union from;
- union sockaddr_union to;
- struct receive_info ri;
- char *tmp;
- struct ip_addr dst_ip, src_ip;
- struct socket_info* si = 0;
- int tmp_len, 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;
- 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);
- ri.src_port = 0;
- ri.dst_port = 0;
- dst_ip.af = 0;
- src_ip.af = 0;
-
- payload = 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);
- 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);
- 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, 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;
- /* a little bit memory */
- 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;
- }
- memset(si, 0, sizeof(struct socket_info));
- si->address = ri.dst_ip;
- si->socket=-1;
- /* set port & proto */
- si->port_no = ri.dst_port;
- if(hg->ip_proto->data == IPPROTO_TCP) si->proto=PROTO_TCP;
- else if(hg->ip_proto->data == IPPROTO_UDP) si->proto=PROTO_UDP;
- si->flags=0;
- si->addr_info_lst=0;
- si->address_str.s = ip_addr2a(&si->address);;
- si->address_str.len = strlen(si->address_str.s);
- 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);
- si->name.len = si->address_str.len;
- si->name.s = si->address_str.s;
- ri.bind_address=si;
- /*TIME*/
- heptime->tv_sec = hg->time_sec->data;
- heptime->tv_usec = hg->time_usec->data;
- heptime->captid = ntohs(hg->capt_id->data);
-
- if(payload != NULL ) {
- /* and now recieve message */
- if (hg->proto_t->data == 5) receive_logging_json_msg(payload, payload_len, hg, "rtcp_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);
- }
- done:
- if(si) pkg_free(si);
- if(hg) pkg_free(hg);
- return 1;
-
- error:
- if(si) pkg_free(si);
- if(hg) pkg_free(hg);
-
- return -1;
-
- }
|