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*/ }
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; }
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; }
/* 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); } } }
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; }
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; }
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; }
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 }
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); }
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; }
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; }
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; }