コード例 #1
0
ファイル: tcp_analysis.c プロジェクト: M0Rf30/xplico
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;
}
コード例 #2
0
ファイル: rtp.c プロジェクト: shineit/wifimanage
static bool RtpClientPkt(rtp_priv *priv, packet *pkt)
{
    bool ret;
    ftval port, ip;
    enum ftype type;
    
    ret = FALSE;
    if (priv->port_diff == TRUE) {
        ProtGetAttr(pkt->stk, uport_src_id, &port);
        if (port.uint16 == priv->port_s)
            ret = TRUE;
    }
    else {
        if (priv->ipv6 == TRUE) {
            ProtGetAttr(ProtGetNxtFrame(pkt->stk), ipv6_src_id, &ip);
            type = FT_IPv6;
        }
        else {
            ProtGetAttr(ProtGetNxtFrame(pkt->stk), ip_src_id, &ip);
            type = FT_IPv4;
        }
        if (FTCmp(&priv->ip_s, &ip, type, FT_OP_EQ, NULL) == 0)
            ret = TRUE;
    }
    
    return ret;
}
コード例 #3
0
ファイル: tcp_analysis.c プロジェクト: M0Rf30/xplico
static int TcpCaDisFlowSetUp(tca_flow *ifw, packet *pkt)
{
    ftval lost;
    bool clnt;
    
    if (pkt != NULL) {
        clnt = TcpCaClientPkt(&ifw->priv, pkt);
        ProtGetAttr(pkt->stk, lost_id, &lost);
        if (lost.uint8 == FALSE) {
            /* create pei */
            PeiNew(&ifw->ppei, tcp_ca_id);
            PeiCapTime(ifw->ppei, pkt->cap_sec);
            PeiMarker(ifw->ppei, pkt->serial);
            PeiStackFlow(ifw->ppei, FlowStack(ifw->flow_id));
            ifw->cap_sec = pkt->cap_sec;
            ifw->end_cap = pkt->cap_sec;
            TcpCaDisFlow(ifw, pkt);
            return 0;
        }
        else {
            ifw->first_lost = TRUE;
            if (clnt) {
                ifw->priv.blost_sent += pkt->len;
                if (ifw->priv.blost_sent == 0)
                    ifw->priv.blost_sent = 1;
            }
            else {
                ifw->priv.blost_receiv += pkt->len;
                if (ifw->priv.blost_receiv == 0)
                    ifw->priv.blost_receiv = 1;
            }
        }
        PktFree(pkt);
    }
    
    return 1;
}
コード例 #4
0
ファイル: rtp.c プロジェクト: shineit/wifimanage
static bool RtpCheck(int flow_id)
{
    const pstack_f *ip;
    packet *pkt;
    bool ret;
    ftval ips, ipx, port;
    bool ipv4, cmp;
    int pt_1, pt_2;
    unsigned int ssrc_1, ssrc_2;
    int cnt, ecnt;
    rtp_hdr *rtp;
    unsigned short min_size;

    if (FlowPktNum(flow_id) < RTP_PKT_LIMIT && FlowIsClose(flow_id) == FALSE) {
        return FALSE;
    }

    ipv4 = FALSE;
    ret = FALSE;
    cnt = ecnt = 0;

    pkt = FlowGetPktCp(flow_id);
    if (pkt != NULL) {
        /* check port */
        ProtGetAttr(pkt->stk, uport_dst_id, &port);
        if (port.uint16 < 1024) {
            PktFree(pkt);
            return FALSE;
        }
        ProtGetAttr(pkt->stk, uport_src_id, &port);
        if (port.uint16 < 1024) {
            PktFree(pkt);
            return FALSE;
        }
        /* check ip */
        ip = ProtGetNxtFrame(pkt->stk);
        if (ProtFrameProtocol(ip) == ip_id)
            ipv4 = TRUE;
        if (ipv4 == TRUE)
            ProtGetAttr(ip, ip_src_id, &ips);
        else
            ProtGetAttr(ip, ipv6_src_id, &ips);
        while (pkt->len == 0) {
            PktFree(pkt);
            pkt = FlowGetPktCp(flow_id);
            if (pkt == NULL)
                break;
        }
    }
    if (pkt != NULL) {
        pt_1 = pt_2 = -1;
        do {
            if (pkt->len > sizeof(rtp_hdr)) {
                rtp = (rtp_hdr *)pkt->data;
                if (rtp->version != 2) {
                    cnt = 0;
                    ecnt++;
                }
                else {
                    ip = ProtGetNxtFrame(pkt->stk);
                    if (ipv4 == TRUE) {
                        ProtGetAttr(ip, ip_src_id, &ipx);
                        cmp = FTCmp(&ips, &ipx, FT_IPv4, FT_OP_EQ, NULL);
                        if (cmp) {
                            if (pt_1 == -1) {
                                pt_1 = rtp->pt;
                                ssrc_1 = rtp->ssrc;
                            }
                            else if (pt_1 != rtp->pt || ssrc_1 != rtp->ssrc)
                                break;
                        }
                        else {
                            if (pt_2 == -1) {
                                pt_2 = rtp->pt;
                                ssrc_2 = rtp->ssrc;
                            }
                            else if (pt_2 != rtp->pt || ssrc_2 != rtp->ssrc)
                                break;
                        }
                        /* check size */
                        if (rtp->cc != 0) {
                            min_size = rtp->cc * 4; /* every CSRC has 4 byte */
                            min_size += sizeof(rtp_hdr);
                            if (pkt->len < min_size)
                                break;
                        }
                    }
                    else {
                        ProtGetAttr(ip, ipv6_src_id, &ipx);
                        cmp = FTCmp(&ips, &ipx, FT_IPv6, FT_OP_EQ, NULL);
                        if (cmp) {
                            if (pt_1 == -1) {
                                pt_1 = rtp->pt;
                            ssrc_1 = rtp->ssrc;
                            }
                            else if (pt_1 != rtp->pt || ssrc_1 != rtp->ssrc)
                                break;
                        }
                        else {
                            if (pt_2 == -1) {
                                pt_2 = rtp->pt;
                                ssrc_2 = rtp->ssrc;
                            }
                            else if (pt_2 != rtp->pt || ssrc_2 != rtp->ssrc)
                                break;
                        }
                        /* check size */
                        if (rtp->cc != 0) {
                            min_size = rtp->cc * 4; /* every CSRC has 4 byte */
                            min_size += sizeof(rtp_hdr);
                            if (pkt->len < min_size)
                                break;
                        }
                    }
                    cnt++;
                }
            }
            else {
                cnt = 0;
                ecnt++;
            }
            PktFree(pkt);
            pkt = FlowGetPktCp(flow_id);
        } while (ecnt != RTP_PKT_ERR_CHECK && cnt != RTP_PKT_CHECK && pkt != NULL);
    }
    
    if (pkt != NULL) {
        PktFree(pkt);
        pkt = NULL;
    }
    
    if (cnt == RTP_PKT_CHECK) {
        ret = TRUE;
    }

    return ret;
}
コード例 #5
0
ファイル: rtp.c プロジェクト: shineit/wifimanage
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;
}
コード例 #6
0
ファイル: disp_manipula.c プロジェクト: Cbrdiv/xplico
/* IMPORTANT!: if valgrind notifies a warning as "write(buf) points to uninitialised byte" it is not a bug, all attributes are union and the function ProtInsAttr copy all data even if uninitialised */
static int DispManipSend(int sock, pei *ppei)
{
    int wr, dim, i;
    pei_component *cmpt;
    pstack_f *stack;
    enum ftype tp;
    ftval attr;

    /* send all data */
    wr = DispSockWrite(sock, ppei, sizeof(pei));
    if (wr == -1) {
        printf("************* Error:%s\n", strerror(errno));
        return -1;
    }
    cmpt = ppei->components;
    while (cmpt != NULL) {
        wr = DispSockWrite(sock, cmpt, sizeof(pei_component));
        if (cmpt->strbuf != NULL) {
            dim = strlen(cmpt->strbuf) + 1;
            wr = DispSockWrite(sock, &dim, sizeof(int));
            wr = DispSockWrite(sock, cmpt->strbuf, dim);
        }
        if (cmpt->name != NULL) {
            dim = strlen(cmpt->name) + 1;
            wr = write(sock, &dim, sizeof(int));
            wr = write(sock, cmpt->name, dim);
        }
        if (cmpt->file_path != NULL) {
            dim = strlen(cmpt->file_path) + 1;
            wr = DispSockWrite(sock, &dim, sizeof(int));
            wr = DispSockWrite(sock, cmpt->file_path, dim);
        }
        cmpt = cmpt->next;
    }

    stack = ppei->stack;
    while (stack != NULL) {
        dim = ProtFrameSize(stack->pid);
        wr = DispSockWrite(sock, &stack->pid, sizeof(int));
        wr = DispSockWrite(sock, stack, dim);
        i = 0;
        tp = ProtAttrType(stack->pid, i);
        while (tp != FT_NONE) {
            if (tp == FT_STRING) {
                ProtGetAttr(stack, i, &attr);
                if (attr.str != NULL) {
                    dim = strlen(attr.str) + 1;
                    wr = DispSockWrite(sock, &dim, sizeof(dim));
                    wr = DispSockWrite(sock, attr.str, dim);
                }
                else {
                    dim = 0;
                    wr = DispSockWrite(sock, &dim, sizeof(dim));
                }
                FTFree(&attr, FT_STRING);
            }
            i++;
            tp = ProtAttrType(stack->pid, i);
        }

        if (stack->gstack != NULL) {
            LogPrintf(LV_FATAL, "This PEI requres Xplico Professional edition. Contact: [email protected]");
            exit(-1);
        }

        stack = stack->pfp;
    }

    return 0;
}
コード例 #7
0
ファイル: syslog.c プロジェクト: Cbrdiv/xplico
static packet *SyslogDissector(int flow_id)
{
    packet *pkt;
    const pstack_f *udp, *ip;
    const char *msg;
    ftval val;
    char file_log[SYSLOG_FILENAME_PATH_SIZE];
    char host[SYSLOG_FILENAME_PATH_SIZE];
    pei *ppei;
    pei_component *cmpn;
    time_t cap_sec, end_cap;
    int cntpkt, len;
    short pri, fac, sev;
    FILE *fp;
    
    ppei = NULL;
    LogPrintf(LV_DEBUG, "Syslog id: %d", flow_id);
    cntpkt = 0;

    /* ip version and number */
    udp = FlowStack(flow_id); /* udp frame */
    ip = ProtGetNxtFrame(udp); /* ip/ipv6 frame */

    ProtStackFrmDisp(udp, TRUE);

    /* host */
    len = 0;
    if (ProtFrameProtocol(ip) == ip_id) {
        ProtGetAttr(ip, ip_src_id, &val);
        if (DnsDbSearch(&val, FT_IPv4, host+len, SYSLOG_FILENAME_PATH_SIZE - len) != 0) {
            FTString(&val, FT_IPv4, host+len);
        }
        len = strlen(host);
        host[len++] = ' ';
        host[len++] = '-';
        host[len++] = ' ';
        ProtGetAttr(ip, ip_dst_id, &val);
        if (DnsDbSearch(&val, FT_IPv4, host+len, SYSLOG_FILENAME_PATH_SIZE - len) != 0) {
            FTString(&val, FT_IPv4, host+len);
        }
    }
    else {
        ProtGetAttr(ip, ipv6_src_id, &val);
        if (DnsDbSearch(&val, FT_IPv6, host+len, SYSLOG_FILENAME_PATH_SIZE - len) != 0) {
            FTString(&val, FT_IPv6, host+len);
        }
        host[len++] = ' ';
        host[len++] = '-';
        host[len++] = ' ';
        ProtGetAttr(ip, ipv6_dst_id, &val);
        if (DnsDbSearch(&val, FT_IPv6, host+len, SYSLOG_FILENAME_PATH_SIZE - len) != 0) {
            FTString(&val, FT_IPv6, host+len);
        }
    }
    len = strlen(host);

    /* syslog file */
    sprintf(file_log, "%s/%s/syslog_%p_%lu.log", ProtTmpDir(), SYSLOG_TMP_DIR, file_log,incr++);
    fp = fopen(file_log, "w");
    
    /* first packet */
    pkt = FlowGetPkt(flow_id);
    if (pkt != NULL) {
        /* pei definition */
        PeiNew(&ppei, prot_id);
        PeiCapTime(ppei, pkt->cap_sec);
        PeiMarker(ppei, pkt->serial);
        PeiStackFlow(ppei, udp);
        cap_sec = pkt->cap_sec;
    }
    if (fp != NULL) {
        while (pkt != NULL) {
            cntpkt++;
            end_cap = pkt->cap_sec;
            pri = SyslogPri(pkt->data, pkt->len);
            if (pri != -1) {
                msg = SyslogMsg(pkt->data, pkt->len);
                if (msg != NULL) {
                    sev = pri & 0x07;
                    fac = pri >> 3;
                    fprintf(fp, "{%s.%s} %s", facility[fac], severity[sev], msg);
                }
            }
            
            PktFree(pkt);
            pkt = FlowGetPkt(flow_id);
        }
コード例 #8
0
ファイル: tcp_analysis.c プロジェクト: M0Rf30/xplico
static int TcpCaDisFlow(tca_flow *ifw, packet *pkt)
{
    ftval lost, syn;
    bool clnt, ins;
    
    clnt = TcpCaClientPkt(&ifw->priv, pkt);
    ifw->flow_size += pkt->len;
    //ProtStackFrmDisp(pkt->stk, TRUE);
    ProtGetAttr(pkt->stk, lost_id, &lost);
    if (lost.uint8 == FALSE) {
        ins = TRUE;
        /* data */
        if (pkt->len != 0) {
            if (clnt) {
                ifw->priv.bsent += pkt->len;
                ifw->priv.pkt_sent++;
            }
            else {
                ifw->priv.breceiv += pkt->len;
                ifw->priv.pkt_receiv++;
            }
        }
        else {
            ProtGetAttr(pkt->stk, syn_id, &syn);
            if (clnt) {
                if (syn.uint8 == TRUE) {
                    if (ifw->syn_clt == FALSE)
                        ifw->syn_clt = TRUE;
                    else
                        ins = FALSE;
                }
            }
            else {
                if (syn.uint8 == TRUE) {
                    if (ifw->syn_srv == FALSE)
                        ifw->syn_srv = TRUE;
                    else
                        ins = FALSE;
                }
            }
        }
        ifw->count++;
        ifw->end_cap = pkt->cap_sec;
        
        /* protocol type -ndpi- */
        if (ifw->stage != 4 && (ifw->l7prot_type == NULL || ifw->l7prot_id.master_protocol == NDPI_PROTOCOL_HTTP) && ifw->l7flow != NULL && ins == TRUE) {
            if (clnt) {
                ifw->l7prot_id = nDPIPacket(pkt, ifw->l7flow, ifw->l7src, ifw->l7dst, ifw->priv.ipv6);
            }
            else {
                ifw->l7prot_id = nDPIPacket(pkt, ifw->l7flow, ifw->l7dst, ifw->l7src, ifw->priv.ipv6);
            }
            if (ifw->l7prot_id.protocol != NDPI_PROTOCOL_UNKNOWN) {
                ifw->stage++;
                ifw->l7prot_type = ndpi_protocol2name(ndpi, ifw->l7prot_id, ifw->buff, TCP_CA_LINE_MAX_SIZE);
            }
        }
#ifdef XPL_CHECK_CODE
        if (pkt->raw_len != 0 && ((pkt->raw + pkt->raw_len) < pkt->data)) {
            LogPrintf(LV_OOPS, "TCP data location error %p %p %lu %lu", pkt->raw, pkt->data, pkt->raw_len, pkt->len);
            ProtStackFrmDisp(pkt->stk, TRUE);
            exit(-1);
        }
        if (pkt->raw_len != 0 && (pkt->data + pkt->len) > (pkt->raw + pkt->raw_len)) {
            LogPrintf(LV_OOPS, "TCP data dim error %p %p %lu %lu", pkt->raw, pkt->data, pkt->raw_len, pkt->len);
            ProtStackFrmDisp(pkt->stk, TRUE);
            exit(-1);
        }
#endif
    }
    else {
#if CA_CHECK_LOST
        LogPrintf(LV_WARNING, "Packet Lost (size:%lu)", pkt->len);
        ProtStackFrmDisp(pkt->stk, TRUE);
#endif
        if (clnt) {
            ifw->priv.blost_sent += pkt->len;
            if (ifw->priv.blost_sent == 0)
                ifw->priv.blost_sent = 1;
        }
        else {
            ifw->priv.blost_receiv += pkt->len;
            if (ifw->priv.blost_receiv == 0)
                ifw->priv.blost_receiv = 1;
        }
    }
        
    PktFree(pkt);

    return 0;
}
コード例 #9
0
ファイル: tcp_analysis.c プロジェクト: M0Rf30/xplico
static int TcpCaDisFlowInit(tca_flow *ifw)
{
    const pstack_f *tcp, *ip;
    ftval port_src, port_dst;
    struct in_addr ip_addr;
    struct in6_addr ipv6_addr;
    char ips_str[INET6_ADDRSTRLEN], ipd_str[INET6_ADDRSTRLEN];

    LogPrintf(LV_DEBUG, "TCP analysis id: %d", ifw->flow_id);

    /* ndpi init */ 
    ifw->l7flow = xcalloc(1, ndpi_flow_struct_size);
    if (ifw->l7flow == NULL) {
        LogPrintf(LV_ERROR, "Out of memory");
        ifw->l7src = NULL;
        ifw->l7dst = NULL;
    }
    else {
        ifw->l7src = xcalloc(1, ndpi_proto_size);
        if (ifw->l7src != NULL) {
            ifw->l7dst = xcalloc(1, ndpi_proto_size);
            if (ifw->l7dst == NULL) {
                xfree(ifw->l7src);
                xfree(ifw->l7flow);
                ifw->l7src = NULL;
                ifw->l7flow = NULL;
            }
        }
        else {
            xfree(ifw->l7flow);
            ifw->l7flow = NULL;
            ifw->l7dst = NULL;
        }
    }
    
    /* init */
    memset(&ifw->priv, 0, sizeof(tca_priv));
    tcp = FlowStack(ifw->flow_id);
    ip = ProtGetNxtFrame(tcp);
    ProtGetAttr(tcp, port_src_id, &port_src);
    ProtGetAttr(tcp, port_dst_id, &port_dst);
    ifw->priv.port_s = port_src.uint16;
    ifw->priv.port_d = port_dst.uint16;
    ifw->priv.stack = tcp;
    if (ifw->priv.port_s != port_dst.uint16)
        ifw->priv.port_diff = TRUE;
    ifw->priv.ipv6 = TRUE;
    ifw->first_lost = FALSE;
    ifw->stage = 0;
    if (ProtFrameProtocol(ip) == ip_id) {
        ifw->priv.ipv6 = FALSE;
    }
    if (!ifw->priv.ipv6) {
        ProtGetAttr(ip, ip_src_id, &ifw->priv.ip_s);
        ProtGetAttr(ip, ip_dst_id, &ifw->priv.ip_d);
        ip_addr.s_addr = ifw->priv.ip_s.uint32;
        inet_ntop(AF_INET, &ip_addr, ips_str, INET6_ADDRSTRLEN);
        ip_addr.s_addr = ifw->priv.ip_d.uint32;
        inet_ntop(AF_INET, &ip_addr, ipd_str, INET6_ADDRSTRLEN);
    }
    else {
        ProtGetAttr(ip, ipv6_src_id, &ifw->priv.ip_s);
        ProtGetAttr(ip, ipv6_dst_id, &ifw->priv.ip_d);
        memcpy(ipv6_addr.s6_addr, ifw->priv.ip_s.ipv6, sizeof(ifw->priv.ip_s.ipv6));
        inet_ntop(AF_INET6, &ipv6_addr, ips_str, INET6_ADDRSTRLEN);
        memcpy(ipv6_addr.s6_addr, ifw->priv.ip_d.ipv6, sizeof(ifw->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);
    
    ifw->l7prot_type = NULL;
    ifw->flow_size = 0;
    ifw->count = 0;
    ifw->ppei = NULL;

    FlowSetTimeOut(ifw->flow_id, 0);

    return 0;
}
コード例 #10
0
ファイル: telnet.c プロジェクト: shineit/wifimanage
static packet *TelnetDissector(int flow_id)
{
    packet *pkt;
    const pstack_f *tcp, *ip;
    ftval lost, ip_host, port;
    unsigned short port_host;
    bool ipv6;
    long offset, len, size;
    char host[TELNET_FILENAME_PATH_SIZE];
    char user[TELNET_BUF_SIZE];
    char password[TELNET_BUF_SIZE];
    char cmd_file[TELNET_FILENAME_PATH_SIZE];
    FILE *fp;
    char *buf;
    pei *ppei;
    time_t cap_sec, end_cap;
    int cntpkt;

    LogPrintf(LV_DEBUG, "Telnet id: %d", flow_id);
    
    cntpkt = 0;
    /* init (this for each telnet stream) */
    user[0] = '\0';
    password[0] = '\0';
    sprintf(cmd_file, "%s/%s/telnet_%lu_%p_%i.txt", ProtTmpDir(), TELNET_TMP_DIR, time(NULL), cmd_file, incr);
    incr++;
    fp = fopen(cmd_file, "w");
    ipv6 = FALSE;
    buf = DMemMalloc(TELNET_LOGIN_SIZE);
    buf[0] = '\0';
    len = 0;
    
    /* ip version and number */
    tcp = FlowStack(flow_id); /* tcp frame */
    ip = ProtGetNxtFrame(tcp); /* ip/ipv6 frame */
    ProtGetAttr(tcp, port_dst_id, &port);
    port_host = port.uint16;
    if (ProtFrameProtocol(ip) == ipv6_id) {
        ipv6 = TRUE;
    }
    if (ipv6 == FALSE) {
        ProtGetAttr(ip, ip_dst_id, &ip_host);
        if (DnsDbSearch(&(ip_host), FT_IPv4, host, TELNET_FILENAME_PATH_SIZE) != 0) {
            FTString(&(ip_host), FT_IPv4, host);
        }
    }
    else {
        ProtGetAttr(ip, ipv6_dst_id, &ip_host);
        if (DnsDbSearch(&(ip_host), FT_IPv6, host, TELNET_FILENAME_PATH_SIZE) != 0) {
            FTString(&(ip_host), FT_IPv6, host);
        }
    }
    sprintf(host+strlen(host), ":%i", port_host);
    
    /* first packet */
    pkt = FlowGetPkt(flow_id);
    if (pkt != NULL) {
        /* pei definition */
        PeiNew(&ppei, telnet_id);
        PeiCapTime(ppei, pkt->cap_sec);
        PeiMarker(ppei, pkt->serial);
        PeiStackFlow(ppei, tcp);
        cap_sec = pkt->cap_sec;
    }
    while (pkt != NULL) {
        cntpkt++;
        end_cap = pkt->cap_sec;
        offset = 0;
        /* check if there are packet lost */
        ProtGetAttr(pkt->stk, lost_id, &lost);
        //ProtStackFrmDisp(pkt->stk, TRUE); /* this function display the structure of packet stack of this packet */
        if (lost.uint8 == FALSE && pkt->len != 0) {
            /* no packet lost and packet with data */
            /* skip the telnet commands, we are interested only in readable data */
#warning "to do: reassemble telnet message from many tcp packets"
            offset = TelnetSkipCommand((unsigned char *)(pkt->data), (unsigned char *)(pkt->data + pkt->len));
            if (offset < pkt->len) {
                TelnetConvertZeros((unsigned char *)(pkt->data + offset), (unsigned char *)(pkt->data + pkt->len));
                size = pkt->len - offset;
                fwrite(pkt->data + offset, 1, size, fp);
                if (len + size < TELNET_LOGIN_SIZE) {
                    memcpy(buf+len, pkt->data + offset, size);
                    len += size;
                    buf[len] = '\0';
                }
            }
        }
        else if (lost.uint8) {
            fprintf(fp, "-----> xplico: packets lost (size: %lub) <-----", pkt->len);
        }

        /* new/next packet */
        PktFree(pkt);
        pkt = FlowGetPkt(flow_id);
    }

    /* search login */
    buf[TELNET_LOGIN_SIZE - 1] = '\0';
    TelnetLogin(buf, user, password, TELNET_BUF_SIZE);

    /* free memory and close file */
    DMemFree(buf);
    if (fp != NULL) {
        fclose(fp);
    }

    if (len != 0) {
        /* compose pei */
        TelnetPei(ppei, host, user, password, cmd_file, &cap_sec, &end_cap);
        /* insert pei */
        PeiIns(ppei);
    }
    
    LogPrintf(LV_DEBUG, "Telnet... bye bye. (count:%i)", cntpkt);

    return NULL;
}
コード例 #11
0
ファイル: tcp_garbage.c プロジェクト: Lingnutter/xplico
packet *TcpGrbDissector(int flow_id)
{
    packet *pkt, *opkt;
    tgrb_priv *priv;
    const pstack_f *tcp, *ip;
    ftval port_src, port_dst, lost;
    struct in_addr ip_addr;
    struct in6_addr ipv6_addr;
    char ips_str[INET6_ADDRSTRLEN], ipd_str[INET6_ADDRSTRLEN];
    bool ipv4;
    int dig_s, dig_d, *dig_x;
    int count, i, j, k;
    int threshold;
    bool txt_data;
    FILE *txt_fp;
    char txt_file[TCP_GRB_FILENAME_PATH_SIZE];
    unsigned char *thrs;
    pei *ppei;
    time_t cap_sec, end_cap;
#if GRB_FILE
    int fd_pcap;
    char filename[TCP_GRB_FILENAME_PATH_SIZE];
    int prot;
    struct pcap_file_header fh;
    struct pcappkt_hdr pckt_header;
#endif
    size_t flow_size;
    bool first_lost, dig_end;
    dig *dig_srch_a, *dig_srch_b, *dig_srch;
    char buff[TCP_CFG_LINE_MAX_SIZE];
    char *l7prot_type;
    struct ndpi_flow_struct *l7flow;
    struct ndpi_id_struct *l7src, *l7dst;
    ndpi_protocol l7prot_id;
    unsigned char stage;
    
    LogPrintf(LV_DEBUG, "TCP garbage id: %d", flow_id);

    /* ndpi init */ 
    l7flow = xcalloc(1, ndpi_flow_struct_size);
    if (l7flow == NULL) {
        LogPrintf(LV_ERROR, "Out of memory");
        l7src = NULL;
        l7dst = NULL;
    }
    else {
        l7src = xcalloc(1, ndpi_proto_size);
        if (l7src != NULL) {
            l7dst = xcalloc(1, ndpi_proto_size);
            if (l7dst == NULL) {
                xfree(l7src);
                xfree(l7flow);
                l7src = NULL;
                l7flow = NULL;
            }
        }
        else {
            xfree(l7flow);
            l7flow = NULL;
            l7dst = NULL;
        }
    }
    
    /* dig init */
    dig_srch_a = dig_srch_b = NULL;
    if (enable_dig) {
        dig_s = dig_d = -1;
        dig_x = NULL;
        dig_srch_a = xmalloc(sizeof(dig) * dig_type_dim);
        dig_srch_b = xmalloc(sizeof(dig) * dig_type_dim);
        if (dig_srch_a != NULL && dig_srch_b != NULL) {
            memset(dig_srch_a, 0, sizeof(dig) * dig_type_dim);
            memset(dig_srch_b, 0, sizeof(dig) * dig_type_dim);
            for (i=0; i!=dig_type_dim; i++) {
                dig_srch_a[i].ft = &(dig_tbl[i]);
                dig_srch_b[i].ft = &(dig_tbl[i]);
                dig_srch_a[i].dig_sync = -1;
                dig_srch_b[i].dig_sync = -1;
            }
        }
        else {
            if (dig_srch_a != NULL)
                xfree(dig_srch_a);
            if (dig_srch_b != NULL)
                xfree(dig_srch_b);
            dig_srch_a = dig_srch_b = NULL;
        }
    }

    /* init */
    priv = DMemMalloc(sizeof(tgrb_priv));
    memset(priv, 0, sizeof(tgrb_priv));
    tcp = FlowStack(flow_id);
    ip = ProtGetNxtFrame(tcp);
    ProtGetAttr(tcp, port_src_id, &port_src);
    ProtGetAttr(tcp, port_dst_id, &port_dst);
    priv->port_s = port_src.uint16;
    priv->port_d = port_dst.uint16;
    priv->stack = tcp;
    if (priv->port_s != port_dst.uint16)
        priv->port_diff = TRUE;
    priv->ipv6 = TRUE;
    ipv4 = FALSE;
    first_lost = FALSE;
    stage = 0;
    if (ProtFrameProtocol(ip) == ip_id) {
        ipv4 = TRUE;
        priv->ipv6 = FALSE;
    }
    if (ipv4) {
        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);
    
    /* file pcap */
#if GRB_FILE
    sprintf(filename, "%s/tcp_%d_grb_%s_%s.pcap", ProtTmpDir(), serial, ips_str, ipd_str);
    serial++;
    fd_pcap = open(filename, O_WRONLY | O_CREAT, 0x01B6);
    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;
    if (ProtGetNxtFrame(ip) != NULL) {
        prot = ProtFrameProtocol(ProtGetNxtFrame(ip));
        if (prot == eth_id)
            fh.linktype = DLT_EN10MB;
        else if (prot == ppp_id)
            fh.linktype = DLT_PPP;
        else
            fh.linktype = DLT_RAW;
    }
    if (fd_pcap != -1)
        write(fd_pcap, (char *)&fh, sizeof(struct pcap_file_header));
#endif
    
    l7prot_type = NULL;
    flow_size = 0;
    count = 0;
    opkt = pkt = NULL;
    ppei = NULL;
    txt_data = FALSE;
    txt_fp = NULL;
    threshold = 0;
#if GRB_TXT_ENABLE
    thrs = xmalloc(TCP_GRB_THRESHOLD+1);
#else
    thrs = NULL;
#endif
    do {
        pkt = FlowGetPkt(flow_id);
        if (pkt != NULL) {
            ProtGetAttr(pkt->stk, lost_id, &lost);
            if (lost.uint8 == FALSE) {
                /* create pei */
                PeiNew(&ppei, tcp_grb_id);
                PeiCapTime(ppei, pkt->cap_sec);
                PeiMarker(ppei, pkt->serial);
                PeiStackFlow(ppei, tcp);
                cap_sec = pkt->cap_sec;
                end_cap = pkt->cap_sec;
                break;
            }
            else {
                first_lost = TRUE;
            }
        }
    } while (pkt != NULL);
    while (pkt != NULL) {
        flow_size += pkt->len;
        //ProtStackFrmDisp(pkt->stk, TRUE);
        ProtGetAttr(pkt->stk, lost_id, &lost);
        if (lost.uint8 == FALSE) {
            count++;
            end_cap = pkt->cap_sec;
            /* protocol type -ndpi- */
            if (stage != 4 && (l7prot_type == NULL || l7prot_id.master_protocol == NDPI_PROTOCOL_HTTP) && l7flow != NULL) {
                if (TcpGrbClientPkt(priv, pkt)) {
                    l7prot_id = nDPIPacket(pkt, l7flow, l7src, l7dst, ipv4);
                }
                else {
                    l7prot_id = nDPIPacket(pkt, l7flow, l7dst, l7src, ipv4);
                }
                if (l7prot_id.protocol != NDPI_PROTOCOL_UNKNOWN) {
                    stage++;
                    l7prot_type = ndpi_protocol2name(ndpi, l7prot_id, buff, TCP_CFG_LINE_MAX_SIZE);
                }
            }
#ifdef XPL_CHECK_CODE
            if (pkt->raw_len != 0 && ((pkt->raw + pkt->raw_len) < pkt->data)) {
                LogPrintf(LV_OOPS, "TCP data location error %p %p %lu %lu", pkt->raw, pkt->data, pkt->raw_len, pkt->len);
                ProtStackFrmDisp(pkt->stk, TRUE);
                exit(-1);
            }
            if (pkt->raw_len != 0 && (pkt->data + pkt->len) > (pkt->raw + pkt->raw_len)) {
                LogPrintf(LV_OOPS, "TCP data dim error %p %p %lu %lu", pkt->raw, pkt->data, pkt->raw_len, pkt->len);
                ProtStackFrmDisp(pkt->stk, TRUE);
                exit(-1);
            }
#endif

#if GRB_FILE
            pckt_header.caplen = pkt->raw_len;
            pckt_header.len = pkt->raw_len;
            pckt_header.tv_sec = pkt->cap_sec;
            pckt_header.tv_usec = pkt->cap_usec;
            if (fd_pcap != -1) {
                write(fd_pcap, (char *)&pckt_header, sizeof(struct pcappkt_hdr));
                write(fd_pcap, (char *)pkt->raw, pkt->raw_len);
            }
#endif
        }
        else {
#if GRB_FILE || GRB_CHECK_LOST
            LogPrintf(LV_WARNING, "Packet Lost (size:%lu)", pkt->len);
            ProtStackFrmDisp(pkt->stk, TRUE);
#endif
        }
        if (thrs != NULL) {
            /* check stream to find text */
            if (lost.uint8 == FALSE && pkt->len != 0) {
                if (threshold + pkt->len >= TCP_GRB_THRESHOLD) {
                    if (txt_data == FALSE) {
                        /* text flow */
                        txt_data = TcpGrbMajorityText(thrs, threshold);
                        if (txt_data == FALSE) {
                            xfree(thrs);
                            thrs = NULL;
                            threshold = 0;
                        }
                        else {
                            sprintf(txt_file, "%s/%s/tcp_grb_%lu_%p_%i.txt", ProtTmpDir(), TCP_GRB_TMP_DIR, time(NULL), txt_file, incr++);
                            txt_fp = fopen(txt_file, "w");
                            if (txt_fp != NULL) {
                                TcpGrbText(txt_fp, thrs, threshold);
                                threshold = 0;
                                memcpy(thrs+threshold, pkt->data,  pkt->len);
                                threshold += pkt->len;
                                thrs[threshold] = '\0';
                            }
                            else {
                                LogPrintf(LV_ERROR, "Unable to open file: %s", txt_file);
                                txt_data = FALSE;
                                xfree(thrs);
                                thrs = NULL;
                                threshold = 0;
                            }
                        }
                    }
                    else {
                        TcpGrbText(txt_fp, thrs, threshold);
                        threshold = 0;
                        if (pkt->len > TCP_GRB_THRESHOLD) {
                            TcpGrbText(txt_fp, (unsigned char *)pkt->data, pkt->len);
                        }
                        else {
                            memcpy(thrs+threshold, pkt->data,  pkt->len);
                            threshold += pkt->len;
                        }
                        thrs[threshold] = '\0';
                    }
                }
                else {
                    memcpy(thrs+threshold, pkt->data,  pkt->len);
                    threshold += pkt->len;
                    thrs[threshold] = '\0';
                }
            }
        }

        /* dig */
        if (dig_srch_a != NULL && pkt->len != 0) {
            if (TcpGrbClientPkt(priv, pkt)) {
                dig_srch = dig_srch_a;
                dig_x = &dig_s;
            }
            else {
                dig_srch = dig_srch_b;
                dig_x = &dig_d;
            }

            for (i=0; i!=dig_type_dim; i++) {
#if 0
                if (*dig_x != -1 && *dig_x != dig_srch[i].dig_sync)
                    continue;
#endif
                bool nmatch = FALSE;
                do {
                    if (dig_srch[i].head == FALSE) {
                        if (lost.uint8 == FALSE && (nmatch == TRUE || TcpGrbDigMatchStart(&(dig_srch[i]), pkt) == 1)) {
                            nmatch = FALSE;
                            *dig_x = i;
                            dig_srch[i].head = TRUE;
                            dig_srch[i].dig_sync = i;
                            dig_srch[i].start_cap = pkt->cap_sec;
                            dig_srch[i].serial = pkt->serial;
                            j = 0;
                            k = dig_srch[i].ft->end_id[0];
                            while (k != -1) {
                                dig_srch[k].head = TRUE;
                                dig_srch[k].dig_sync = i;
                                j++;
                                k = dig_srch[i].ft->end_id[j];
                            }
                            /* save file */
                            sprintf(dig_srch[i].filename, "%s/%s/file_%lu%i.%s", ProtTmpDir(), TCP_GRB_TMP_DIR, time(NULL), incr_dig++, dig_srch[i].ft->ename);
                            LogPrintf(LV_DEBUG, "File %s found (%s)", dig_srch[i].ft->ename, dig_srch[i].filename);
                            dig_srch[i].fp = fopen(dig_srch[i].filename, "wb");
                            if (dig_srch[i].fp != NULL) {
                                if (pkt == dig_srch[i].pkt) {
                                    //ProtStackFrmDisp(pkt->stk, TRUE);
                                    dig_srch[i].fsize = pkt->len - dig_srch[i].pkt_offset;
                                    fwrite(pkt->data + dig_srch[i].pkt_offset, 1, dig_srch[i].fsize, dig_srch[i].fp);
                                }
                                else {
                                    if (opkt == dig_srch[i].pkt) {
                                        //ProtStackFrmDisp(pkt->stk, TRUE);
                                        dig_srch[i].fsize = opkt->len - dig_srch[i].pkt_offset;
                                        fwrite(opkt->data + dig_srch[i].pkt_offset, 1, dig_srch[i].fsize, dig_srch[i].fp);
                                    }
                                    else {
                                        LogPrintf(LV_ERROR, "Improve dig code");
                                    }
                                    fwrite(pkt->data, 1, pkt->len, dig_srch[i].fp);
                                    dig_srch[i].fsize = pkt->len;
                                }
                            }
                            dig_srch[i].pkt_offset = 0;
                            dig_srch[i].pkt = NULL;
                        }
                    }
                    else {
                        dig_end = FALSE;
                        if (lost.uint8 == FALSE) {
                            if (dig_srch[i].ft->elen != 0) {
                                if (TcpGrbDigMatchEnd(&(dig_srch[i]), pkt) == 1) {
                                    ProtStackFrmDisp(pkt->stk, TRUE);
                                    dig_end = TRUE;
                                    k = dig_srch[i].dig_sync;
                                    dig_srch[k].fsize += dig_srch[i].pkt_offset + 1;
                                    if (dig_srch[k].fp != NULL) {
                                        fwrite(pkt->data, 1, dig_srch[i].pkt_offset + 1, dig_srch[k].fp);
                                        fclose(dig_srch[k].fp);
                                    }
                                    dig_srch[i].pkt_offset = 0;
                                    dig_srch[i].pkt = NULL;
                                }
                                if (dig_srch[i].ft->stend == TRUE) {
                                    if (TcpGrbDigMatchStart(&(dig_srch[i]), pkt) == 1) {
                                        dig_end = TRUE;
                                        nmatch = TRUE;
                                        k = dig_srch[i].dig_sync;
                                        dig_srch[k].fsize += dig_srch[i].pkt_offset;
                                        if (dig_srch[k].fp != NULL) {
                                            fwrite(pkt->data, 1, dig_srch[i].pkt_offset, dig_srch[k].fp);
                                            fclose(dig_srch[k].fp);
                                        }
                                    }
                                }
                            }
                            if (dig_end == FALSE) {
                                if (dig_srch[i].fsize + pkt->len >= dig_srch[i].ft->msize) {
                                    dig_end = TRUE;
                                    k = dig_srch[i].dig_sync;
                                    if (dig_srch[k].fp != NULL) {
                                        if (lost.uint8 == FALSE)
                                            fwrite(pkt->data, 1, dig_srch[i].ft->msize - dig_srch[i].fsize, dig_srch[k].fp);
                                        fclose(dig_srch[k].fp);
                                        dig_srch[k].fsize = dig_srch[i].ft->msize;
                                    }
                                }
                            }
                            if (dig_end == TRUE) {
                                dig_srch[i].head = FALSE;
                                *dig_x = -1;
                                j = 0;
                                k = dig_srch[i].ft->end_id[0];
                                while (k != -1) {
                                    dig_srch[k].head = FALSE;
                                    if (k != i) {
                                        dig_srch[k].fs = 0;
                                        dig_srch[k].dig_sync = -1;
                                    }
                                    j++;
                                    k = dig_srch[i].ft->end_id[j];
                                }
                                k = dig_srch[i].dig_sync;
                                
                                dig_srch[i].fs = 0;
                                dig_srch[i].dig_sync = -1;
                                LogPrintf(LV_DEBUG, "End file %s (%s)", dig_srch[i].ft->ename, dig_srch[k].filename);
                                dig_srch[k].end_cap = pkt->cap_sec;

                                GrbDigPei(&dig_srch[k], tcp);
                                dig_srch[k].fsize = 0;
                                dig_srch[k].fp = NULL;
                                dig_srch[k].filename[0] = '\0';
                            }
                            else if (i == dig_srch[i].dig_sync) {
                                dig_srch[i].fsize += pkt->len;
                                if (dig_srch[i].fp != NULL) {
                                    if (lost.uint8 == FALSE)
                                        fwrite(pkt->data, 1, pkt->len, dig_srch[i].fp);
                                    else {
                                        char *zero;
                                        zero = xmalloc(pkt->len);
                                        if (zero != NULL) {
                                            memset(zero, 0, pkt->len);
                                            fwrite(zero, 1, pkt->len, dig_srch[i].fp);
                                            xfree(zero);
                                        }
                                    }
                                }
                            }
                        }
                    }
                } while(nmatch == TRUE);
            }
        }
        
        if (opkt != NULL)
            PktFree(opkt);
        opkt = pkt;
        pkt = FlowGetPkt(flow_id);
    }
    if (opkt != NULL) {
        PktFree(opkt);
        opkt = NULL;
    }
    
    /* text flows */
    if (thrs != NULL) {
        if (txt_data == FALSE) {
            /* text flow */
            if (TcpGrbMajorityText(thrs, threshold) == TRUE) {
                sprintf(txt_file, "%s/%s/tcp_grb_%lu_%p_%i.txt", ProtTmpDir(), TCP_GRB_TMP_DIR, time(NULL), txt_file, incr++);
                txt_fp = fopen(txt_file, "w");
            }
        }
        if (txt_fp != NULL) {
            TcpGrbText(txt_fp, thrs, threshold);
        }
        xfree(thrs);
    }
    
    /* ndpi free */
    if (l7flow != NULL) {
        xfree(l7flow);
        xfree(l7src);
        xfree(l7dst);
    }
    if (l7prot_type == NULL)
        l7prot_type = "Unknown";

    /* dig flow */
    for (i=0; i!=dig_type_dim; i++) {
        if (dig_srch_a[i].head == TRUE) {
            if (i == dig_srch_a[i].dig_sync) {
                if (dig_srch_a[i].fp != NULL)
                    fclose(dig_srch_a[i].fp);
                LogPrintf(LV_DEBUG, "End stream of file %s", dig_srch_a[i].ft->ename);
                dig_srch_a[i].end_cap = end_cap;
                GrbDigPei(&dig_srch_a[i], tcp);
                dig_srch_a[i].fsize = 0;
                dig_srch_a[i].fp = NULL;
                dig_srch_a[i].filename[0] = '\0';
            }
        }
        if (dig_srch_b[i].head == TRUE) {
            if (i == dig_srch_b[i].dig_sync) {
                if (dig_srch_b[i].fp != NULL)
                    fclose(dig_srch_b[i].fp);
                LogPrintf(LV_DEBUG, "End stream of file %s", dig_srch_b[i].ft->ename);
                dig_srch_b[i].end_cap = end_cap;
                GrbDigPei(&dig_srch_b[i], tcp);
                dig_srch_b[i].fsize = 0;
                dig_srch_b[i].fp = NULL;
                dig_srch_b[i].filename[0] = '\0';
            }
        }
        
    }
    /* tcp reset */
    if (first_lost && (count < 5 || flow_size == 0)) {
        if (txt_fp != NULL) {
            fclose(txt_fp);
            remove(txt_file);
            txt_fp = NULL;
        }
    }
    else {
        if (txt_fp != NULL) {
            fclose(txt_fp);
            /* insert data */
            GrbPei(ppei, l7prot_type, flow_size, txt_file, &cap_sec, &end_cap);
            /* insert pei */
            PeiIns(ppei);
        }
        else  {
            /* insert data */
            GrbPei(ppei, l7prot_type, flow_size, NULL, &cap_sec, &end_cap);
            /* insert pei */
            PeiIns(ppei);
        }
    }
    /* end */
#if GRB_FILE
    if (fd_pcap != -1)
        close(fd_pcap);
#endif

    if (dig_srch_a != NULL) {
        xfree(dig_srch_a);
        xfree(dig_srch_b);
    }
    DMemFree(priv);

    LogPrintf(LV_DEBUG, "TCP->%s garbage... bye bye  fid:%d count:%i", l7prot_type, flow_id, count);

    return NULL;
}