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; 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) 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: unknown 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 = 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; } 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; }
static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_info * dst2) { struct dest_info dst; struct socket_info *si; struct dest_info* dst_fin = NULL; struct proxy_l * p=NULL /* make gcc happy */; void* buffer = NULL; union sockaddr_union from_su; union sockaddr_union to_su; unsigned int len, buflen, proto; struct hep_hdr hdr; struct hep_iphdr hep_ipheader; struct hep_timehdr hep_time; struct timeval tvb; struct timezone tz; struct hep_ip6hdr hep_ip6header; if(body->s==NULL || body->len <= 0) return -1; if(dup_uri_str.s==0 || dup_uri==NULL) return 0; gettimeofday( &tvb, &tz ); /* message length */ len = body->len + sizeof(struct hep_ip6hdr) + sizeof(struct hep_hdr) + sizeof(struct hep_timehdr);; /* The packet is too big for us */ if (unlikely(len>BUF_SIZE)){ goto error; } /* Convert proto:ip:port to sockaddress union SRC IP */ if (pipport2su(from->s, &from_su, &proto)==-1 || (pipport2su(to->s, &to_su, &proto)==-1)) goto error; /* check if from and to are in the same family*/ if(from_su.s.sa_family != to_su.s.sa_family) { LM_ERR("interworking detected ?\n"); goto error; } if (!dst2){ init_dest_info(&dst); /* create a temporary proxy*/ dst.proto = PROTO_UDP; p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT, dst.proto); if (p==0) { LM_ERR("bad host name in uri\n"); goto error; } hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT); LM_DBG("setting up the socket_info\n"); dst_fin = &dst; } else { dst_fin = dst2; } if (force_send_sock_str.s) { LM_DBG("force_send_sock activated, grep for the sock_info\n"); si = grep_sock_info(&force_send_sock_uri->host, (force_send_sock_uri->port_no)?force_send_sock_uri->port_no:SIP_PORT, PROTO_UDP); if (!si) { LM_WARN("cannot grep socket info\n"); } else { LM_DBG("found socket while grep: [%.*s] [%.*s]\n", si->name.len, si->name.s, si->address_str.len, si->address_str.s); dst_fin->send_sock = si; } } if (dst_fin->send_sock == 0) { dst_fin->send_sock=get_send_socket(0, &dst_fin->to, dst_fin->proto); if (dst_fin->send_sock == 0) { LM_ERR("can't forward to af %d, proto %d no corresponding" " listening socket\n", dst_fin->to.s.sa_family, dst_fin->proto); goto error; } } /* Version && proto && length */ hdr.hp_l = sizeof(struct hep_hdr); hdr.hp_v = hep_version; hdr.hp_p = proto; /* AND the last */ if (from_su.s.sa_family==AF_INET){ /* prepare the hep headers */ hdr.hp_f = AF_INET; hdr.hp_sport = htons(from_su.sin.sin_port); hdr.hp_dport = htons(to_su.sin.sin_port); hep_ipheader.hp_src = from_su.sin.sin_addr; hep_ipheader.hp_dst = to_su.sin.sin_addr; len = sizeof(struct hep_iphdr); } else if (from_su.s.sa_family==AF_INET6){ /* prepare the hep6 headers */ hdr.hp_f = AF_INET6; hdr.hp_sport = htons(from_su.sin6.sin6_port); hdr.hp_dport = htons(to_su.sin6.sin6_port); hep_ip6header.hp6_src = from_su.sin6.sin6_addr; hep_ip6header.hp6_dst = to_su.sin6.sin6_addr; len = sizeof(struct hep_ip6hdr); } else { LM_ERR("Unsupported protocol family\n"); goto error;; } hdr.hp_l +=len; if (hep_version == 2){ len += sizeof(struct hep_timehdr); } len += sizeof(struct hep_hdr) + body->len; buffer = (void *)pkg_malloc(len+1); if (buffer==0){ LM_ERR("out of memory\n"); goto error; } /* Copy job */ memset(buffer, '\0', len+1); /* copy hep_hdr */ memcpy((void*)buffer, &hdr, sizeof(struct hep_hdr)); buflen = sizeof(struct hep_hdr); /* hep_ip_hdr */ if(from_su.s.sa_family==AF_INET) { memcpy((void*)buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr)); buflen += sizeof(struct hep_iphdr); } else { memcpy((void*)buffer+buflen, &hep_ip6header, sizeof(struct hep_ip6hdr)); buflen += sizeof(struct hep_ip6hdr); } if(hep_version == 2) { hep_time.tv_sec = to_le(tvb.tv_sec); hep_time.tv_usec = to_le(tvb.tv_usec); hep_time.captid = hep_capture_id; memcpy((void*)buffer+buflen, &hep_time, sizeof(struct hep_timehdr)); buflen += sizeof(struct hep_timehdr); } /* PAYLOAD */ memcpy((void*)(buffer + buflen) , (void*)body->s, body->len); buflen +=body->len; if (msg_send_buffer(dst_fin, buffer, buflen, 1)<0) { LM_ERR("cannot send hep duplicate message\n"); goto error; } if (p) { free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); } pkg_free(buffer); return 0; error: if(p) { free_proxy(p); /* frees only p content, not p itself */ pkg_free(p); } if(buffer) pkg_free(buffer); return -1; }