static ndpi_protocol nDPIPacket(packet *pkt, struct ndpi_flow_struct *l7flow, struct ndpi_id_struct *l7src, struct ndpi_id_struct *l7dst, bool ipv6) { void *data; size_t offset, size; ftval voffset; const pstack_f *ip; unsigned long when; ndpi_protocol l7prot_id; if (ipv6) { ip = ProtStackSearchProt(pkt->stk, ipv6_id); ProtGetAttr(ip, ipv6_offset_id, &voffset); offset = voffset.uint32; data = pkt->raw + offset; size = pkt->raw_len - offset; } else { ip = ProtStackSearchProt(pkt->stk, ip_id); ProtGetAttr(ip, ip_offset_id, &voffset); offset = voffset.uint32; data = pkt->raw + offset; size = pkt->raw_len - offset; } when = pkt->cap_sec; when = when * NDPI_TICK_RES; when += pkt->cap_usec/1000; /* (1000000 / NDPI_TICK_RES) */; l7prot_id = ndpi_detection_process_packet(ndpi, l7flow, data, size, when, l7src, l7dst); return l7prot_id; }
static bool RtcpClientPkt(rtp_priv *priv, packet *pkt) { bool ret; ftval port, ip; enum ftype type; const pstack_f *udp; ret = FALSE; udp = ProtStackSearchProt(pkt->stk, udp_id); if (priv->port_diff == TRUE) { ProtGetAttr(udp, uport_src_id, &port); if (port.uint16 == priv->port_s) ret = TRUE; } else { if (priv->ipv6 == TRUE) { ProtGetAttr(ProtGetNxtFrame(udp), ipv6_src_id, &ip); type = FT_IPv6; } else { ProtGetAttr(ProtGetNxtFrame(udp), ip_src_id, &ip); type = FT_IPv4; } if (FTCmp(&priv->ip_s, &ip, type, FT_OP_EQ, NULL) == 0) ret = TRUE; } return ret; }
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; }