ERF和PCAP文件中的ipv4流包统计与汇聚

       跟着学校老师搞流量识别时写的,能把PCAP或ERF文件中的流分组后排序生成新的文件,思路很乱,好像还有点bug,分析一个114MB的PCAP文件没问题,但是分析1个2.7G的大数据集,在写入新文件的时候就出问题了,Wireshark打不开。有空再改改。

#include <winsock2.h>
#include <map>
#include <list>
#include <vector>
#include <cstdio>
#include <omp.h>
#include <algorithm>
#include <cstdlib>
using namespace std;
#define TRACE_PCAP		1
#define TRACE_ERF		2

#define LINK_ETH		0x00000001
#define LINK_11C		0x0000000B

#define PROT_IP			0x0800
#define PROT_TCP		0x06
#define PROT_UDP		0x11
#define PROT_ICMP		0x01

#define PCAP_HDR_LEN	16
#define ERF_HDR_LEN		18					//including eth protocol header
#define ETH_HDR_LEN		14
#define C11_HDR_LEN		8

#define UM_FLOW			WM_USER + 100

#define BUFF_LEN		204800
#define HASH_LEN		2000000
#define MICE_FLOW_PKTS	4

struct thread_param
{
    u_short	thread_id;
    LARGE_INTEGER fp_start;
    LARGE_INTEGER fp_end;
};
struct eth_header
{
    unsigned char		h_dest[6]; /* destination eth addr */
    unsigned char		h_source[6]; /* source ether addr */
    unsigned short		h_proto; /* packet type ID field */
};

struct c11_header
{
    unsigned char		h_unkown[6]; /*  */
    unsigned short		h_proto; /* packet type ID field */
};

struct ip_header
{
    unsigned char     iphVerLen;      // Version and length
    unsigned char     ipTOS;          // Type of service
    unsigned short    ipLength;       // Total datagram length
    unsigned short    ipID;		      // Identification
    unsigned short    ipFlags;	      // Flags
    unsigned char     ipTTL;	      // Time to live
    unsigned char     ipProtocol;	  // Protocol
    unsigned short    ipChecksum;     // Header checksum
    unsigned long     ipSource;       // Source address
    unsigned long     ipDestination;  // Destination address
};

struct tcp_header
{
    unsigned short			sourcePort;			// Source Port
    unsigned short			destinationPort;	// Destination Port
    unsigned long			sequenceNumber;		// Number of Sequence
    unsigned long			acknowledgeNumber;	// Number of aknowledge
    unsigned char			    dataoffset;			// Pointer to data
    unsigned char			    flags;				// Flags
    unsigned short			windows;			// Size of window
    unsigned short			checksum;			// Total checksum
    unsigned short			urgentPointer;		// Urgent pointer
};

struct udp_header
{
    unsigned short			sourcePort;			// Source Port
    unsigned short			destinationPort;	// Destination Port
    unsigned short			len;				// Total length
    unsigned short			checksum;			// Total checksum
};

struct pcap_file_header
{
    unsigned long			magic;
    unsigned short			version_major;
    unsigned short			version_minor;
    unsigned long			thiszone;
    unsigned long			sigfigs;
    unsigned long			snaplen;
    unsigned long			linktype;
};

struct pcap_pkthdr
{
    unsigned long			sec;
    unsigned long			usec;
    unsigned long			cap_len;
    unsigned long			len;
};

struct erf_pkthdr
{
    unsigned long			usec;
    unsigned long			sec;
    unsigned char			type;
    unsigned char			flags;
    unsigned short			rlen;
    unsigned short			lctr;
    unsigned short			wlen;
};

struct db_pkt
{
    unsigned long			sec;
    unsigned long			usec;
    char					src_ip[20];
    char					dst_ip[20];
    unsigned short			src_port;
    unsigned short			dst_port;
    char					trs_prot[8];
    unsigned short			pkt_len;
};

struct trns_pkt_info
{
    unsigned long			sec;
    unsigned long			usec;
    unsigned long			src_ip;			// Source address
    unsigned long			dst_ip;			// Destination address
    unsigned short			src_port;		//Source port
    unsigned short			dst_port;		//Destination port
    unsigned char			  trs_prot;
    unsigned short			pkt_len;
    unsigned long             len;
    char*           buff;
};

struct flow_info
{
    unsigned long			id;
    unsigned long			src_ip;			// Source address
    unsigned long			dst_ip;			// Destination address
    unsigned short			src_port;		//Source port
    unsigned short			dst_port;		//Destination port
    unsigned long			n_pkt;			//Number of packets
    unsigned int			f_start;		//start position in the flow file
    unsigned int			f_end;			//end  position in the flow file
};

int ipcmp(const unsigned long& ip1,const unsigned long& ip2)
{
        if(   (ip1&0x000000ff)          <  (ip2&0x000000ff)           ) return -1;
        if(   (ip1&0x000000ff)          >  (ip2&0x000000ff)           ) return 1;
        if(   (ip1&0x0000ff00)>>8   <  (ip2&0x0000ff00)>>8    ) return -1;
        if(   (ip1&0x0000ff00)>>8   >  (ip2&0x0000ff00)>>8    ) return 1;
        if(   (ip1&0x00ff0000)>>16 <  (ip2&0x00ff0000)>>16  ) return -1;
        if(   (ip1&0x00ff0000)>>16 >  (ip2&0x00ff0000)>>16  ) return 1;
        if(   (ip1&0xff000000)>>24 <  (ip2&0xff000000)>>24  ) return -1;
        if(   (ip1&0xff000000)>>24 >  (ip2&0xff000000)>>24  ) return 1;
        return 0;
}

struct session
{
    unsigned long			ip1;
    unsigned long			ip2;  //ip1 always < ip2
    unsigned short			port1;
    unsigned short			port2;
    bool operator <(const session& x) const
    {

        if (ipcmp(ip1,x.ip1)<0) return true;
        if (ipcmp(ip1,x.ip1)>0) return false;
        if (ipcmp(ip2,x.ip2)<0) return true;
        if (ipcmp(ip2,x.ip2)>0) return false;
        /*
        if (ip1<x.ip1) return true;
        if (ip1>x.ip1) return false;
        if (ip2<x.ip2) return true;
        if (ip2>x.ip2) return false;
        */
        if (port1<x.port1) return true;
        if (port1>x.port1) return false;
        if (port2<x.port2) return true;
        if (port2>x.port2) return false;
        return false;
    }
};

map<session,list<trns_pkt_info> >g_flowmap;
char		g_tracefile[MAX_PATH] = "1.pcap";
int			g_tracetype = TRACE_PCAP;
u_short		g_linktype = LINK_ETH;
FILE		*fp_trace = NULL;
pcap_file_header g_fhdr;

long NextTransPacket(trns_pkt_info &pkt, FILE *fp_trace)
{
    int cap_len;								//cap packet length does not include format header
    char *buff, *p;
    long res = 0;
    memset(&pkt, 0, sizeof(pkt));
    if (!fp_trace)return 0;
    if (feof(fp_trace))return 0;
    if (g_tracetype == TRACE_PCAP)
    {
        struct pcap_pkthdr pkthdrp;
        if ((fread((void *)&pkthdrp, 1, sizeof(struct pcap_pkthdr), fp_trace)) < sizeof(struct pcap_pkthdr))
            return 0;
        cap_len = pkthdrp.cap_len;				//The cap_len of a pcap packet does not include the pcap header, big-endian
        pkt.sec = pkthdrp.sec;
        pkt.usec = pkthdrp.usec;
        res = cap_len + sizeof(struct pcap_pkthdr);
    }
    else if (g_tracetype == TRACE_ERF)
    {
        struct erf_pkthdr pkthdre;
        if ((fread((void *)&pkthdre, 1, sizeof(struct erf_pkthdr), fp_trace) )< sizeof(struct erf_pkthdr))
            return 0;
        cap_len = ntohs(pkthdre.rlen) - sizeof(struct erf_pkthdr) - 2;			//The rlen of a erf packet includes the erf header,little-endian
        pkt.sec = ntohl(pkthdre.sec);
        pkt.usec = ntohl(pkthdre.usec);
        fseek(fp_trace, 2, SEEK_CUR);											//Skip eth protocol header
        res = ntohs(pkthdre.rlen);
    }

    buff = (char *)malloc(cap_len);
    u_short link_prot;
    struct ip_header *iph;
    struct eth_header *ethh;
    struct c11_header *c11h;
    struct tcp_header *tcph;
    struct udp_header *udph;
    char *pHeader;
//	in_addr addr;
    unsigned int IPHeaderLength;

    if (fread(buff, 1, cap_len, fp_trace) < cap_len)
        return FALSE;
    pkt.buff=(char *)malloc(res);
    fseek(fp_trace,-res,SEEK_CUR);
    fread(pkt.buff,1,res,fp_trace);
    pkt.len=res;
    pHeader = buff;
    if (g_linktype == LINK_11C)
    {
        c11h = (struct c11_header *)pHeader;
        link_prot = ntohs(c11h->h_proto);
    }
    else
    {
        ethh = (struct eth_header *)pHeader;
        link_prot = ntohs(ethh->h_proto);
        if (link_prot == 0x0081)				//VLAN tag
        {
            pHeader += 4;
            ethh = (struct eth_header *)pHeader;
            link_prot = ntohs(ethh->h_proto);
        }
    }
    if (link_prot == PROT_IP)  //IP packet
    {
        pHeader += (g_linktype == LINK_11C) ? sizeof(struct c11_header) : sizeof(struct eth_header);
        iph = (struct ip_header *)pHeader;
        IPHeaderLength = ((iph->iphVerLen) & 0x0F) * 4;
        pkt.src_ip = iph->ipSource;
        pkt.dst_ip = iph->ipDestination;
        pkt.trs_prot = iph->ipProtocol;
        if (iph->ipProtocol == PROT_TCP)  //TCP packet
        {
            pHeader += IPHeaderLength;
            tcph = (struct tcp_header *)pHeader;
            pkt.src_port = ntohs(tcph->sourcePort);
            pkt.dst_port = ntohs(tcph->destinationPort);
            pkt.pkt_len = ntohs(iph->ipLength) - IPHeaderLength - sizeof(struct tcp_header);
        }
        else if (iph->ipProtocol == PROT_UDP)  //UDP packet
        {
            pHeader += IPHeaderLength;
            udph = (struct udp_header *)pHeader;
            pkt.src_port = ntohs(udph->sourcePort);
            pkt.dst_port = ntohs(udph->destinationPort);
            pkt.pkt_len = ntohs(iph->ipLength) - IPHeaderLength - sizeof(struct udp_header);
        }
    }
    free(buff);
    return res;
}


void ReadFlowFile()
{
    fp_trace=fopen(g_tracefile,"rb");
    if (!fp_trace)return;
	if (g_tracetype == TRACE_PCAP)
	{
		fread((void *)&g_fhdr, 1, sizeof(pcap_file_header), fp_trace);
		g_linktype = g_fhdr.linktype;
	}
    trns_pkt_info pkt;
    long res;
    session tmp;
    while(res=NextTransPacket(pkt,fp_trace))
    {
       if(pkt.src_ip==0||pkt.dst_ip==0) continue;
        pkt.buff=(char *)malloc(res);
        fseek(fp_trace,-res,SEEK_CUR);
        fread(pkt.buff,1,res,fp_trace);
        pkt.len=res;
       if(ipcmp(pkt.src_ip,pkt.dst_ip)<0)
       //if(pkt.src_ip<pkt.dst_ip)
        {
            tmp.ip1=pkt.src_ip;
            tmp.ip2=pkt.dst_ip;
            tmp.port1=pkt.src_port;
            tmp.port2=pkt.dst_port;
        }
        else
        {
            tmp.ip1=pkt.dst_ip;
            tmp.ip2=pkt.src_ip;
            tmp.port1=pkt.dst_port;
            tmp.port2=pkt.src_port;
        }
        if(!g_flowmap.count(tmp))
        {
            list<trns_pkt_info> li;
            li.push_back(pkt);
            g_flowmap[tmp]=li;
        }
        else
        {
            g_flowmap[tmp].push_back(pkt);
            pkt.buff=NULL;
        }
    }
    fclose(fp_trace);
    fp_trace=NULL;
}
void ShowAllFlows()
{
    session tmp;
    in_addr addr1,addr2;
    printf("共有%d组数据\n",g_flowmap.size());
    system("PAUSE");
    map<session,list<trns_pkt_info> >::iterator it;
    int i;
    for(it=g_flowmap.begin(),i=1;it!=g_flowmap.end();it++,i++)
    {
        tmp=it->first;
        printf("\n----------------------------------\n");
        printf("第%d组数据:\n",i);
        memcpy(&addr1,&tmp.ip1,4);
        memcpy(&addr2,&tmp.ip2,4);
        printf("ip1:%s  port1:%d\n",inet_ntoa(addr1),tmp.port1);
        printf("ip2:%s  port2:%d\n",inet_ntoa(addr2),tmp.port2);
        printf("共有%d个包:\n",it->second.size());
        for(list<trns_pkt_info>::iterator j=it->second.begin();j!=it->second.end();j++)
        {
            memcpy(&addr1,&j->src_ip,4);
            memcpy(&addr2,&j->dst_ip,4);
            printf("src:%s port:%d  ",inet_ntoa(addr1),j->src_port);
            printf("dst:%s port:%d  \n",inet_ntoa(addr2),j->dst_port);
        }
        printf("----------------------------------\n");
        system("PAUSE");
    }
}
void ConvergeFlows()
{
    char pkt_fname[MAX_PATH];
	char buff[BUFF_LEN];
	if(g_tracetype == TRACE_PCAP)
		sprintf(pkt_fname, "%s.pkt.pcap", g_tracefile);
	else
		sprintf(pkt_fname, "%s.pkt.erf", g_tracefile);
    FILE *fp_pkt = fopen(pkt_fname, "wb");
	if (g_tracetype == TRACE_PCAP)
	{
	     struct pcap_pkthdr pkthdrp;
		fwrite((void *)&g_fhdr, 1, sizeof(struct pcap_file_header), fp_pkt);
	}
    map<session,list<trns_pkt_info> >::iterator it;
    trns_pkt_info pkt;
    for(it=g_flowmap.begin();it!=g_flowmap.end();it++)
    {
        for(list<trns_pkt_info>::iterator j=it->second.begin();j!=it->second.end();j++)
        {
            pkt=*j;
            fwrite(pkt.buff, sizeof(char), pkt.len, fp_pkt);
        }
    }
    fclose(fp_pkt);
}
int main()
{
    ReadFlowFile();
   // ShowAllFlows();
    ConvergeFlows();
}

  

posted @ 2016-05-19 17:21  CodeMIRACLE  阅读(479)  评论(0编辑  收藏  举报