用dpdk抓到的報文要自己保存成pcap格式的包,並且能用wireshark打開

經過這段時間接觸dpdk,瞭解了dpdk的工作模式和流程,現在需要從綁定的網卡上獲取數據包然後保存成pcpa格式的包,因爲dpdk綁定的網卡不用使用tcpdump 還有我這個版本也沒有pdump可以使用,只能自己解析。

之前在網上看到的demo都是把pcap文件解析成五元組之類的東西,現在根據那些demo反向寫一個保存的,下面是代碼,轉載希望能標註一下。

pcap.h:

//  pcap.h  
//  pcaptest  
    //  
    //  Created by ly on 18-5-25.  
 
       
#ifndef pcaptest_pcap_h  
#define pcaptest_pcap_h 

#include "comdef.h" 
       
typedef unsigned int  bpf_u_int32;  
typedef unsigned short  u_short;  
typedef int bpf_int32;  
       
    /* 
     Pcap文件頭24B各字段說明: 
     Magic:4B:0x1A 2B 3C 4D:用來標示文件的開始 
     Major:2B,0x02 00:當前文件主要的版本號      
     Minor:2B,0x04 00當前文件次要的版本號 
     ThisZone:4B當地的標準時間;全零 
     SigFigs:4B時間戳的精度;全零 
     SnapLen:4B最大的存儲長度     
     LinkType:4B鏈路類型 
     常用類型: 
     0            BSD loopback devices, except for later OpenBSD 
     1            Ethernet, and Linux loopback devices 
     6            802.5 Token Ring 
     7            ARCnet 
     8            SLIP 
     9            PPP 
     */  
typedef struct pcap_file_header {  
    bpf_u_int32 magic;  
    u_short major;  
    u_short minor;  
    bpf_int32 thiszone;      
    bpf_u_int32 sigfigs;     
    bpf_u_int32 snaplen;     
    bpf_u_int32 linktype;    
}pcap_file_header;  
       
    /* 
     Packet包頭和Packet數據組成 
     字段說明: 
     Timestamp:時間戳高位,精確到seconds      
     Timestamp:時間戳低位,精確到microseconds 
     Caplen:當前數據區的長度,即抓取到的數據幀長度,由此可以得到下一個數據幀的位置。 
     Len:離線數據長度:網絡中實際數據幀的長度,一般不大於caplen,多數情況下和Caplen數值相等。 
     Packet數據:即 Packet(通常就是鏈路層的數據幀)具體內容,長度就是Caplen,這個長度的後面,就是當前PCAP文件中存放的下一個Packet數據包,也就 是說:PCAP文件裏面並沒有規定捕獲的Packet數據包之間有什麼間隔字符串,下一組數據在文件中的起始位置。我們需要靠第一個Packet包確定。 
     */  
       
typedef struct  timestamp{  
    bpf_u_int32 timestamp_s;  
    bpf_u_int32 timestamp_ms;  
}timestamp;  
       
typedef struct pcap_header{  
    timestamp ts;  
    bpf_u_int32 capture_len;  
    bpf_u_int32 len;  
       
}pcap_header;  
       
       

void encode_pcap(struct rte_mbuf *pktbuf);
      
    #endif  

 





pcap.c:

#include <stdio.h>
#include "pcap.h"
#include "comdef.h"
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define MAGIC 0xa1b2c3d4
//#define MAJOR 2
//#define MINOR 4

 /*pktbuf是dpdk mbuf 的數據*/
void encode_pcap(struct rte_mbuf *pktbuf)
{
    
    printf("into endecode \n");
    u_short major =2;
    u_short minor =4;
    char *pbuf = (char*)pktbuf->pkt.data;
    uint16_t len =pktbuf->pkt.data_len;
    pcap_file_header pcap_file_hdr;
    timestamp pcap_timemp;
    pcap_header pcap_hdr;

    printf("[pcap_file_hdr]=%d\n",sizeof(pcap_file_hdr));
    printf("[pcap_hdr] = %d \n",sizeof(pcap_hdr));
    printf("[pcap_file_header]  = %d  \n",sizeof(pcap_file_header));
    printf("[pcap_header]  =  %d  \n",sizeof(pcap_header));


//初始化pcap頭
    printf("----struct--\n");
    pcap_file_hdr.magic = 0xa1b2c3d4;
    printf("magic\n");
    pcap_file_hdr.major = major;
    pcap_file_hdr.minor = minor;
    pcap_file_hdr.thiszone = 0;
    pcap_file_hdr.sigfigs  = 0;
    printf("snaplen\n");
    pcap_file_hdr.snaplen  = 65535;
    printf("pcap_file_hdr\n");
    pcap_file_hdr.linktype =1;
    

    pcap_timemp.timestamp_s = 0;
    pcap_timemp.timestamp_ms= 0;

    pcap_hdr.capture_len = (uint32_t)pktbuf->pkt.pkt_len;
    pcap_hdr.len = (uint32_t)pktbuf->pkt.pkt_len;

    int ret =0;

    ret = access("/home/ly/encode.pcap",0);//只寫入一個文件,首先判斷文件是否存在
    if(ret == -1)
    {//不存在創建,名且寫入pcap文件頭,和pcap頭,還有報文(tcp\ip 頭和數據)
        FILE *fd;
        int ret =0;
	fd = fopen("/home/ly/encode.pcap","wb+");
	if (fd == NULL )
	{
	    printf("w+:can't open the file\n");
	    return;
	}
        ret = write_file_header(fd,&pcap_file_hdr);
	if(ret == -1 )
	{
	    printf("write file header error!\n");
	    return;
	}
	fseek(fd,0,SEEK_END);
	ret = write_header(fd,&pcap_hdr);
	if(ret == -1 )
	{
	    printf("write header error!\n");
	    return;
	}
	fseek(fd,0,SEEK_END);
	ret = write_pbuf(fd,pktbuf);
	if (ret == -1)
	{
	    printf("write pbuf error!\n");
	    return;
	}
        fclose(fd);
        return;
    }
    FILE *fd_pcap;//如果文件已存在,直接向文件末尾寫入,pcap頭和數據
    int ret_a =0;
    fd_pcap = fopen("/home/ly/encode.pcap","ab+");
    if (fd_pcap == NULL)
    {
	printf("a+:can't no open file !\n");
	return;
    }
    fseek(fd_pcap,0,SEEK_END);
    ret_a = write_header(fd_pcap,&pcap_hdr);
    if(ret_a == -1)
    {
	printf("write header error! \n");
	return;
    }
    fseek(fd_pcap,0,SEEK_END);
    ret_a =write_pbuf(fd_pcap,pktbuf);
    if (ret_a == -1)
    {
	printf("write pbuf error! \n");
	return;
    }
    fclose(fd_pcap);
    return;
      
}

int write_file_header(FILE *fd , pcap_file_header * pcap_file_hdr)
{
    int ret =0;
    if(fd <0 )
	return -1;
    ret = fwrite(pcap_file_hdr,sizeof(pcap_file_header),1,fd);
    if (ret != 1 )
	return -1;
    return 0;
}

int write_header(FILE *fd ,pcap_header * pcap_hdr)
{
    int ret =0;
    if(fd < 0 )
	return -1;
    ret = fwrite(pcap_hdr,sizeof(pcap_header),1,fd);
    if(ret != 1)
	return -1;
    return 0;
}


int write_pbuf(FILE *fd ,struct rte_mbuf *pktbuf)
{
    int ret =0;
    if (fd < 0 )
	return -1;
    ret = fwrite(pktbuf->pkt.data,pktbuf->pkt.data_len,1,fd);
    if (ret != 1)
	return -1;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章