int ProtDep(proto_dep *ppdep) { int dep_n; if (prot_ins == -1) { LogPrintf(LV_ERROR, "%s can be used only in DissecRegist function", __FUNCTION__); return -1; } /* insert */ dep_n = prot_tbl[prot_ins].dep_num; prot_tbl[prot_ins].dep = xrealloc(prot_tbl[prot_ins].dep, sizeof(proto_dep)*(dep_n+1)); memset(&prot_tbl[prot_ins].dep[dep_n], 0, sizeof(proto_dep)); prot_tbl[prot_ins].dep[dep_n].name = xmalloc(strlen(ppdep->name)+1); strcpy(prot_tbl[prot_ins].dep[dep_n].name, ppdep->name); prot_tbl[prot_ins].dep[dep_n].attr = xmalloc(strlen(ppdep->attr)+1); strcpy(prot_tbl[prot_ins].dep[dep_n].attr, ppdep->attr); prot_tbl[prot_ins].dep[dep_n].type = ppdep->type; FTCopy(&(prot_tbl[prot_ins].dep[dep_n].val), &(ppdep->val), ppdep->type); if (ppdep->op == FT_OP_REX) { /* compile regular expression */ if (regcomp(&(prot_tbl[prot_ins].dep[dep_n].opd), ppdep->val.str, REG_ICASE) != 0) { LogPrintf(LV_ERROR, "Regular expression errror (%s) in %s dissector", ppdep->val.str, prot_tbl[prot_ins].name); return -1; } } prot_tbl[prot_ins].dep[dep_n].op = ppdep->op; prot_tbl[prot_ins].dep[dep_n].ProtCheck = ppdep->ProtCheck; if (ppdep->pktlim != 0) prot_tbl[prot_ins].dep[dep_n].pktlim = ppdep->pktlim; else prot_tbl[prot_ins].dep[dep_n].pktlim = USHRT_MAX; prot_tbl[prot_ins].dep_num++; return dep_n; }
static packet* RtpDissector(int flow_id) { struct in_addr ip_addr; struct in6_addr ipv6_addr; const pstack_f *udp, *ip; ftval port_src, port_dst, offset, phone; char ips_str[INET6_ADDRSTRLEN], ipd_str[INET6_ADDRSTRLEN]; rtp_priv *priv; packet *pkt; int rid, ret, gid, rtcp_fid; cmp_val rip, rport; char tmp_file_1[256]; char tmp_file_2[256]; char media_file_1[256]; char media_file_2[256]; char media_conv[256]; FILE *fp_pcap_1, *fp_pcap_2, *fp_pcap; struct pcap_file_header fh; struct pcappkt_hdr pckt_header; struct stat fsbuf; char cmd[1024]; size_t nwrt, wcnt; time_t tstart, tend; pei *ppei; pei_component *cmpn; bool aud1, aud2; unsigned short pkt_cnt; LogPrintf(LV_DEBUG, "RTP id: %d", flow_id); gid = FlowGrpId(flow_id); priv = DMemMalloc(sizeof(rtp_priv)); memset(priv, 0, sizeof(rtp_priv)); udp = FlowStack(flow_id); ip = ProtGetNxtFrame(udp); ProtGetAttr(udp, uport_src_id, &port_src); ProtGetAttr(udp, uport_dst_id, &port_dst); priv->port_s = port_src.uint16; priv->port_d = port_dst.uint16; priv->stack = udp; if (priv->port_s != port_dst.uint16) priv->port_diff = TRUE; priv->ipv6 = TRUE; if (ProtFrameProtocol(ip) == ip_id) priv->ipv6 = FALSE; if (priv->ipv6 == FALSE) { ProtGetAttr(ip, ip_src_id, &priv->ip_s); ProtGetAttr(ip, ip_dst_id, &priv->ip_d); ip_addr.s_addr = priv->ip_s.uint32; inet_ntop(AF_INET, &ip_addr, ips_str, INET6_ADDRSTRLEN); ip_addr.s_addr = priv->ip_d.uint32; inet_ntop(AF_INET, &ip_addr, ipd_str, INET6_ADDRSTRLEN); } else { ProtGetAttr(ip, ipv6_src_id, &priv->ip_s); ProtGetAttr(ip, ipv6_dst_id, &priv->ip_d); memcpy(ipv6_addr.s6_addr, priv->ip_s.ipv6, sizeof(priv->ip_s.ipv6)); inet_ntop(AF_INET6, &ipv6_addr, ips_str, INET6_ADDRSTRLEN); memcpy(ipv6_addr.s6_addr, priv->ip_d.ipv6, sizeof(priv->ip_d.ipv6)); inet_ntop(AF_INET6, &ipv6_addr, ipd_str, INET6_ADDRSTRLEN); } LogPrintf(LV_DEBUG, "\tSRC: %s:%d", ips_str, port_src.uint16); LogPrintf(LV_DEBUG, "\tDST: %s:%d", ipd_str, port_dst.uint16); /* RTCP flow search */ rid = -1; rtcp_fid = -1; if (rtcp_id != -1) { rid = GrpRuleNew(flow_id); if (priv->ipv6 == TRUE) { rip.prot = ipv6_id; rip.att = ipv6_dst_id; FTCopy(&rip.val, &priv->ip_d, FT_IPv6); } else { rip.prot = ip_id; rip.att = ip_dst_id; rip.val.uint32 = priv->ip_d.uint32; } rport.prot = udp_id; rport.att = uport_dst_id; port_dst.uint16++; rport.val.int16 = port_dst.uint16; GrpRule(rid, 2, &rip, &rport); if (priv->ipv6 == TRUE) { rip.att = ipv6_src_id; } else { rip.att = ip_src_id; } rport.att = uport_src_id; GrpRule(rid, 2, &rip, &rport); GrpRuleCmplt(rid); LogPrintf(LV_DEBUG, "Rule rtcp %i, port:%i", rid, port_dst.uint16); } /* put packets in the pcap files */ sprintf(tmp_file_1, "%s/%s/rtp_1_%d_%lu_%d.pcap", ProtTmpDir(), RTP_TMP_DIR, incr, time(NULL), port_src.uint16); sprintf(tmp_file_2, "%s/%s/rtp_2_%d_%lu_%d.pcap", ProtTmpDir(), RTP_TMP_DIR, incr, time(NULL), port_src.uint16); sprintf(media_conv, "%s/%s/rtp_%d_%lu_%d", ProtTmpDir(), RTP_TMP_DIR, incr, time(NULL), port_src.uint16); incr++; fp_pcap_1 = fopen(tmp_file_1, "w"); fp_pcap_2 = fopen(tmp_file_2, "w"); memset(&fh, 0, sizeof(struct pcap_file_header)); fh.magic = 0xA1B2C3D4; fh.version_major = PCAP_VERSION_MAJOR; fh.version_minor = PCAP_VERSION_MINOR; fh.snaplen = 65535; fh.linktype = DLT_RAW; if (fp_pcap_1 != NULL) { fwrite((char *)&fh, 1, sizeof(struct pcap_file_header), fp_pcap_1); } if (fp_pcap_2 != NULL) { fwrite((char *)&fh, 1, sizeof(struct pcap_file_header), fp_pcap_2); } /* first packet */ pkt_cnt = 0; pkt = FlowGetPkt(flow_id); /* start time */ if (pkt != NULL) { /* pei definition */ PeiNew(&ppei, rtp_id); PeiCapTime(ppei, pkt->cap_sec); PeiMarker(ppei, pkt->serial); PeiStackFlow(ppei, udp); tstart = pkt->cap_sec; } while (pkt != NULL) { pkt_cnt++; /* check if exit rtcp "stream" */ if (rid != -1) { rtcp_fid = GrpLink(gid); if (rtcp_fid != -1) { FlowSyncr(flow_id, FALSE); FlowSyncr(rtcp_fid, FALSE); PeiAddStkGrp(ppei, FlowStack(rtcp_fid)); rid = -1; } } tend = pkt->cap_sec; if (priv->ipv6) { ip = ProtStackSearchProt(pkt->stk, ipv6_id); ProtGetAttr(ip, ipv6_offset_id, &offset); wcnt = offset.uint32; } else { ip = ProtStackSearchProt(pkt->stk, ip_id); ProtGetAttr(ip, ip_offset_id, &offset); wcnt = offset.uint32; } pckt_header.caplen = pkt->raw_len - wcnt; pckt_header.len = pkt->raw_len - wcnt; pckt_header.tv_sec = pkt->cap_sec; pckt_header.tv_usec = pkt->cap_usec; if (RtpClientPkt(priv, pkt)) { fp_pcap = fp_pcap_1; } else { fp_pcap = fp_pcap_2; } if (fp_pcap != NULL) { wcnt = 0; do { nwrt = fwrite(((char *)&pckt_header)+wcnt, 1, sizeof(struct pcappkt_hdr)-wcnt, fp_pcap); if (nwrt != -1) wcnt += nwrt; else break; } while (wcnt != sizeof(struct pcappkt_hdr)); wcnt = offset.uint32; do { nwrt = fwrite(((char *)pkt->raw)+wcnt, 1, pkt->raw_len-wcnt, fp_pcap); if (nwrt != -1) wcnt += nwrt; else break; } while (wcnt != pkt->raw_len); } PktFree(pkt); pkt = FlowGetPkt(flow_id); } /* close file */ if (fp_pcap_1 != NULL) fclose(fp_pcap_1); if (fp_pcap_1 != NULL) fclose(fp_pcap_2); /* remove rtcp rule */ if (rid != -1) { rtcp_fid = GrpLink(gid); if (rtcp_fid != -1) { FlowSyncr(flow_id, FALSE); FlowSyncr(rtcp_fid, FALSE); PeiAddStkGrp(ppei, FlowStack(rtcp_fid)); rid = -1; } else { GrpRuleRm(rid); } } /* decode rtcp packet */ if (rtcp_fid != -1) { /* new priv data */ priv->port_s++; priv->port_d++; pkt = FlowGetPkt(rtcp_fid); while (pkt != NULL) { pkt = ProtDissecPkt(rtcp_id, pkt); if (pkt != NULL) { ProtGetAttr(pkt->stk, rtcp_phone_id, &phone); if (RtcpClientPkt(priv, pkt)) { strcpy(ipd_str, phone.str); } else { strcpy(ips_str, phone.str); } PktFree(pkt); } pkt = FlowGetPkt(rtcp_fid); } } /* audio decoding */ sprintf(cmd, "./videosnarf -i %s -o %s 2>/dev/null 1>/dev/null", tmp_file_1, tmp_file_1); ret = system(cmd); if (ret == -1) { LogPrintf(LV_WARNING, "videosnarf failed"); } else if (WEXITSTATUS(ret) != 0) { LogPrintf(LV_WARNING, "videosnarf crash"); } sprintf(cmd, "./videosnarf -i %s -o %s 2>/dev/null 1>/dev/null", tmp_file_2, tmp_file_2); ret = system(cmd); if (ret == -1) { LogPrintf(LV_WARNING, "videosnarf failed"); } else if (WEXITSTATUS(ret) != 0) { LogPrintf(LV_WARNING, "videosnarf crash"); } /* delete temporary files */ #if DEBUG_RM remove(tmp_file_1); remove(tmp_file_2); #endif /* media file check */ sprintf(media_file_1, "%s-media-1.wav", tmp_file_1); sprintf(media_file_2, "%s-media-1.wav", tmp_file_2); /* complete pei */ /* from */ PeiNewComponent(&cmpn, pei_from); PeiCompCapTime(cmpn, tstart); PeiCompAddStingBuff(cmpn, ipd_str); PeiAddComponent(ppei, cmpn); /* to */ PeiNewComponent(&cmpn, pei_to); PeiCompCapTime(cmpn, tstart); PeiCompAddStingBuff(cmpn, ips_str); PeiAddComponent(ppei, cmpn); /* duration */ sprintf(cmd, "%lu", tend-tstart); PeiNewComponent(&cmpn, pei_duration); PeiCompCapTime(cmpn, tstart); PeiCompAddStingBuff(cmpn, cmd); PeiAddComponent(ppei, cmpn); /* audio from */ aud2 = FALSE; if (stat(media_file_2, &fsbuf) == 0) { aud2 = TRUE; /* convert to be used with lame */ sprintf(tmp_file_2, "%s_2.wav", media_conv); sprintf(cmd, "sox %s -s %s 2>/dev/null 1>/dev/null", media_file_2, tmp_file_2); ret = system(cmd); #if DEBUG_RM remove(media_file_2); #endif /* mp3 conversion */ sprintf(media_file_2, "%s_2.mp3", media_conv); sprintf(cmd, "lame --quiet -h %s %s 2>/dev/null 1>/dev/null", tmp_file_2, media_file_2); ret = system(cmd); if (ret == -1) { LogPrintf(LV_WARNING, "lame failed"); } else if (WEXITSTATUS(ret) != 0) { LogPrintf(LV_WARNING, "lame crash (%i): %s", WEXITSTATUS(ret), cmd); } if (stat(media_file_2, &fsbuf) == 0) { PeiNewComponent(&cmpn, pei_audio_from); PeiCompCapTime(cmpn, tstart); PeiCompCapEndTime(cmpn, tend); PeiCompAddFile(cmpn, "audio_caller.mp3", media_file_2, fsbuf.st_size); PeiAddComponent(ppei, cmpn); } sprintf(media_file_2, "%s_stereo_2.wav", media_conv); sprintf(cmd, "sox %s -c 2 %s pan 1 2>/dev/null 1>/dev/null", tmp_file_2, media_file_2); ret = system(cmd); #if DEBUG_RM remove(tmp_file_2); #endif } /* audio to */ aud1 = FALSE; if (stat(media_file_1, &fsbuf) == 0) { aud1 = TRUE; /* convert to be used with lame */ sprintf(tmp_file_1, "%s_1.wav", media_conv); sprintf(cmd, "sox %s -s %s 2>/dev/null 1>/dev/null", media_file_1, tmp_file_1); ret = system(cmd); #if DEBUG_RM remove(media_file_1); #endif /* mp3 conversion */ sprintf(media_file_1, "%s_1.mp3", media_conv); sprintf(cmd, "lame --quiet -h %s %s 2>/dev/null 1>/dev/null", tmp_file_1, media_file_1); ret = system(cmd); if (ret == -1) { LogPrintf(LV_WARNING, "lame failed"); } else if (WEXITSTATUS(ret) != 0) { LogPrintf(LV_WARNING, "lame crash (%i): %s", WEXITSTATUS(ret), cmd); } if (stat(media_file_1, &fsbuf) == 0) { PeiNewComponent(&cmpn, pei_audio_to); PeiCompCapTime(cmpn, tstart); PeiCompCapEndTime(cmpn, tend); PeiCompAddFile(cmpn, "audio_called.mp3", media_file_1, fsbuf.st_size); PeiAddComponent(ppei, cmpn); } sprintf(media_file_1, "%s_stereo_1.wav", media_conv); sprintf(cmd, "sox %s -c 2 %s pan -1 2>/dev/null 1>/dev/null", tmp_file_1, media_file_1); ret = system(cmd); #if DEBUG_RM remove(tmp_file_1); #endif } /* mix audio */ if (aud2 || aud1) { /* mix two audio files */ sprintf(tmp_file_1, "%s_mix.wav", media_conv); sprintf(tmp_file_2, "%s_mix.mp3", media_conv); if (aud1 == FALSE) { sprintf(cmd, "sox %s %s 2>/dev/null 1>/dev/null", media_file_2, tmp_file_1); } else if (aud2 == FALSE) { sprintf(cmd, "sox %s %s 2>/dev/null 1>/dev/null", media_file_1, tmp_file_1); } else { sprintf(cmd, "sox -m %s %s -s %s 2>/dev/null 1>/dev/null", media_file_2, media_file_1, tmp_file_1); } ret = system(cmd); if (ret == -1) { LogPrintf(LV_WARNING, "sox failed"); } else if (WEXITSTATUS(ret) != 0) { LogPrintf(LV_WARNING, "sox mix crash: %s", cmd); } /* mp3 conversion */ sprintf(cmd, "lame --quiet -h %s %s 2>/dev/null 1>/dev/null", tmp_file_1, tmp_file_2); ret = system(cmd); /* delete temporary files */ #if DEBUG_RM remove(media_file_1); remove(media_file_2); remove(tmp_file_1); #endif if (stat(tmp_file_2, &fsbuf) == 0) { PeiNewComponent(&cmpn, pei_audio_mix); PeiCompCapTime(cmpn, tstart); PeiCompCapEndTime(cmpn, tend); PeiCompAddFile(cmpn, "audio_mix.mp3", tmp_file_2, fsbuf.st_size); PeiAddComponent(ppei, cmpn); } } /* insert pei */ PeiIns(ppei); /* free */ DMemFree(priv); LogPrintf(LV_DEBUG, "RTP... bye bye fid:%d (pkt:%i)", flow_id, pkt_cnt); return NULL; }