之前在網上看到的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;
}