static packet* SdpDissector(packet *pkt) { packet *sdp_pkt; sdp_msg *msg; pstack_f *frame; sdp_pkt = NULL; /* create new SDP message */ msg = DMemMalloc(sizeof(sdp_msg)); SdpMsgInit(msg); if (SdpParse(pkt, pkt->len, msg) == 0) { /* new sdp packet */ sdp_pkt = PktNew(); sdp_pkt->stk = ProtCopyFrame(pkt->stk, TRUE); /* new frame */ frame = ProtCreateFrame(sdp_id); ProtSetNxtFrame(frame, sdp_pkt->stk); sdp_pkt->stk = frame; /* set frame attribute */ sdp_pkt->cap_sec = pkt->cap_sec; sdp_pkt->cap_usec = pkt->cap_usec; sdp_pkt->serial = pkt->serial; sdp_pkt->data = (char *)msg; } PktFree(pkt); return sdp_pkt; }
static void PcapDissector(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { struct cap_ref *ref = (struct cap_ref *)user; packet *pkt; static time_t tm = 0; struct timespec to; unsigned long len; char tgl; pkt = PktNew(); ref->cnt++; pkt->raw = DMemMalloc(h->caplen+sizeof(unsigned long)*2+sizeof(char *)+4); memcpy(pkt->raw, bytes, h->caplen); pkt->raw_len = h->caplen; /* align 4b */ len = pkt->raw_len; len = len + 4 - (len%4); *((unsigned long *)&(pkt->raw[len])) = ref->dlt; *((unsigned long *)&(pkt->raw[len+sizeof(unsigned long)])) = ref->cnt; *((char **)(&(pkt->raw[len+sizeof(unsigned long)*2]))) = ref->file_name; if (h->ts.tv_sec < 0) pkt->cap_sec = 0; else pkt->cap_sec = h->ts.tv_sec; pkt->cap_usec = h->ts.tv_usec; pkt->serial = pkt_serial; /* crash info */ crash_pkt_cnt = ref->cnt; crash_ref_name = ref->file_name; /* decode */ if (!ciao) ProtDissec(pcap_prot_id, pkt); FlowSetGblTime(h->ts.tv_sec); /* next serial number */ pkt_serial++; if (time(NULL) > tm) { tgl = 0; ReportSplash(); while (DispatchPeiPending() > DISP_PEI_MAX_QUEUE) { tgl = (tgl + 1) % 4; to.tv_sec = 0; to.tv_nsec = 300000000; /* wait some time */ while (nanosleep(&to, &to) != 0) ; if (tgl == 0) ReportSplash(); } tm = time(NULL) + 2; } }
int DissecRegist(const char *file_cfg) { proto_dep dep; pei_cmpt peic; bool hins; insert_http = FALSE; if (file_cfg != NULL) { if (CfgParamBool(file_cfg, "HTTPFD_HTTP_INSERT", &hins) == 0) { if (hins) { insert_http = TRUE; } } } memset(&dep, 0, sizeof(proto_dep)); memset(&peic, 0, sizeof(pei_cmpt)); /* protocol name */ ProtName("Http file download", "httpfd"); /* http dependence */ dep.name = "http"; dep.attr = "http.content_range"; dep.type = FT_STRING; dep.op = FT_OP_CNTD; dep.val.str = DMemMalloc(2); strcpy(dep.val.str, "-"); ProtDep(&dep); peic.abbrev = "url"; peic.desc = "Uniform Resource Locator"; ProtPeiComponent(&peic); peic.abbrev = "file"; peic.desc = "File"; ProtPeiComponent(&peic); peic.abbrev = "range"; peic.desc = "File range"; ProtPeiComponent(&peic); peic.abbrev = "content_type"; peic.desc = "Content Type"; ProtPeiComponent(&peic); /* dissectors registration */ ProtDissectors(HttpFdDissector, NULL, NULL, NULL); return 0; }
static int SdpConnectionInfo(const char *data, int len, sdp_msg *msg) { const char *next_token; const char *lineend; int tokenlen; lineend = data + len; /* The first token is connection type */ tokenlen = get_token_len(data, lineend, &next_token); if (tokenlen == 0 || data[tokenlen] != ' ') { return -1; } if (strncmp(data, "IN", tokenlen) == 0) { msg->cntn_info.nettype = SDP_NETTP_IN; } else { return -1; } data = next_token; /* next token is address type */ tokenlen = get_token_len(data, lineend, &next_token); if (tokenlen == 0 || data[tokenlen] != ' ') { msg->cntn_info.nettype = SDP_NETTP_NONE; return -1; } if (strncmp(data, "IP4", tokenlen) == 0) { msg->cntn_info.nettype = SDP_ADDRTP_IP4; } else if (strncmp(data, "IP6", tokenlen) == 0) { msg->cntn_info.nettype = SDP_ADDRTP_IP6; } else { msg->cntn_info.nettype = SDP_NETTP_NONE; return -1; } data = next_token; /* next token is address */ tokenlen = get_token_len(data, lineend, &next_token); if (tokenlen == 0 || (data[tokenlen] != '\r' && data[tokenlen] != '\n')) { msg->cntn_info.nettype = SDP_NETTP_NONE; msg->cntn_info.nettype = SDP_ADDRTP_NONE; return -1; } msg->cntn_info.address = DMemMalloc(tokenlen + 1); memcpy(msg->cntn_info.address, data, tokenlen); msg->cntn_info.address[tokenlen] = '\0'; return 0; }
int PeiNewComponent(pei_component **comp, int comp_id) { if (comp == NULL) { return -1; } *comp = DMemMalloc(sizeof(pei_component)); if (*comp == NULL) { return -1; } memset(*comp, 0, sizeof(pei_component)); (*comp)->eid = comp_id; return 0; }
int DissecRegist(const char *file_cfg) { proto_dep dep; pei_cmpt peic; memset(&dep, 0, sizeof(proto_dep)); memset(&peic, 0, sizeof(pei_cmpt)); /* protocol name */ ProtName("MMS Message Encapsulation", "mms"); /* http dependence */ dep.name = "http"; dep.attr = "http.content_type"; dep.type = FT_STRING; dep.op = FT_OP_CNTD; dep.val.str = DMemMalloc(32); strcpy(dep.val.str, "application/vnd.wap.mms-message"); ProtDep(&dep); /* PEI components */ peic.abbrev = "url"; peic.desc = "Uniform Resource Locator"; ProtPeiComponent(&peic); peic.abbrev = "from"; peic.desc = "Source telephon number"; ProtPeiComponent(&peic); peic.abbrev = "to"; peic.desc = "Destinaton telephon number"; ProtPeiComponent(&peic); peic.abbrev = "cc"; peic.desc = "Destinaton telephon number (cc)"; ProtPeiComponent(&peic); peic.abbrev = "bcc"; peic.desc = "Destinaton telephon number (bcc)"; ProtPeiComponent(&peic); peic.abbrev = "part"; peic.desc = "Content part"; ProtPeiComponent(&peic); peic.abbrev = "raw"; peic.desc = "Binary raw fromat"; ProtPeiComponent(&peic); /* dissectors registration */ ProtDissectors(MmsDissector, NULL, NULL, NULL); return 0; }
int PeiNew(pei **ppei, int prot_id) { if (ppei == NULL) { return -1; } *ppei = DMemMalloc(sizeof(pei)); if (*ppei == NULL) { return -1; } PeiInit(*ppei); (*ppei)->prot_id = prot_id; (*ppei)->time = time(NULL); return 0; }
static inline char *PeiStrCpy(const char *cpy) { char *ret; int len; if (cpy == NULL) return NULL; len = strlen(cpy); ret = DMemMalloc(len+1); if (ret != NULL) { memcpy(ret, cpy, len); ret[len] = '\0'; } return ret; }
int FTCopy(ftval *d, const ftval *s, enum ftype type) { switch (type) { case FT_STRING: if (s->str != NULL) { d->str = DMemMalloc(strlen(s->str)+1); strcpy(d->str, s->str); } else d->str = NULL; break; default: memcpy(d, s, sizeof(ftval)); } return 0; }
int DissecRegist(const char *file_cfg) { proto_dep dep; pei_cmpt peic; memset(&dep, 0, sizeof(proto_dep)); memset(&peic, 0, sizeof(pei_cmpt)); /* protocol name */ ProtName("Internet Printing Protocol", "ipp"); /* http dependence */ dep.name = "http"; dep.attr = "http.content_type"; dep.type = FT_STRING; dep.op = FT_OP_CNTD; dep.val.str = DMemMalloc(16); strcpy(dep.val.str, "application/ipp"); ProtDep(&dep); /* PEI components */ peic.abbrev = "url"; peic.desc = "Uniform Resource Locator"; ProtPeiComponent(&peic); peic.abbrev = "pdf"; peic.desc = "pdf file"; ProtPeiComponent(&peic); peic.abbrev = "pcl"; peic.desc = "pcl file"; ProtPeiComponent(&peic); /* dissectors registration */ ProtDissectors(IppDissector, NULL, NULL, NULL); return 0; }
static int SnoopDissector(FILE *fp, struct cap_ref *ref) { struct snoop_packet_header hdr; unsigned long hlen, len; packet *pkt; time_t tm = 0; struct timespec to; while (1) { /* read header */ hlen = fread(&hdr, 1, sizeof(struct snoop_packet_header), fp); if (hlen != sizeof(struct snoop_packet_header)) { if (hlen == 0) return 0; printf("Snoop file error\n"); return -1; } pkt = PktNew(); /* conver values */ hdr.tlen = ntohl(hdr.tlen); hdr.len = ntohl(hdr.len); hdr.blen = ntohl(hdr.blen); hdr.secs = ntohl(hdr.secs); hdr.usecs = ntohl(hdr.usecs); len = hdr.blen - hlen; ref->cnt++; pkt->raw = DMemMalloc(len+sizeof(unsigned long)*2+sizeof(char *)+4); len = fread(pkt->raw, 1, len, fp); pkt->raw_len = len; /* align 4b */ len = len + 4 - (len%4); *((unsigned long *)&(pkt->raw[len])) = ref->dlt; *((unsigned long *)&(pkt->raw[len+sizeof(unsigned long)])) = ref->cnt; *((char **)(&(pkt->raw[len+sizeof(unsigned long)*2]))) = ref->file_name; pkt->cap_sec = hdr.secs; pkt->cap_usec = hdr.usecs; pkt->serial = pkt_serial; /* crash info */ crash_pkt_cnt = ref->cnt; crash_ref_name = ref->file_name; /* decode */ if (!ciao) ProtDissec(pcap_prot_id, pkt); FlowSetGblTime(hdr.secs); /* next serial number */ pkt_serial++; if (time(NULL) > tm) { ReportSplash(); while (DispatchPeiPending() > DISP_PEI_MAX_QUEUE) { to.tv_sec = 0; to.tv_nsec = 300000000; /* wait some time */ while (nanosleep(&to, &to) != 0) ; ReportSplash(); } tm = time(NULL) + 2; } } return 0; }
static void RltmPolDissector(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { struct pcap_ref *ref = (struct pcap_ref *)user; packet *pkt; static time_t tm = 0; int offset; struct timespec to; struct pcap_pkthdr pckt_header; size_t nwrt, wcnt; pkt = PktNew(); ref->cnt++; pkt->raw = DMemMalloc(h->caplen+sizeof(unsigned long)*2+sizeof(char *)+sizeof(unsigned long)*2); memcpy(pkt->raw, bytes, h->caplen); pkt->raw_len = h->caplen; offset = 0; *((unsigned long *)&(pkt->raw[pkt->raw_len])) = ref->dlt; offset += sizeof(unsigned long); *((unsigned long *)&(pkt->raw[pkt->raw_len+offset])) = ref->cnt; offset += sizeof(unsigned long); if (savepcap) *((char **)&(pkt->raw[pkt->raw_len+offset])) = pcap_deb; else *((char **)&(pkt->raw[pkt->raw_len+offset])) = "Real Time"; offset += sizeof(char *); *((unsigned long *)&(pkt->raw[pkt->raw_len+offset])) = ref->ses_id; offset += sizeof(unsigned long); *((unsigned long *)&(pkt->raw[pkt->raw_len+offset])) = ref->pol_id; pkt->cap_sec = h->ts.tv_sec; pkt->cap_usec = h->ts.tv_usec; pkt->serial = pkt_serial; /* crash info */ crash_pkt_cnt = ref->cnt; /* decode */ /* save packet */ if (fp_pcap != NULL) { pckt_header.caplen = pkt->raw_len; pckt_header.len = pkt->raw_len; pckt_header.ts.tv_sec = pkt->cap_sec; pckt_header.ts.tv_usec = pkt->cap_usec; wcnt = 0; do { nwrt = fwrite(((char *)&pckt_header)+wcnt, 1, sizeof(struct pcap_pkthdr)-wcnt, fp_pcap); if (nwrt != -1) wcnt += nwrt; else break; } while (wcnt != sizeof(struct pcap_pkthdr)); wcnt = 0; 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); } ProtDissec(pol_prot_id, pkt); FlowSetGblTime(h->ts.tv_sec); /* next serial number */ pkt_serial++; if (time(NULL) > tm) { tm = time(NULL) + 5; ReportSplash(); while (DispatchPeiPending() > DISP_PEI_MAX_QUEUE) { to.tv_sec = 2; to.tv_nsec = 1; /* wait some time */ while (nanosleep(&to, &to) != 0) ; LogPrintf(LV_WARNING, "Possible data loss!"); ReportSplash(); } } }
static packet* IppDissector(packet *pkt) { http_msg *msg; pei *ppei; pei_component *cmpn; int ind, fd; unsigned char buff[IPP_BUFFER_SIZE]; char *pcl_file, *pdf_file; char cmd[IPP_FILENAME_PATH_SIZE*2]; ssize_t len; unsigned int offset; ipp_ver ver; FILE *pcl; struct stat fst; ppei = NULL; /* display info */ msg = (http_msg *)pkt->data; LogPrintf(LV_DEBUG, "IPP Dissector"); #ifdef XPL_CHECK_CODE if (msg->serial == 0) { LogPrintf(LV_FATAL, "IPP Dissector serial error"); exit(-1); } #endif /* check if post and if PCL file */ if (msg->mtd != HTTP_MT_POST || msg->req_body_size == 0) { /* free memory */ HttpMsgRemove(msg); HttpMsgFree(msg); PktFree(pkt); return NULL; } /* open body file */ fd = open(msg->req_body_file, O_RDONLY); if (fd == 0) { LogPrintf(LV_ERROR, "Can't open file:%s", msg->req_body_file); /* free memory */ HttpMsgRemove(msg); HttpMsgFree(msg); PktFree(pkt); return NULL; } len = read(fd, buff, IPP_BUFFER_SIZE); offset = 0; /* IPP version */ if (buff[0] == 1) { if (buff[1] == 0) { ver = IPP_1_0; } else if (buff[1] == 1) { ver = IPP_1_1; } else { LogPrintf(LV_WARNING, "Unknow version: %u.%u", buff[0], buff[1]); close(fd); /* free memory */ HttpMsgRemove(msg); HttpMsgFree(msg); PktFree(pkt); return NULL; } } else { LogPrintf(LV_WARNING, "Unknow version: %u.%u", buff[0], buff[1]); close(fd); /* free memory */ HttpMsgRemove(msg); HttpMsgFree(msg); PktFree(pkt); return NULL; } offset += 2; /* check if print job */ if (ntohs(*((unsigned short *)(buff+offset))) != PRINT_JOB) { close(fd); /* free memory */ HttpMsgRemove(msg); HttpMsgFree(msg); PktFree(pkt); return NULL; } offset += 2; offset += 4; /* skeep request id */ #warning "to improve" offset = ParseAttributes(buff, offset, len); /* i hope that IPP_BUFFER_SIZE is alwayse correct */ /* create PCL file */ pcl_file = DMemMalloc(IPP_FILENAME_PATH_SIZE); pdf_file = DMemMalloc(IPP_FILENAME_PATH_SIZE); sprintf(pcl_file, "%s/%s/ipp_%lu_%p_%i.pcl", ProtTmpDir(), IPP_TMP_DIR, time(NULL), msg, incr); sprintf(pdf_file, "%s/%s/ipp_%lu_%p_%i.pdf", ProtTmpDir(), IPP_TMP_DIR, time(NULL), msg, incr); incr++; pcl = fopen(pcl_file, "w+"); fwrite(buff+offset, 1, len-offset, pcl); len = read(fd, buff, IPP_BUFFER_SIZE); while (len != 0) { fwrite(buff, 1, len, pcl); len = read(fd, buff, IPP_BUFFER_SIZE); } fclose(pcl); close(fd); /* pdf conversion */ sprintf(cmd, "%s -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=%s %s", pcl6_path, pdf_file, pcl_file); system(cmd); fst.st_size = 0; stat(pdf_file, &fst); /* compose pei */ ppei = DMemMalloc(sizeof(pei)); PeiInit(ppei); ppei->prot_id = prot_id; ppei->serial = pkt->serial; ppei->time_cap = pkt->cap_sec; ppei->stack = ProtCopyFrame(pkt->stk, TRUE); /* url */ ind = 0; cmpn = DMemMalloc(sizeof(pei_component)); memset(cmpn, 0, sizeof(pei_component)); cmpn->eid = pei_url_id; cmpn->id = ind; cmpn->time_cap = msg->start_cap; cmpn->time_cap_end = msg->end_cap; cmpn->strbuf = msg->uri; msg->uri = NULL; ppei->components = cmpn; /* pdf */ ind++; cmpn->next = DMemMalloc(sizeof(pei_component)); cmpn = cmpn->next; memset(cmpn, 0, sizeof(pei_component)); cmpn->eid = pei_pdffile_id; cmpn->id = ind; cmpn->time_cap = msg->start_cap; cmpn->time_cap_end = msg->end_cap; cmpn->file_path = pdf_file; cmpn->file_size = fst.st_size; if (msg->error) cmpn->err = ELMT_ER_PARTIAL; /* pcl */ ind++; cmpn->next = DMemMalloc(sizeof(pei_component)); cmpn = cmpn->next; memset(cmpn, 0, sizeof(pei_component)); cmpn->eid = pei_pclfile_id; cmpn->id = ind; cmpn->time_cap = msg->start_cap; cmpn->time_cap_end = msg->end_cap; cmpn->file_path = pcl_file; cmpn->file_size = msg->req_body_size - offset; if (msg->error) cmpn->err = ELMT_ER_PARTIAL; /* free memory */ HttpMsgRemove(msg); HttpMsgFree(msg); PktFree(pkt); /* insert pei */ PeiIns(ppei); return NULL; }
static void PcapDissector(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { struct cap_ref *ref = (struct cap_ref *)user; int offset; packet *pkt; static time_t tm = 0; static time_t tstart = 0; static size_t tsize = 0; struct timespec to; FILE *fp; pkt = PktNew(); ref->cnt++; pkt->raw = DMemMalloc(h->caplen+sizeof(unsigned long)*2+sizeof(char *)+sizeof(unsigned long)*2); memcpy(pkt->raw, bytes, h->caplen); pkt->raw_len = h->caplen; tsize += h->caplen; offset = 0; *((unsigned long *)&(pkt->raw[pkt->raw_len])) = ref->dlt; offset += sizeof(unsigned long); *((unsigned long *)&(pkt->raw[pkt->raw_len+offset])) = ref->cnt; offset += sizeof(unsigned long); *((char **)&(pkt->raw[pkt->raw_len+offset])) = ref->file_name; offset += sizeof(char *); *((unsigned long *)&(pkt->raw[pkt->raw_len+offset])) = ref->ses_id; offset += sizeof(unsigned long); *((unsigned long *)&(pkt->raw[pkt->raw_len+offset])) = ref->pol_id; if (h->ts.tv_sec < 0) pkt->cap_sec = 0; else pkt->cap_sec = h->ts.tv_sec; pkt->cap_usec = h->ts.tv_usec; pkt->serial = pkt_serial; /* crash info */ crash_pkt_cnt = ref->cnt; crash_ref_name = ref->file_name; /* decode */ ProtDissec(pol_prot_id, pkt); FlowSetGblTime(h->ts.tv_sec); /* next serial number */ pkt_serial++; if (time(NULL) > tm) { tm = time(NULL); ReportSplash(); while (DispatchPeiPending() > DISP_PEI_MAX_QUEUE) { to.tv_sec = 2; to.tv_nsec = 1; /* wait some time */ while (nanosleep(&to, &to) != 0) ; ReportSplash(); } if (tstart == 0) { tstart = tm; } else { fp = fopen(file_status, "w+"); if (fp != NULL) { fprintf(fp, "s:%lu r:%lu\n", (unsigned long)tsize, (tm - tstart)); fclose(fp); } } tm += 5; } }
static int SdpParse(packet *pkt, int len, sdp_msg *msg) { bool in_media; int offset; int linelen; int next_offset; unsigned char type; unsigned char delim; char *tmp; int (*SdpAttr)(const char *, int, sdp_msg *); char *data; data = pkt->data; in_media = FALSE; offset = 0; while (offset < len) { /* * Find the end of the line. */ linelen = find_line_end_unquoted(data+offset, len - offset, &next_offset); /* * Line must contain at least e.g. "v=". */ if (linelen < 2) break; type = data[offset]; delim = data[offset + 1]; if (delim != '=') { LogPrintf(LV_WARNING, "Invalid SDP line (no '=' delimiter)"); LogPrintf(LV_DEBUG, "Type %c, %i, %s", type, offset, data+offset); offset += next_offset; continue; } /* * Attributes. */ SdpAttr = NULL; switch (type) { case 'v': SdpAttr = SdpProtocolVersion; break; case 'o': SdpAttr = SdpOwner; break; case 's': SdpAttr = SdpSessionName; break; case 'i': if (in_media) { SdpAttr = SdpMediaTitle; } else{ SdpAttr = SdpSessionInfo; } break; case 'u': SdpAttr = SdpUri; break; case 'e': SdpAttr = SdpEmail; break; case 'p': SdpAttr = SdpPhone; break; case 'c': SdpAttr = SdpConnectionInfo; break; case 'b': SdpAttr = SdpBandwidth; break; case 't': SdpAttr = SdpTime; break; case 'r': SdpAttr = SdpRepeatTime; break; case 'm': SdpAttr = SdpMedia; in_media = TRUE; break; case 'k': SdpAttr = SdpEncryptionKey; break; case 'a': if (in_media) { SdpAttr = SdpMediaAttribute; } else{ SdpAttr = SdpSessionAttribute; } break; case 'z': SdpAttr = SdpTimezone; break; default: break; } if (SdpAttr) { SdpAttr(data+offset + 2, linelen - 2, msg); } else { tmp = DMemMalloc(linelen + 1); memcpy(tmp, data + offset, linelen); tmp[linelen] = '\0'; LogPrintf(LV_WARNING, "Invalid SDP Attribute: %s", tmp); DMemFree(tmp); } offset += next_offset; } return 0; }
static int SdpMedia(const char *data, int len, sdp_msg *msg) { const char *next_token; const char *lineend; char number[256]; int tokenlen, token; short mcnt; mcnt = msg->transp.count; if (mcnt == SDP_MAX_RTP_CHANNELS) return -1; lineend = data + len; /* The first token media type */ tokenlen = get_token_len(data, lineend, &next_token); if (tokenlen == 0 || data[tokenlen] != ' ') { return -1; } msg->transp.type[mcnt] = SDP_MEDIA_UNKNOW; if (strncmp(data, "audio", tokenlen) == 0) { msg->transp.type[mcnt] = SDP_MEDIA_AUDIO; } else if (strncmp(data, "video", tokenlen) == 0) { msg->transp.type[mcnt] = SDP_MEDIA_VIDEO; } else { LogPrintf(LV_WARNING, "New media type"); } data = next_token; /* port */ tokenlen = get_token_len(data, lineend, &next_token); if (tokenlen == 0 || data[tokenlen] != ' ') { return -1; } token = find_chr(data, tokenlen, '/'); if (token != -1) { memcpy(number, data, token); number[token] = '\0'; msg->transp.port[mcnt] = atoi(number); LogPrintf(LV_WARNING, "Port count to be complete"); } else { msg->transp.port[mcnt] = atoi(data); } data = next_token; /* media protocol */ tokenlen = get_token_len(data, lineend, &next_token); if (tokenlen == 0 || data[tokenlen] != ' ') { return -1; } msg->transp.proto[mcnt] = DMemMalloc(tokenlen+1); memcpy(msg->transp.proto[mcnt], data, tokenlen); msg->transp.proto[mcnt][tokenlen] = '\0'; data = next_token; /* pt */ tokenlen = get_token_len(data, lineend, &next_token); if (strcmp(msg->transp.proto[mcnt], "RTP/AVP") == 0) { while (tokenlen != 0) { #if 0 memcpy(number, data, tokenlen); number[tokenlen] = '\0'; msg->transp.media[mcnt].pt[msg->transp.media[mcnt].pt_count] = atoi(number); #else msg->transp.media[mcnt].pt[msg->transp.media[mcnt].pt_count] = atoi(data); #endif msg->transp.media[mcnt].pt_count++; data = next_token; tokenlen = get_token_len(data, lineend, &next_token); } } msg->transp.count++; return 0; }
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; }
static int SnoopDissector(FILE *fp, struct cap_ref *ref) { struct snoop_packet_header hdr; unsigned long hlen, len; packet *pkt; time_t tm = 0; static time_t tstart = 0; static size_t tsize = 0; int offset; struct timespec to; FILE *fpl; while (1) { /* read header */ hlen = fread(&hdr, 1, sizeof(struct snoop_packet_header), fp); if (hlen != sizeof(struct snoop_packet_header)) { if (hlen == 0) return 0; printf("Snoop file error\n"); return -1; } pkt = PktNew(); /* conver values */ hdr.tlen = ntohl(hdr.tlen); hdr.len = ntohl(hdr.len); hdr.blen = ntohl(hdr.blen); hdr.secs = ntohl(hdr.secs); hdr.usecs = ntohl(hdr.usecs); len = hdr.blen - hlen; ref->cnt++; pkt->raw = DMemMalloc(len+sizeof(unsigned long)*2+sizeof(char *)+4); len = fread(pkt->raw, 1, len, fp); pkt->raw_len = len; tsize += len; offset = 0; *((unsigned long *)&(pkt->raw[len])) = ref->dlt; offset += sizeof(unsigned long); *((unsigned long *)&(pkt->raw[len+offset])) = ref->cnt; offset += sizeof(unsigned long); *((char **)(&(pkt->raw[len+offset]))) = ref->file_name; offset += sizeof(char *); *((unsigned long *)&(pkt->raw[len+offset])) = ref->ses_id; offset += sizeof(unsigned long); *((unsigned long *)&(pkt->raw[len+offset])) = ref->pol_id; pkt->cap_sec = hdr.secs; pkt->cap_usec = hdr.usecs; pkt->serial = pkt_serial; /* crash info */ crash_pkt_cnt = ref->cnt; crash_ref_name = ref->file_name; /* decode */ ProtDissec(pol_prot_id, pkt); FlowSetGblTime(hdr.secs); /* next serial number */ pkt_serial++; if (time(NULL) > tm) { tm = time(NULL); ReportSplash(); while (DispatchPeiPending() > DISP_PEI_MAX_QUEUE) { to.tv_sec = 2; to.tv_nsec = 1; /* wait some time */ while (nanosleep(&to, &to) != 0) ; ReportSplash(); } if (tstart == 0) tstart = tm; else { fpl = fopen(file_status, "w+"); if (fpl != NULL) { fprintf(fpl, "s:%lu r:%lu\n", (unsigned long)tsize, (tm - tstart)); fclose(fpl); } } tm += 5; } } return 0; }
static packet* RtpDissector(int flow_id) { struct in_addr ip_addr; struct in6_addr ipv6_addr; const pstack_f *udp, *ip; ftval port_src, port_dst, offset, phone; char ips_str[INET6_ADDRSTRLEN], ipd_str[INET6_ADDRSTRLEN]; rtp_priv *priv; packet *pkt; int rid, ret, gid, rtcp_fid; cmp_val rip, rport; char tmp_file_1[256]; char tmp_file_2[256]; char media_file_1[256]; char media_file_2[256]; char media_conv[256]; FILE *fp_pcap_1, *fp_pcap_2, *fp_pcap; struct pcap_file_header fh; struct pcappkt_hdr pckt_header; struct stat fsbuf; char cmd[1024]; size_t nwrt, wcnt; time_t tstart, tend; pei *ppei; pei_component *cmpn; bool aud1, aud2; unsigned short pkt_cnt; LogPrintf(LV_DEBUG, "RTP id: %d", flow_id); gid = FlowGrpId(flow_id); priv = DMemMalloc(sizeof(rtp_priv)); memset(priv, 0, sizeof(rtp_priv)); udp = FlowStack(flow_id); ip = ProtGetNxtFrame(udp); ProtGetAttr(udp, uport_src_id, &port_src); ProtGetAttr(udp, uport_dst_id, &port_dst); priv->port_s = port_src.uint16; priv->port_d = port_dst.uint16; priv->stack = udp; if (priv->port_s != port_dst.uint16) priv->port_diff = TRUE; priv->ipv6 = TRUE; if (ProtFrameProtocol(ip) == ip_id) priv->ipv6 = FALSE; if (priv->ipv6 == FALSE) { ProtGetAttr(ip, ip_src_id, &priv->ip_s); ProtGetAttr(ip, ip_dst_id, &priv->ip_d); ip_addr.s_addr = priv->ip_s.uint32; inet_ntop(AF_INET, &ip_addr, ips_str, INET6_ADDRSTRLEN); ip_addr.s_addr = priv->ip_d.uint32; inet_ntop(AF_INET, &ip_addr, ipd_str, INET6_ADDRSTRLEN); } else { ProtGetAttr(ip, ipv6_src_id, &priv->ip_s); ProtGetAttr(ip, ipv6_dst_id, &priv->ip_d); memcpy(ipv6_addr.s6_addr, priv->ip_s.ipv6, sizeof(priv->ip_s.ipv6)); inet_ntop(AF_INET6, &ipv6_addr, ips_str, INET6_ADDRSTRLEN); memcpy(ipv6_addr.s6_addr, priv->ip_d.ipv6, sizeof(priv->ip_d.ipv6)); inet_ntop(AF_INET6, &ipv6_addr, ipd_str, INET6_ADDRSTRLEN); } LogPrintf(LV_DEBUG, "\tSRC: %s:%d", ips_str, port_src.uint16); LogPrintf(LV_DEBUG, "\tDST: %s:%d", ipd_str, port_dst.uint16); /* RTCP flow search */ rid = -1; rtcp_fid = -1; if (rtcp_id != -1) { rid = GrpRuleNew(flow_id); if (priv->ipv6 == TRUE) { rip.prot = ipv6_id; rip.att = ipv6_dst_id; FTCopy(&rip.val, &priv->ip_d, FT_IPv6); } else { rip.prot = ip_id; rip.att = ip_dst_id; rip.val.uint32 = priv->ip_d.uint32; } rport.prot = udp_id; rport.att = uport_dst_id; port_dst.uint16++; rport.val.int16 = port_dst.uint16; GrpRule(rid, 2, &rip, &rport); if (priv->ipv6 == TRUE) { rip.att = ipv6_src_id; } else { rip.att = ip_src_id; } rport.att = uport_src_id; GrpRule(rid, 2, &rip, &rport); GrpRuleCmplt(rid); LogPrintf(LV_DEBUG, "Rule rtcp %i, port:%i", rid, port_dst.uint16); } /* put packets in the pcap files */ sprintf(tmp_file_1, "%s/%s/rtp_1_%d_%lu_%d.pcap", ProtTmpDir(), RTP_TMP_DIR, incr, time(NULL), port_src.uint16); sprintf(tmp_file_2, "%s/%s/rtp_2_%d_%lu_%d.pcap", ProtTmpDir(), RTP_TMP_DIR, incr, time(NULL), port_src.uint16); sprintf(media_conv, "%s/%s/rtp_%d_%lu_%d", ProtTmpDir(), RTP_TMP_DIR, incr, time(NULL), port_src.uint16); incr++; fp_pcap_1 = fopen(tmp_file_1, "w"); fp_pcap_2 = fopen(tmp_file_2, "w"); memset(&fh, 0, sizeof(struct pcap_file_header)); fh.magic = 0xA1B2C3D4; fh.version_major = PCAP_VERSION_MAJOR; fh.version_minor = PCAP_VERSION_MINOR; fh.snaplen = 65535; fh.linktype = DLT_RAW; if (fp_pcap_1 != NULL) { fwrite((char *)&fh, 1, sizeof(struct pcap_file_header), fp_pcap_1); } if (fp_pcap_2 != NULL) { fwrite((char *)&fh, 1, sizeof(struct pcap_file_header), fp_pcap_2); } /* first packet */ pkt_cnt = 0; pkt = FlowGetPkt(flow_id); /* start time */ if (pkt != NULL) { /* pei definition */ PeiNew(&ppei, rtp_id); PeiCapTime(ppei, pkt->cap_sec); PeiMarker(ppei, pkt->serial); PeiStackFlow(ppei, udp); tstart = pkt->cap_sec; } while (pkt != NULL) { pkt_cnt++; /* check if exit rtcp "stream" */ if (rid != -1) { rtcp_fid = GrpLink(gid); if (rtcp_fid != -1) { FlowSyncr(flow_id, FALSE); FlowSyncr(rtcp_fid, FALSE); PeiAddStkGrp(ppei, FlowStack(rtcp_fid)); rid = -1; } } tend = pkt->cap_sec; if (priv->ipv6) { ip = ProtStackSearchProt(pkt->stk, ipv6_id); ProtGetAttr(ip, ipv6_offset_id, &offset); wcnt = offset.uint32; } else { ip = ProtStackSearchProt(pkt->stk, ip_id); ProtGetAttr(ip, ip_offset_id, &offset); wcnt = offset.uint32; } pckt_header.caplen = pkt->raw_len - wcnt; pckt_header.len = pkt->raw_len - wcnt; pckt_header.tv_sec = pkt->cap_sec; pckt_header.tv_usec = pkt->cap_usec; if (RtpClientPkt(priv, pkt)) { fp_pcap = fp_pcap_1; } else { fp_pcap = fp_pcap_2; } if (fp_pcap != NULL) { wcnt = 0; do { nwrt = fwrite(((char *)&pckt_header)+wcnt, 1, sizeof(struct pcappkt_hdr)-wcnt, fp_pcap); if (nwrt != -1) wcnt += nwrt; else break; } while (wcnt != sizeof(struct pcappkt_hdr)); wcnt = offset.uint32; do { nwrt = fwrite(((char *)pkt->raw)+wcnt, 1, pkt->raw_len-wcnt, fp_pcap); if (nwrt != -1) wcnt += nwrt; else break; } while (wcnt != pkt->raw_len); } PktFree(pkt); pkt = FlowGetPkt(flow_id); } /* close file */ if (fp_pcap_1 != NULL) fclose(fp_pcap_1); if (fp_pcap_1 != NULL) fclose(fp_pcap_2); /* remove rtcp rule */ if (rid != -1) { rtcp_fid = GrpLink(gid); if (rtcp_fid != -1) { FlowSyncr(flow_id, FALSE); FlowSyncr(rtcp_fid, FALSE); PeiAddStkGrp(ppei, FlowStack(rtcp_fid)); rid = -1; } else { GrpRuleRm(rid); } } /* decode rtcp packet */ if (rtcp_fid != -1) { /* new priv data */ priv->port_s++; priv->port_d++; pkt = FlowGetPkt(rtcp_fid); while (pkt != NULL) { pkt = ProtDissecPkt(rtcp_id, pkt); if (pkt != NULL) { ProtGetAttr(pkt->stk, rtcp_phone_id, &phone); if (RtcpClientPkt(priv, pkt)) { strcpy(ipd_str, phone.str); } else { strcpy(ips_str, phone.str); } PktFree(pkt); } pkt = FlowGetPkt(rtcp_fid); } } /* audio decoding */ sprintf(cmd, "./videosnarf -i %s -o %s 2>/dev/null 1>/dev/null", tmp_file_1, tmp_file_1); ret = system(cmd); if (ret == -1) { LogPrintf(LV_WARNING, "videosnarf failed"); } else if (WEXITSTATUS(ret) != 0) { LogPrintf(LV_WARNING, "videosnarf crash"); } sprintf(cmd, "./videosnarf -i %s -o %s 2>/dev/null 1>/dev/null", tmp_file_2, tmp_file_2); ret = system(cmd); if (ret == -1) { LogPrintf(LV_WARNING, "videosnarf failed"); } else if (WEXITSTATUS(ret) != 0) { LogPrintf(LV_WARNING, "videosnarf crash"); } /* delete temporary files */ #if DEBUG_RM remove(tmp_file_1); remove(tmp_file_2); #endif /* media file check */ sprintf(media_file_1, "%s-media-1.wav", tmp_file_1); sprintf(media_file_2, "%s-media-1.wav", tmp_file_2); /* complete pei */ /* from */ PeiNewComponent(&cmpn, pei_from); PeiCompCapTime(cmpn, tstart); PeiCompAddStingBuff(cmpn, ipd_str); PeiAddComponent(ppei, cmpn); /* to */ PeiNewComponent(&cmpn, pei_to); PeiCompCapTime(cmpn, tstart); PeiCompAddStingBuff(cmpn, ips_str); PeiAddComponent(ppei, cmpn); /* duration */ sprintf(cmd, "%lu", tend-tstart); PeiNewComponent(&cmpn, pei_duration); PeiCompCapTime(cmpn, tstart); PeiCompAddStingBuff(cmpn, cmd); PeiAddComponent(ppei, cmpn); /* audio from */ aud2 = FALSE; if (stat(media_file_2, &fsbuf) == 0) { aud2 = TRUE; /* convert to be used with lame */ sprintf(tmp_file_2, "%s_2.wav", media_conv); sprintf(cmd, "sox %s -s %s 2>/dev/null 1>/dev/null", media_file_2, tmp_file_2); ret = system(cmd); #if DEBUG_RM remove(media_file_2); #endif /* mp3 conversion */ sprintf(media_file_2, "%s_2.mp3", media_conv); sprintf(cmd, "lame --quiet -h %s %s 2>/dev/null 1>/dev/null", tmp_file_2, media_file_2); ret = system(cmd); if (ret == -1) { LogPrintf(LV_WARNING, "lame failed"); } else if (WEXITSTATUS(ret) != 0) { LogPrintf(LV_WARNING, "lame crash (%i): %s", WEXITSTATUS(ret), cmd); } if (stat(media_file_2, &fsbuf) == 0) { PeiNewComponent(&cmpn, pei_audio_from); PeiCompCapTime(cmpn, tstart); PeiCompCapEndTime(cmpn, tend); PeiCompAddFile(cmpn, "audio_caller.mp3", media_file_2, fsbuf.st_size); PeiAddComponent(ppei, cmpn); } sprintf(media_file_2, "%s_stereo_2.wav", media_conv); sprintf(cmd, "sox %s -c 2 %s pan 1 2>/dev/null 1>/dev/null", tmp_file_2, media_file_2); ret = system(cmd); #if DEBUG_RM remove(tmp_file_2); #endif } /* audio to */ aud1 = FALSE; if (stat(media_file_1, &fsbuf) == 0) { aud1 = TRUE; /* convert to be used with lame */ sprintf(tmp_file_1, "%s_1.wav", media_conv); sprintf(cmd, "sox %s -s %s 2>/dev/null 1>/dev/null", media_file_1, tmp_file_1); ret = system(cmd); #if DEBUG_RM remove(media_file_1); #endif /* mp3 conversion */ sprintf(media_file_1, "%s_1.mp3", media_conv); sprintf(cmd, "lame --quiet -h %s %s 2>/dev/null 1>/dev/null", tmp_file_1, media_file_1); ret = system(cmd); if (ret == -1) { LogPrintf(LV_WARNING, "lame failed"); } else if (WEXITSTATUS(ret) != 0) { LogPrintf(LV_WARNING, "lame crash (%i): %s", WEXITSTATUS(ret), cmd); } if (stat(media_file_1, &fsbuf) == 0) { PeiNewComponent(&cmpn, pei_audio_to); PeiCompCapTime(cmpn, tstart); PeiCompCapEndTime(cmpn, tend); PeiCompAddFile(cmpn, "audio_called.mp3", media_file_1, fsbuf.st_size); PeiAddComponent(ppei, cmpn); } sprintf(media_file_1, "%s_stereo_1.wav", media_conv); sprintf(cmd, "sox %s -c 2 %s pan -1 2>/dev/null 1>/dev/null", tmp_file_1, media_file_1); ret = system(cmd); #if DEBUG_RM remove(tmp_file_1); #endif } /* mix audio */ if (aud2 || aud1) { /* mix two audio files */ sprintf(tmp_file_1, "%s_mix.wav", media_conv); sprintf(tmp_file_2, "%s_mix.mp3", media_conv); if (aud1 == FALSE) { sprintf(cmd, "sox %s %s 2>/dev/null 1>/dev/null", media_file_2, tmp_file_1); } else if (aud2 == FALSE) { sprintf(cmd, "sox %s %s 2>/dev/null 1>/dev/null", media_file_1, tmp_file_1); } else { sprintf(cmd, "sox -m %s %s -s %s 2>/dev/null 1>/dev/null", media_file_2, media_file_1, tmp_file_1); } ret = system(cmd); if (ret == -1) { LogPrintf(LV_WARNING, "sox failed"); } else if (WEXITSTATUS(ret) != 0) { LogPrintf(LV_WARNING, "sox mix crash: %s", cmd); } /* mp3 conversion */ sprintf(cmd, "lame --quiet -h %s %s 2>/dev/null 1>/dev/null", tmp_file_1, tmp_file_2); ret = system(cmd); /* delete temporary files */ #if DEBUG_RM remove(media_file_1); remove(media_file_2); remove(tmp_file_1); #endif if (stat(tmp_file_2, &fsbuf) == 0) { PeiNewComponent(&cmpn, pei_audio_mix); PeiCompCapTime(cmpn, tstart); PeiCompCapEndTime(cmpn, tend); PeiCompAddFile(cmpn, "audio_mix.mp3", tmp_file_2, fsbuf.st_size); PeiAddComponent(ppei, cmpn); } } /* insert pei */ PeiIns(ppei); /* free */ DMemFree(priv); LogPrintf(LV_DEBUG, "RTP... bye bye fid:%d (pkt:%i)", flow_id, pkt_cnt); return NULL; }
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; }