Пример #1
0
static void SegFault(int sig)
{
    int fid;
    const pstack_f *stk;
    
    /* default handler */
    signal(SIGSEGV, SIG_DFL);

    LogPrintf(LV_OOPS, "SegFault");
    /* print flow stack of thread */
    fid = FthreadSelfFlowId();
    if (fid != -1) {
        stk = FlowStack(fid);
        ProtStackFrmDisp(stk, TRUE);
    }
    else {
        fflush(NULL);
        if (mnp_pei != NULL)
            LogPrintfPei(LV_OOPS, mnp_pei, "Fault data saved in xml file");
        LogPrintf(LV_ERROR, "Thread without xplico's protol-stack (possible main flow)"); 
    }
    /* save to file in wireshark filter format all flows active in the time of fault */
    LogFault("Segmentation Fault");
    printf("Segmentation Fault: see log file and report it to the developers: [email protected]\n");
    fflush(NULL);
#if 0
    while (1)
        sleep(1);
#endif
    raise(SIGSEGV); /* call default handler*/
}
Пример #2
0
static packet* PppoeDissector(packet *pkt)
{
    pstack_f *frame;
    ftval val;
    unsigned short len;
    pppoe_hdr *pppoeh;

    /* simple verify */
    if (sizeof(pppoe_hdr) > pkt->len) {
        ProtStackFrmDisp(pkt->stk, TRUE);
        PktFree(pkt);
        return NULL;
    }
    len = 0;
    pppoeh = (pppoe_hdr*)pkt->data;
    len = ntohs(pppoeh->len);
    
    if (len > pkt->len - sizeof(pppoe_hdr)) {
        ProtStackFrmDisp(pkt->stk, TRUE);
        PktFree(pkt);
        return NULL;
    }

    /* new frame */
    frame = ProtCreateFrame(prot_id);
    ProtSetNxtFrame(frame, pkt->stk);
    pkt->stk = frame;
    
    /* set attribute */
    /* type */
    val.uint8 = pppoeh->type;
    ProtInsAttr(frame, type_id, &val);
    
    /* code */
    val.uint8 = pppoeh->code;
    ProtInsAttr(frame, code_id, &val);

    /* session id */
    val.uint16 = ntohs(pppoeh->sess_id);
    ProtInsAttr(frame, ses_id, &val);

    /* pdu */
    pkt->data += sizeof(pppoe_hdr);
    pkt->len = len;

    return pkt;
}
Пример #3
0
int FlowPutPkt(int flow_id, packet *pkt)
{
    struct timeval tpkt;

    pthread_mutex_lock(flow_tbl[flow_id].mux);

    if (flow_tbl[flow_id].pkt_q != NULL) {
        flow_tbl[flow_id].pkt_q->next = pkt;
        flow_tbl[flow_id].pkt_q = pkt;
    }
    else {
        flow_tbl[flow_id].pkt_q = pkt;
        flow_tbl[flow_id].fpkt = pkt;
        flow_tbl[flow_id].cpkt = pkt;
        flow_tbl[flow_id].time = pkt->cap_sec;
        flow_tbl[flow_id].ustime = pkt->cap_usec;
        /* wakeup group in wait */
        if (flow_tbl[flow_id].grp_fuse == TRUE && flow_tbl[flow_id].grp_id != -1) {
            /* time of next patcket of this flow */
            tpkt.tv_sec = pkt->cap_sec;
            tpkt.tv_usec = pkt->cap_usec;
            GrpNewPkt(flow_tbl[flow_id].grp_id, flow_tbl[flow_id].gref, &tpkt);
        }
    }
    flow_tbl[flow_id].ins_time = pkt->cap_sec;
    flow_tbl[flow_id].ins_ustime = pkt->cap_usec;
    flow_tbl[flow_id].pkt_num++;
#ifdef XPL_PEDANTIC_STATISTICS
    flow_tbl[flow_id].pkt_tot++;
#endif

#ifdef XPL_CHECK_CODE
    if (pkt->len > pkt->raw_len && pkt->raw != NULL) {
        LogPrintf(LV_OOPS, "Data dimension error raw:%lu data:%lu", pkt->raw_len, pkt->len);
        ProtStackFrmDisp(pkt->stk, TRUE);
    }
#endif
    /* wakeup flow in wait */
    pthread_cond_signal(flow_tbl[flow_id].cond);
    
    /* if group with syncronization from flows, wait pkt elaboration */
    if (flow_tbl[flow_id].sync && flow_tbl[flow_id].elab == TRUE) {
        /* group of flows */
        pthread_cond_wait(flow_tbl[flow_id].gcond, flow_tbl[flow_id].mux);
    }
    pthread_mutex_unlock(flow_tbl[flow_id].mux);

    return 0;
}
Пример #4
0
/* these functions should not be used */
void FlowDebOpen(void)
{
    int i;

    for (i=0; i!=tbl_dim; i++) {
        if (flow_tbl[i].stack != NULL) {
            LogPrintf(LV_DEBUG, "open flow: %i", i);
            LogPrintf(LV_DEBUG, "\t name: %s", flow_tbl[i].name);
            LogPrintf(LV_DEBUG, "\t proto: %i", flow_tbl[i].proto_id);
            LogPrintf(LV_DEBUG, "\t elab: %i", flow_tbl[i].elab);
            LogPrintf(LV_DEBUG, "\t sync: %i", flow_tbl[i].sync);
            LogPrintf(LV_DEBUG, "\t fthd: %i", flow_tbl[i].fthd_id);
            LogPrintf(LV_DEBUG, "\t grp: %i", flow_tbl[i].grp_id);
            ProtStackFrmDisp(flow_tbl[i].stack, TRUE);
        }
    }
}
Пример #5
0
int FlowSetName(int flow_id, int prot_id)
{
    FlowTblLock();

#ifdef XPL_CHECK_CODE
    if (flow_tbl[flow_id].name[0] != '\0') {
        LogPrintf(LV_OOPS, "flow (%d) have alrady a name (%s).", flow_id, flow_tbl[flow_id].name);
        ProtStackFrmDisp(flow_tbl[flow_id].stack, TRUE);
    }
#endif

    sprintf(flow_tbl[flow_id].name, "%s_%d", prot_tbl[prot_id].name, flow_id);
    flow_tbl[flow_id].proto_id = prot_id;

    FlowTblUnlock();

    return 0;
}
Пример #6
0
int FlowSetElab(int flow_id, int fthd_id)
{
    FlowTblLock();

#ifdef XPL_CHECK_CODE
    if (flow_tbl[flow_id].elab == TRUE) {
        LogPrintf(LV_OOPS, "flow (%s) alrady in elaboration.", flow_tbl[flow_id].name);
        ProtStackFrmDisp(flow_tbl[flow_id].stack, TRUE);
    }
#endif

    /* set to elab all flow of group */
    if (flow_tbl[flow_id].grp_id != -1) {
        GrpElab(flow_tbl[flow_id].grp_id, fthd_id, flow_id);
    }
    else {
        flow_tbl[flow_id].elab = TRUE;
        flow_tbl[flow_id].fthd_id = fthd_id;
    }

    FlowTblUnlock();

    return 0;
}
Пример #7
0
int FlowDelete(int flow_id)
{
    int ret;
    packet *pkt, *tmp;
    int i, cnt, base;
    int nxt_flw, grp_id;
    freel *ftmp;
    
    FlowTblLock();

    /* check if flow is closed */
    if (flow_tbl[flow_id].close == FALSE) {
        FlowTblUnlock();
        LogPrintf(LV_ERROR, "It is tried to delete an open flow");
        return -1;
    }

    /* close all flows son of this */
    grp_id = flow_tbl[flow_id].grp_id;
    if (grp_id == -1) {
        if (flow_tbl[flow_id].son_num) {
            cnt = 0;
            base = flow_num;
            for (i=0; i<tbl_dim && cnt<base; i++) {
                if (flow_tbl[i].stack != NULL) {
                    cnt++;
                    if (flow_tbl[i].pfid == flow_id) {
                        FlowClose(i);
                        flow_tbl[i].pfid = -1; /* parent terminated */
                    }
                }
            }
        }
    }
    else if (GrpFlowNum(grp_id) == 1) {
        /* last flow of this group (the thread flow is terminated!) */
        cnt = 0;
        base = flow_num;
        for (i=0; i<tbl_dim && cnt<base; i++) {
            if (flow_tbl[i].stack != NULL) {
                cnt++;
                if (flow_tbl[i].pgrp_id == grp_id) {
                    FlowClose(i);
                    flow_tbl[i].pfid = -1; /* parent terminated */
                    flow_tbl[i].pgrp_id = -1; /* parent terminated */
                }
            }
        }
    }

    /* parent son counter */
    if (flow_tbl[flow_id].pfid != -1) {
        flow_tbl[flow_tbl[flow_id].pfid].son_num--;
    }

    /* count the packet from protocol node to protocol dissector */
#ifdef XPL_PEDANTIC_STATISTICS
    if (flow_tbl[flow_id].proto_id != -1 && flow_tbl[flow_id].proto_id != flow_tbl[flow_id].pfid) {
        ProtPktFromNode(flow_tbl[flow_id].proto_id, flow_tbl[flow_id].pkt_tot);
    }
#endif

    /* remove all (grp) rules created by this flow */
    GrpRuleRmAll(flow_id);

    /* check if flow have packet in the queue */
    pthread_mutex_lock(flow_tbl[flow_id].mux);
    if (flow_tbl[flow_id].pkt_num != 0) {
        if (flow_tbl[flow_id].elab == TRUE) {
            LogPrintf(LV_WARNING, "Deleted a flow with %d packet in queue", flow_tbl[flow_id].pkt_num);
            ProtStackFrmDisp(FlowStack(flow_id), TRUE);
        }
        pkt = flow_tbl[flow_id].fpkt;
        
        /* free all packet */
#ifndef XPL_CHECK_CODE
        PktFree(pkt); /* recursive */
        pkt = NULL;
#else
        while (pkt != NULL) {
            tmp = pkt;
            pkt = pkt->next;
            tmp->next = NULL;
            PktFree(tmp);
            flow_tbl[flow_id].pkt_num--;
        }
        if (flow_tbl[flow_id].pkt_num != 0) {
            LogPrintf(LV_OOPS, "bug in pkt flow counter");
        }
#endif
    }

    pthread_mutex_unlock(flow_tbl[flow_id].mux);

    /* thread */
    if (flow_tbl[flow_id].elab == TRUE) {
        if (flow_tbl[flow_id].grp_id == -1) {
            ProtRunFlowDec(flow_tbl[flow_id].proto_id);
            FthreadChFlow(flow_tbl[flow_id].fthd_id, -1);
        }
        else {
            if (FthreadFlow(flow_tbl[flow_id].fthd_id) == flow_id) {
                GrpLock(flow_tbl[flow_id].grp_id);
                do {
                    nxt_flw = GrpNext(flow_tbl[flow_id].grp_id);
                } while (nxt_flw != -1 && nxt_flw == flow_id);
                GrpUnlock(flow_tbl[flow_id].grp_id);
#ifndef PROT_GRP_COUNT
                if (nxt_flw == -1) {
                    ProtRunFlowDec(flow_tbl[flow_id].proto_id);
                }
#else
                ProtRunFlowDec(flow_tbl[flow_id].proto_id);
#endif
                FthreadChFlow(flow_tbl[flow_id].fthd_id, nxt_flw);
            }
            else {
#ifdef PROT_GRP_COUNT
                ProtRunFlowDec(flow_tbl[flow_id].proto_id);
#endif
            }
        }
    }

    /* remove from grp */
    if (flow_tbl[flow_id].grp_id != -1) {
        ret = GrpRm(flow_tbl[flow_id].grp_id, flow_id);
#ifdef XPL_CHECK_CODE
        if (ret == -1) {
            LogPrintf(LV_OOPS, "bug in Grp Add/Rm use");
        }
#endif
    }

    /* stack */
    ProtDelFrame(flow_tbl[flow_id].stack);

    /* reset flow cel */
    FlowElemInit(flow_tbl+flow_id, TRUE);
    
    ftmp = xmalloc(sizeof(freel));
    ftmp->id = flow_id;
    ftmp->nxt = ffree;
    ffree = ftmp;
    ffree_num++;
    
    flow_num--;

    FlowTblUnlock();

    return 0;
}
Пример #8
0
static packet *GtpDissector(packet *pkt)
{
    pstack_f *frame;
    ftval val;
    gtphdr *gtp_h;
    unsigned short offset;
    unsigned char neht, nhlen;

    if (pkt->len < GTP_MIN_HEADER_SIZE) {
        LogPrintf(LV_WARNING, "GTP V1 size error");
        PktFree(pkt);
        return NULL;
    }
    
    /* header */
    gtp_h = (gtphdr *)pkt->data;
    /* gtp version */
    if (gtp_h->ver != 1) {
        LogPrintf(LV_WARNING, "GTP version error (ver:%i)", gtp_h->ver);
        GtpPrintHdr(gtp_h);
        //ProtStackFrmDisp(pkt->stk, TRUE);
        PktFree(pkt);

        return NULL;
    }
    offset = 8;
    if (gtp_h->ext || gtp_h->seq || gtp_h->npdu) {
        offset += 4;
        if (gtp_h->ext) {
            /* decode extension header */
            neht = gtp_h->neht;
            while (neht != 0) {
                nhlen = pkt->data[offset];
                offset += nhlen;
                neht = pkt->data[offset-1];
            }
        }
        //GtpPrintHdr(gtp_h);

        /* new frame */
        frame = ProtCreateFrame(prot_id);
        ProtSetNxtFrame(frame, pkt->stk);
        pkt->stk = frame;
        
        /* set attribute */
        val.uint32 = gtp_h->teid;
        ProtInsAttr(frame, tunnel_id, &val);
        val.uint8 = gtp_h->mtype;
        ProtInsAttr(frame, proto_id, &val);
        
        /* pdu */
        pkt->data += offset;
        pkt->len -= offset;

        //LogPrintf(LV_DEBUG, "data: 0x%x 0x%x", pkt->data[0], pkt->data[1]);

        return pkt;
    }
    
    //ProtStackFrmDisp(pkt->stk, TRUE);
    PktFree(pkt);

    return NULL;

#if 0
    /* gtp version */
    if (gtp_h->ver != 1) {
        LogPrintf(LV_WARNING, "GTP version error (ver:%i)", gtp_h->ver);
        GtpPrintHdr(gtp_h);
        //ProtStackFrmDisp(pkt->stk, TRUE);
        PktFree(pkt);

        return NULL;
    }
    proto_offset += 2;

    /* control message */
    if (gtp_h->t == 1) {
        LogPrintf(LV_DEBUG, "Control message gtp ver:%i ", gtp_h->ver);
        PktFree(pkt);

        return NULL;
    }
    
    /* length */
    if (gtp_h->l == 1) {
        length = ntohs(*(uint16_t *)(pkt->data + proto_offset));
        //LogPrintf(LV_DEBUG, "Length message: %i", length);
        proto_offset += 2;
    }

    /* tunnel and session id */
    tunnel = ntohs(*(uint16_t *)(pkt->data + proto_offset));
    proto_offset += 2;
    session = ntohs(*(uint16_t *)(pkt->data + proto_offset));
    proto_offset += 2;

    /* Ns and Nr fields */
    if (gtp_h->s == 1) {
        LogPrintf(LV_DEBUG, "Ns and Nr fields");
        ProtStackFrmDisp(pkt->stk, TRUE);
        proto_offset += 4;
    }
    
    /* offset size field */
    if (gtp_h->o == 1) {
        offset = ntohs(*(uint16_t *)(pkt->data + proto_offset));
        //ProtStackFrmDisp(pkt->stk, TRUE);
        proto_offset += (offset + 2);
    }
    
    /* new frame */
    frame = ProtCreateFrame(prot_id);
    ProtSetNxtFrame(frame, pkt->stk);
    pkt->stk = frame;

    /* set attribute */
    val.uint16 = tunnel;
    ProtInsAttr(frame, tunnel_id, &val);
    val.uint16 = session;
    ProtInsAttr(frame, session_id, &val);
    val.uint16 = 3; /* forced to be PPP */
    ProtInsAttr(frame, proto_id, &val);

    /* pdu */
    pkt->data += proto_offset;
    pkt->len -= proto_offset;

    return pkt;
#endif
}
Пример #9
0
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);
        }
Пример #10
0
static packet* IpDissector(packet *pkt)
{
    pstack_f *frame;
    ftval val;
    struct iphdr *ip;
    unsigned short checksum_v;
    size_t iphdr_len;
    size_t ip_len;

    if (sizeof(struct iphdr) > pkt->len) {
        LogPrintf(LV_WARNING, "IP hedear packet dimension overflow the real dimension of packet");
        ProtStackFrmDisp(pkt->stk, TRUE);
        PktFree(pkt);
        return NULL;
    }

    ip = (struct iphdr *)pkt->data;
    /* IPv- or IPv4 */
    if (ip->version != 4) {
        if (ip->version == 6 && ipv6_id != -1)
            return ProtDissecPkt(ipv6_id, pkt);

        LogPrintf(LV_WARNING, "IP verision %i without dissector", ip->version);
        ProtStackFrmDisp(pkt->stk, TRUE);
        PktFree(pkt);
        return NULL;
    }
    /* IPv4 */
    iphdr_len = ip->ihl << 2;
    ip_len = ntohs(ip->tot_len);

    /* check consistence and checksum */
    if (ip_len > pkt->len) {
        //LogPrintf(LV_WARNING, "IP packet dimension overflow the real dimension of packet (%i>%i)", ip_len, pkt->len);
        LogPrintf(LV_WARNING, "IP packet dimension overflow the real dimension of packet");
        ProtStackFrmDisp(pkt->stk, TRUE);
        PktFree(pkt);
        return NULL;
    }

#if (XPL_DIS_IP_CHECKSUM == 0)
    if (ip_len <= iphdr_len) {
        LogPrintf(LV_WARNING, "Bogus IP length (%i, less than header length 20)", ip_len);
        ProtStackFrmDisp(pkt->stk, TRUE);
        PktFree(pkt);
        return NULL;
    }
    checksum_v = ip_fast_csum((unsigned char *)ip, ip->ihl);
    if (checksum_v != 0) {
        LogPrintf(LV_WARNING, "IP packet chechsum error (0x%x != 0x%x)", checksum_v, ip->check);
        //ProtStackFrmDisp(pkt->stk, TRUE);
        PktFree(pkt);
        return NULL;
    }
#else 
    if (ip_len <= iphdr_len) {
        ip_len = pkt->len;
    }
#endif
    
    /* fragment ip */
    if (ip->frag_off != 0 && ip->frag_off != 0x40) {
#warning we have to be implement the fragment ip
        LogPrintf(LV_WARNING, "IP packet fragment 0x%x (%i)", ip->frag_off, ntohs(ip->frag_off)<<3);
        ProtStackFrmDisp(pkt->stk, TRUE);
        PktFree(pkt);
        return NULL;
    }

    /* new frame */
    frame = ProtCreateFrame(prot_id);
    ProtSetNxtFrame(frame, pkt->stk);
    pkt->stk = frame;

    /* set attribute */
    val.uint8 = ip->protocol;
    ProtInsAttr(frame, proto_id, &val);
#ifdef XPL_X86
    val.uint32 = ip->saddr;
#else
    val.uint32 = Emb32(&ip->saddr);
#endif
    ProtInsAttr(frame, src_id, &val);
#ifdef XPL_X86
    val.uint32 = ip->daddr;
#else
    val.uint32 = Emb32(&ip->daddr);
#endif
    ProtInsAttr(frame, dst_id, &val);
    val.uint32 = (pkt->data - pkt->raw);
    ProtInsAttr(frame, offset_id, &val);
#if SNIFFER_EVASION
    val.uint8 = ip->ttl;
    ProtInsAttr(frame, ttl_id, &val);
    val.uint16 = ntohs(ip->id);
    ProtInsAttr(frame, id_id, &val);
#endif

    /* pdu */
    pkt->data += iphdr_len;
    pkt->len = ip_len - iphdr_len;

    return pkt;
}
Пример #11
0
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;
}
Пример #12
0
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;
}