Exemple #1
0
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;
}
Exemple #2
0
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;
}