c语言:将pcap数据包按域名进行拆分

实现功能:

提取一个pcap文件里的每个pcap数据包的五元组和根域名,插入到哈希表。
提取一个pcap文件里的每个pcap数据包的五元组,去哈希表中查找,如果可以查到,取出对应的根域名,并且输出为pcap数据包,名字是根域名。

以下为一些小记:(判断一个数据包是否有域名!
用一个数组记录已存在的数据包,再决定进行新建pcap还是追加。
根域名数组里有,说明已经有了pcap包,追加在后面。
根域名数组里没有,新建一个。
tmp代表这个根域名在数组的什么位置。)

代码如下:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<netinet/in.h>
typedef int32_t bpf_int32;
typedef u_int32_t bpf_u_int32;
typedef u_int16_t u_short;
typedef u_int32_t u_int32;
typedef u_int16_t u_int16;
typedef u_int8_t u_int8;
char tempSrcIp[256];//存储转化后的字符地址。
char tempDstIp[256];
//pacp文件头结构体
struct pcap_file_header
{
    bpf_u_int32 magic;       /* 0xa1b2c3d4 */
    u_short version_major;   /* magjor Version 2 */
    u_short version_minor;   /* magjor Version 4 */
    bpf_int32 thiszone;      /* gmt to local correction */
    bpf_u_int32 sigfigs;     /* accuracy of timestamps */
    bpf_u_int32 snaplen;     /* max length saved portion of each pkt */
    bpf_u_int32 linktype;    /* data link type (LINKTYPE_*) */
};

//时间戳
struct time_val
{
    int tv_sec;         /* seconds 含义同 time_t 对象的值 */
    int tv_usec;        /* and microseconds */
};

//pcap数据包头结构体
struct pcap_pkthdr
{
    struct time_val ts;  /* time stamp */
    bpf_u_int32 caplen; /* length of portion present */
    bpf_u_int32 len;    /* length this packet (off wire) */
};

//IP数据报头 20字节
typedef struct IPHeader_t
{ //IP数据报头
    u_int8 Ver_HLen;       //版本+报头长度
    u_int8 TOS;            //服务类型
    u_int16 TotalLen;       //总长度
    u_int16 ID; //标识
    u_int16 Flag_Segment;   //标志+片偏移
    u_int8 TTL;            //生存周期
    u_int8 Protocol;       //协议类型
    u_int16 Checksum;       //头部校验和
    u_int32 SrcIP; //源IP地址
    u_int32 DstIP; //目的IP地址
} IPHeader_t;

//TCP/UDP数据
typedef struct TCPUDPHeader_t
{
    u_int16_t SrcPort;     // 源端口号16bit
    u_int16_t DstPort;    // 目的端口号16bit
   
}TCPUDPHeader_t;

typedef struct Quintet
{
	u_int32 SrcIP; //源IP地址
	u_int32 DstIP; //目的IP地址
	u_int16_t SrcPort;     // 源端口号16bit
	u_int16_t DstPort;    // 目的端口号16bit
	u_int8 Protocol;       //协议类型
}Quintet_t;

struct NODE{//定义结点
    char * tuple;
	char * dm_host;
	struct NODE *next;
} ;

struct wuyuan   //用来保存转换后的结果
{
	char * srcip;
	char * dstip;
	int srcport;
	int dstport;
	int proto;
	
};

//编写一个比较两个五元组是否相同的函数,0表示不相等,1表示相等
int wuyuan_isEqual(struct wuyuan a,struct wuyuan b)
{
	if(a.proto==b.proto){
		if(a.srcip==b.srcip && a.dstip==b.dstip && a.srcport==b.srcport && a.dstport==b.dstport)//五元组一模一样时.
		{
			return 1;
		}
		else{
			if(a.srcip==b.dstip && a.dstip==b.srcip && a.srcport==b.dstport && a.dstport==b.srcport)//五元组恰好相反
			{
				return 1;
			}
			else{
				return 0;
			}
		}
		
	}
	else{
		return 0;
	}
	
}     
//输入为数组和根域名和数量
int host_isexist(char * shuzu,char * dm_host,int sl){
	int host_len=strlen(dm_host);
	int z=0;
	while(z<host_len){
		if(*(shuzu+z)==*(dm_host+z)){
			if(z=host_len-1){
				//printf("loooook:%c",*(shuzu+z));
				return 1;
			}
		}
		z++;
	}
	return 0;
}

//建立新pcap包并写入内容,或在已有的pcap包的基础上写入内容。
//输入是w0/a1(新建还是追加)、根域名(arr)、文件指针、caplen值和偏移量,表格内的数量sl,tmp,pcap_head.
int out_pcap(int a,char * dm_host,FILE* pFile,int caplen,int pkt_offset,int sl,int tmp,char  pcap_head[24])
{
	//先根据根域名拼接好pcap包名。	
	char * outfile;
	outfile = (char *)malloc(100);
	int len=strlen(dm_host);
	int j;
	for(j=0;j<len;j++){
		*(outfile+j)=*(dm_host+j);
	}
	strcat(outfile,".pcap");	
	if(0==a){//创建新pcap包
		//定义pcap包的格式。
		
		FILE *output = fopen(outfile,"w+");//a+是在文件末尾开始加入。
						if( output == 0)
						{
							printf( "创建pcap文件失败");
							return 0;
						}  
		if(0==tmp)//说明是第一个,所以要上传pcap数据包头。
		{
			//这是第一个数据包,所有没有偏移。
			//每个数据包头都要传上pcap文件头。
		  fseek(pFile,24, SEEK_SET);
		  
		  fwrite(pcap_head,24,1,output);
		  char  cs[16+caplen];
		  
		 // fwrite(pFile,(16+ptk_header->caplen),1,output);
		 fread(cs,(16+caplen),1,pFile);
		 fwrite(cs,(16+caplen),1,output);
		 //printf("%s",cs);
		  fclose(output);
		}else{
			//把这个数据包写入。是数组里没有的数据包,要新建一个叫host的pcap文件。
					fseek(pFile, pkt_offset-16-caplen, SEEK_SET);//移动pfile文件指针位置,回到文件开头  
					  fwrite(pcap_head,24,1,output);
					  char  cs[16+caplen];					  
					 // fwrite(pFile,(16+ptk_header->caplen),1,output);
					 fread(cs,(16+caplen),1,pFile);
					 fwrite(cs,(16+caplen),1,output);
					 //printf("%s",cs);
					  fclose(output);
		}
		
	}else if(1==a){//在已有的pcap包基础上追加内容
		//打开已有的pcap包,在后面写入新数据。得到数组中的五元组,并拼接。
				
					FILE *output = fopen(outfile,"a+");
						if( output == 0)
						{
							printf( "打开pcap文件失败");
							return 0;
						}  
						
					//把这个数据包写入
					fseek(pFile, (pkt_offset-16-caplen), SEEK_SET);//移动pfile文件指针位置,回到数据包开头。 
					char  cs1[16+caplen];
					 // fwrite(pFile,(16+ptk_header->caplen),1,output);
					 fread(cs1,(16+caplen),1,pFile);
					 fwrite(cs1,(16+caplen),1,output);
					 //printf("%s",cs);
					  fclose(output);
	}
	return 1;
}

		  //查找src在dst中的位置,不存在则返回-1.考虑HOST、Host、host三种情况
		  //直接return host的值。
char * get_data_offset(char *src, char *dst,int dst_len)
{
	//先把src的首字母在dst中找,如果找到,则把dst中后面一部分与src相同长度的字符串摘出来进行比较,若相等则返回第一个位置,
	//否则返回-1.
	int dIndex=0;//dst移动下标
	int sIndex = 0;//src移动下标
	int src_len=strlen(src);
	//printf("%s\n",dst);
	//printf("!!!%d",src_len);
	while(dIndex <= dst_len-src_len){
		
		//如果两个字母相等,继续判断剩下的
		if(*src == *(dst+dIndex)){
			sIndex = 0;
			for(;sIndex<src_len;sIndex++){//往后遍历src长度的字符串
				//dst 和src一直没移动。
				if(*(dst+sIndex+dIndex)!=*(src+sIndex))//如果中间任何一个字母不等于
				{
			
					break;
				}else{ //如果全部等于
				//之前是sIndex和dIndex一直在移动。用一个tmpindex记录。
			
				}
			}
			if(sIndex == src_len){
				int tmp_index=dIndex+sIndex+2;//把: 都省略掉
				int host_len=0;
				char * host;
				host=(char *)malloc (100);
					while(*(dst+tmp_index)!='\r' && *(dst+tmp_index+1)!='\n'){//一直+1,直到碰到\r\n
					//	printf("%c",*(dst+tmp_index));
						*(host+host_len)=*(dst+tmp_index);
						tmp_index++;
						host_len++;
						
					}
					printf("\n");
				return host;
			}
		
		}		
		dIndex++;	//printf("src:%s",src);
			//printf("dst:%s\n",dst);
		
	}

	return NULL;
	
}
//先用字符串匹配,匹配是否有.com.cn,有的话取倒数第三个.右边的所有字符;没有的话取倒数第二个.右边的所有字符。
char * get_domain_from_host(char * host)
{
	char *z=".com.cn";
	char *tmp_res;
	char *res;
	int len=strlen(host);//记录host的长度。
	tmp_res=(char *)malloc (100);
	res=(char *)malloc (20);//输出的结果
	//调用字符串查找函数找有没有.com.cn
	tmp_res=get_data_offset(z,host,len);

	//创建一个函数,读取host中.的个数,并将其对应的下标位置记录下。
	//定义一个数组,记录下标值。再定义一个num记录.的个数。
	int mark[10];
	int num=0;
	int i=0;
	while(i<len){//遍历host
		if(*(host+i)=='.'){
			mark[num]=i;
			num++;
		}
		i++;
	}
	
	if(tmp_res==NULL){//说明没有.com.cn
		//取倒数第二个.右边的所有字符。第一个.的位置是mark[0],第二个.的位置是mark[1]...    倒数第一个.的位置是num-1;倒数第二个是num-2,倒数第三个是num-3.
		int j=mark[num-2]+1;
		int k=0;
		while(j<len){
			*(res+k)=*(host+j);
			k++;
			j++;
		}
		return res;
	}else{//说明有,取倒数第三个.右边的所有字符
		int j=mark[num-3]+1;
		int k=0;
		while(j<len){
			*(res+k)=*(host+j);
			k++;
			j++;
		}
		return res;
	}
	return NULL;
}
int hash(char *s){//计算字符串的hashcode值
    int h=0;
    for(;*s;s++)
        h=*s+h*31;
	if(h<0){
		h=0-h;
	}
    return h%100;
}

//有tuple和dm_host两个
//将五元组-根域名,插入到哈希表(五元组作为key)   
//确认这个五元组信息,是否可以从哈希表中查到(输入五元组去查找,值是damain_host),如果可以查到则将这个包写到pcap文件中,pcap文件名字是domain_host
//把字符串跟索引值联系起来的方法:计算字符串的hashcode
void hash_insert(struct NODE * host_5tuple_hash[],char* tuple,char * dm_host){
	int index=hash(tuple);
	printf("hashcode:%d\n",index);
	//创建一个新节点
	struct NODE *p;
	p=(struct NODE *)malloc (sizeof(struct NODE));
	
	int i = 0;
	
	p->tuple= (char*)malloc(strlen(tuple)+1);
	memcpy(p->tuple,tuple,strlen(tuple));
	*(p->tuple+strlen(tuple)) = '\0';
	p->dm_host=dm_host;
	//printf("????%s\n",p->tuple);
	//判断对应的哈希桶是否为空
	if(host_5tuple_hash[index]->next==NULL){
		//如果为空,将新节点接上去
		host_5tuple_hash[index]->next=p;
		p->next=NULL;
		
	}
	else{
		//不为空则遍历到为空的地方,再接上
		struct NODE *temp_head;
		temp_head=(struct NODE *)malloc (sizeof(struct NODE));
		temp_head=host_5tuple_hash[index];//移动temp_head指针
		while(temp_head->next!=NULL){
			temp_head=temp_head->next;
		}
		temp_head->next=p;
		p->next=NULL;
		
	}
	
}
//查询,从根域名查询host名称
struct NODE * hash_search(struct NODE * host_5tuple_hash[],char * tuple){
	int index=hash(tuple);
	if(host_5tuple_hash[index]->next==NULL){
		printf("zero");
		return NULL;
	}
	else{
		//不为空则打印domain_host及五元组值,再返回首地址
		printf("5tuple:%s\n",host_5tuple_hash[index]->next->tuple);
		printf("dmhost:%s\n",host_5tuple_hash[index]->next->dm_host);
		return host_5tuple_hash[index];
	}
}

//遍历一个数据包,得到数据包的五元组和根域名并且插入哈希表中。
void get_tuple_dmhost_hash(FILE* pFile,struct NODE * host_5tuple_hash[])
{
	struct pcap_pkthdr *ptk_header = NULL;//设置将要读取的pcap包的包头
    IPHeader_t *ip_header = NULL;
    TCPUDPHeader_t *tcpudp_header = NULL;
    Quintet_t *quintet = NULL;
    //初始化,分配内存
    ptk_header  = (struct pcap_pkthdr *)malloc(256);
    ip_header = (IPHeader_t *)malloc(sizeof(IPHeader_t));
    tcpudp_header = (TCPUDPHeader_t *)malloc(sizeof(TCPUDPHeader_t));
    quintet = (Quintet_t *)malloc(sizeof(Quintet_t));
    //memset(buf, 0, sizeof(buf));
	

    //开始读数据包------------
    long int pkt_offset;	//用来文件偏移
    pkt_offset = 24;       //pcap文件头结构 24个字节
    int i = 0;int j;

    while(1) //遍历数据包,结构:pcap文件头24B,数据包头16B(包括caplen),数据包内容中包括数据帧头14B,IP数据报头20B(源地址和目的地址),UDP/TCP数据包内容。
    {
        i++;
		fseek(pFile, pkt_offset, SEEK_SET);//移动pfile文件指针位置,跳过pcap文件头
		//对要存储的变量地址的内容进行初始化。
        memset(ptk_header, 0, sizeof(struct pcap_pkthdr));
        memset(quintet,0,sizeof(struct Quintet));	
        //读pcap数据包头结构,16个字节
        if(fread(ptk_header, 16, 1, pFile) != 1) 
        {
            printf("%d: can not read ptk_header\n", i);
            break;
        }
        pkt_offset += 16 + ptk_header->caplen;   //下一个数据包的开始位置为此数据包的起始位置+数据包头(16B)+数据长度caplen
		//printf("caplen:%d\n",ptk_header->caplen);
        //数据帧头 14字为ethnet协议大小,跳过。
        fseek(pFile,14, SEEK_CUR);
        //IP数据报头 20字节
        memset(ip_header, 0, sizeof(IPHeader_t));
        if(fread(ip_header, sizeof(IPHeader_t), 1, pFile) != 1)
        {
            printf("%d: can not read ip_header\n", i);
            break;
        }
        quintet->SrcIP = ip_header->SrcIP;
        quintet->DstIP = ip_header->DstIP;
        quintet->Protocol = ip_header->Protocol;
		
        memset(tcpudp_header,0,sizeof(TCPUDPHeader_t));
		//TCP/UDP头 20字节,端口字段是一样的
        if(fread(tcpudp_header, sizeof(TCPUDPHeader_t), 1, pFile) != 1)
            {
                printf("%d: can not read tcpudp_header\n", i);
                break;
            }
        quintet->SrcPort = tcpudp_header->SrcPort;
        quintet->DstPort = tcpudp_header->DstPort;
		//将数值转化为ip地址
		//printf("???%d\n",&ip_header->SrcIP);
		inet_ntop(AF_INET,&(ip_header->SrcIP),tempSrcIp,sizeof(tempSrcIp));
        inet_ntop(AF_INET, &(ip_header->DstIP),tempDstIp,sizeof(tempDstIp));

		//将数值转换为端口号
      quintet->SrcPort = ntohs(quintet->SrcPort);
      quintet->DstPort = ntohs(quintet->DstPort);
	
		//先把caplen长度的数据包内容读取到一个空间。再使用字符串查找的方法,形如http.host == "xxx" 或者Host: jingxi.co\r\n
		  char tmp_http[10000];
		 fseek(pFile, (pkt_offset-16-ptk_header->caplen), SEEK_SET);//回到每个数据包的开头。
		  if(fread(tmp_http,ptk_header->caplen,1,pFile)!=1)
		  {
			  printf("fail");
		  }

		  //使用字符串查找的方法。
		char *x="host";
		char * res;
		res=(char *)malloc (100);
		res=get_data_offset(x,tmp_http,ptk_header->caplen);
		if(res==NULL){
			x="Host";
			res=get_data_offset(x,tmp_http,ptk_header->caplen);
			if(res==NULL){
				x="HOST";
				res=get_data_offset(x,tmp_http,ptk_header->caplen);
				if(res==NULL){
					printf("search host fail");
					break;
				}
			}
		}
		//从host里面提取出顶级域名。考虑以下几种情况:除了.com.cn,都取倒数第二个.右边的所有字符。
		//所以先用字符串匹配,匹配是否有.com.cn,有的话取倒数第三个.右边的所有字符;没有的话取倒数第二个.右边的所有字符。
		char * domain_host;
		domain_host=(char *)malloc (20);
		domain_host=get_domain_from_host(res);
		printf("res:%s\n",domain_host);
		//插入哈希表,tuple=五元组
		char * tuple;
		tuple=(char *)malloc (100);
		char *sport;
					sport = (char *)malloc(20);
					sprintf(sport, "%d", quintet->SrcPort);	
					char *dport;
					dport = (char *)malloc(20);
					sprintf(dport, "%d", quintet->DstPort);	
					char *pro;
					pro = (char *)malloc(10);
					sprintf(pro, "%d", quintet->Protocol);	
					
					tuple=tempSrcIp;strcat(tuple,"_");strcat(tuple,tempDstIp);strcat(tuple,"_");strcat(tuple,sport);strcat(tuple,"_");
					strcat(tuple,dport);strcat(tuple,"_");strcat(tuple,pro);
					
		hash_insert(host_5tuple_hash,tuple,domain_host);
}
		//根据五元组查找根域名并输出。
		struct NODE * tmp_tuple;
		tmp_tuple=(struct NODE *)malloc (sizeof(struct NODE));
		//tmp_tuple=hash_search(host_5tuple_hash,"58.216.4.176_180.163.39.54_42205_80_6"); 
			//遍历链表进行输出
	/*for(j=0;j<100;j++){
		//说明桶子内有值,循环输出直到next为null
		if(host_5tuple_hash[j]->next!=NULL){
				printf("bucket%d:\n",j);
				struct NODE *temp_head2;
				temp_head2=(struct NODE *)malloc (sizeof(struct NODE));
				temp_head2=host_5tuple_hash[j];//移动temo_head2指针
				while(temp_head2->next!=NULL){
					
					printf("tuple:%s,",temp_head2->next->tuple);
					printf("dm_host:%s\n",temp_head2->next->dm_host);
				
					//指针移动
					temp_head2=temp_head2->next;
				}
		}*/
		free(ip_header);free(tcpudp_header);free(quintet);free(ptk_header);
}
//提取各个数据包的五元组,并去哈希表中进行查找,存在的话得到对应的根域名值,并且以此作为文件名把相同五元组的数据包输出为一个pcap数据包。
void search_hash_bydmhost(FILE* pFile,struct NODE * host_5tuple_hash[])
{
	struct pcap_pkthdr *ptk_header = NULL;//设置将要读取的pcap包的包头
    IPHeader_t *ip_header = NULL;
    TCPUDPHeader_t *tcpudp_header = NULL;
    Quintet_t *quintet = NULL;
    //初始化,分配内存
    ptk_header  = (struct pcap_pkthdr *)malloc(256);
    ip_header = (IPHeader_t *)malloc(sizeof(IPHeader_t));
    tcpudp_header = (TCPUDPHeader_t *)malloc(sizeof(TCPUDPHeader_t));
    quintet = (Quintet_t *)malloc(sizeof(Quintet_t));
    //memset(buf, 0, sizeof(buf));
/*	char filename[100];
	scanf("%s", &filename); 
	FILE* pFile = fopen( filename, "r");*/
	
    if( pFile == 0)
    {
        printf( "打开pcap文件失败");
    }
	//先创建一个数组记录已经创建过pcap包的根域名
	char * pcaped_host[10000];
	//计数,记录数组中已经存储多少个五元组了。
	int sl=0;

    //开始读数据包------------
    long int pkt_offset;	//用来文件偏移
    pkt_offset = 24;       //pcap文件头结构 24个字节
    int i = 0;
	//定义一个东西记录pcap数据包头,24字节。
	char  pcap_head[24];
	
	fread(pcap_head,24,1,pFile);
    while(1) //遍历数据包,结构:pcap文件头24B,数据包头16B(包括caplen),数据包内容中包括数据帧头14B,IP数据报头20B(源地址和目的地址),UDP/TCP数据包内容。
    {//提取到它的五元组
        i++;
		fseek(pFile, pkt_offset, SEEK_SET);//移动pfile文件指针位置,跳过pcap文件头;到每一次数据包开头的位置。
		//对要存储的变量地址的内容进行初始化。
        memset(ptk_header, 0, sizeof(struct pcap_pkthdr));
        memset(quintet,0,sizeof(struct Quintet));	
        //读pcap数据包头结构,16个字节
        if(fread(ptk_header, 16, 1, pFile) != 1) 
        {
            printf("%d: can not read ptk_header\n", i);
            break;
        }
        pkt_offset += 16 + ptk_header->caplen;   //下一个数据包的开始位置为此数据包的起始位置+数据包头(16B)+数据长度caplen
		//printf("caplen:%d\n",ptk_header->caplen);
        //数据帧头 14字为ethnet协议大小,跳过。
        fseek(pFile,14, SEEK_CUR);
        //IP数据报头 20字节
        memset(ip_header, 0, sizeof(IPHeader_t));
        if(fread(ip_header, sizeof(IPHeader_t), 1, pFile) != 1)
        {
            printf("%d: can not read ip_header\n", i);
            break;
        }
        quintet->SrcIP = ip_header->SrcIP;
        quintet->DstIP = ip_header->DstIP;
        quintet->Protocol = ip_header->Protocol;
		
        memset(tcpudp_header,0,sizeof(TCPUDPHeader_t));
		//TCP/UDP头 20字节,端口字段是一样的
        if(fread(tcpudp_header, sizeof(TCPUDPHeader_t), 1, pFile) != 1)
            {
                printf("%d: can not read tcpudp_header\n", i);
                break;
            }
        quintet->SrcPort = tcpudp_header->SrcPort;
        quintet->DstPort = tcpudp_header->DstPort;
		//将数值转化为ip地址
		//printf("???%d\n",&ip_header->SrcIP);
		inet_ntop(AF_INET,&(ip_header->SrcIP),tempSrcIp,sizeof(tempSrcIp));
        inet_ntop(AF_INET, &(ip_header->DstIP),tempDstIp,sizeof(tempDstIp));

		//将数值转换为端口号
      quintet->SrcPort = ntohs(quintet->SrcPort);
      quintet->DstPort = ntohs(quintet->DstPort);
	  
	  //到此为止得到了其五元组。暂时不考虑同一条流的,目的地和起始地互发的情况。把五元组进行拼接,再去哈希表中查找得到根域名。
	  //插入哈希表,tuple=五元组
		char * tuple2;
		tuple2=(char *)malloc (100);
		char *sport2;
					sport2 = (char *)malloc(20);
					sprintf(sport2, "%d", quintet->SrcPort);	
					char *dport2;
					dport2 = (char *)malloc(20);
					sprintf(dport2, "%d", quintet->DstPort);	
					char *pro2;
					pro2 = (char *)malloc(10);
					sprintf(pro2, "%d", quintet->Protocol);	
					
					tuple2=tempSrcIp;strcat(tuple2,"_");strcat(tuple2,tempDstIp);strcat(tuple2,"_");strcat(tuple2,sport2);strcat(tuple2,"_");
					strcat(tuple2,dport2);strcat(tuple2,"_");strcat(tuple2,pro2);
		//根据五元组查找根域名。
		struct NODE * tmp_host;
		tmp_host=(struct NODE *)malloc (sizeof(struct NODE));
		tmp_host=(hash_search(host_5tuple_hash,tuple2)); 
		int hostlen=strlen(tmp_host->next->dm_host);//这个是根域名
	//若两个数据包的端口号和ip地址恰好相反,则为同一个流。
	  //每一个流输出一个文件。
	  //创建一个数组,记录所有不同的五元组,并对应所有输出的pcap文件。每次检查一个新的数据包,就去数组里找,存不存在,存在就直接插入这个输出包里,不存在就先加入数组,再新建对应的pcap文件并写入。
	  if(sl==0)//如果这是第一个数据包,直接插入数组中,并创建新文件。
	  {
		  
		    pcaped_host[0]= (char*)malloc(hostlen+1);
			memcpy(pcaped_host[0],tmp_host->next->dm_host,hostlen);
			*(pcaped_host[0]+hostlen) = '\0';
		  
		  //创建新pcap包并写入数据。
		  //调用函数创建一个新的pcap包。(int a,struct wuyuan arr,FILE* pFile,int caplen,int pkt_offset,int sl,int temp,pcaphead)
		  out_pcap(0,tmp_host->next->dm_host,pFile,ptk_header->caplen,0,sl,0,pcap_head);
		  sl++;
	  }
	  else{//根据sl值遍历数组,判断是否存在。
			int tmp=0;
			int result=0;//先默认不存在.
			while(tmp<sl)
			{
				result=host_isexist(pcaped_host[tmp],tmp_host->next->dm_host,sl);
				if(result==1)//如果已经找到存在的
				{
					break;
				}
				tmp++;//到数组的下一个元素。
			} 
			if(result==0){//如果不在数组里,建立一个新的pcap包。
					//添加进数组,并且sl+1.
					pcaped_host[sl]= (char*)malloc(hostlen+1);
					memcpy(pcaped_host[sl],tmp_host->next->dm_host,hostlen);
					*(pcaped_host[sl]+hostlen) = '\0';
					//建议一个新的pcap包。
					out_pcap(0,tmp_host->next->dm_host,pFile,ptk_header->caplen,pkt_offset,sl,1,pcap_head);
					sl++;//假如有10个数据,最后一位已有的是9.现在添加第11个数据,位置是10
				}
			else if(result==1)//如果在数组里,tmp代表所相同的五元组的位置,输入到对应的pcap包里。
			{
					//打开已有的pcap包,在后面写入新数据。得到数组中的五元组,并拼接。
					out_pcap(1,tmp_host->next->dm_host,pFile,ptk_header->caplen,pkt_offset,sl,tmp,pcap_head);
			}
	  }
    } 
	//遍历完后,显示一下一共多少个pcap包。
	printf("shuliang:%d\n",sl);
}

int main()
{
	//创建哈希表的指针数组
	struct NODE * host_5tuple_hash[1000];
	//创建100个链表,并保存在指针数组中。
	int ii;
	for(ii=0;ii<100;ii++){
        struct NODE *head;
		head=(struct NODE *)malloc (sizeof(struct NODE));
		host_5tuple_hash[ii]=head;
		host_5tuple_hash[ii]->next=NULL;
	}
	
	FILE* pFile = fopen( "data.pcap", "r");
    if( pFile == 0)
    {
        printf( "打开pcap文件失败");
        return 0;
    }
	FILE* pFile2 = fopen( "data.pcap", "r");
    if( pFile == 0)
    {
        printf( "打开pcap文件失败");
        return 0;
    }
	//运行该函数,得到以五元组为key,根域名为值的哈希表,输入为数据包和空哈希表。
    get_tuple_dmhost_hash(pFile,host_5tuple_hash); fclose(pFile);
	//提取各个数据包的五元组,并去哈希表中进行查找,存在的话得到对应的根域名值,并且以此作为文件名把相同五元组的数据包输出为一个pcap数据包。
	search_hash_bydmhost(pFile2,host_5tuple_hash);
	
	fclose(pFile2);
    return 0;
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值