[转] pcap文件解析--pcap文件头与包文件头(一)

前段时间接到一个公司关于解析pacp文件的培训(我是被培训的),在完成了一部分的功能后决定把一些关于pcap文件的了解记录到博客中。

初识Pcap文件

在开始读取pcap文件之前,先让我们来看看Pcap文件的大概结构。
 
如上图所示在一个Pcap文件中存在1个Pcap文件头和多个数据包,其中每个数据包都有自己的头和包内容。
下面我们先看看PCAP文件头每个字段是什么意思:
magic为文件识别头,pcap固定为:0xA1B2C3D4。(4个字节)
magor version为主版本号(2个字节)
minor version为次要版本号(2个字节)
timezone为当地的标准时间(4个字节)
sigflags为时间戳的精度(4个字节)
snaplen为最大的存储长度(4个字节)
linktype为链路类型(4个字节)
常用类型:
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
10           FDDI
100         LLC/SNAP-encapsulated ATM
101         “raw IP”, with no link
102         BSD/OS SLIP
103         BSD/OS PPP
104         Cisco HDLC
105         802.11
108         later OpenBSD loopback devices (with the AF_value in network byte order)
113         special Linux “cooked” capture
114         LocalTalk
 
数据包头则依次为:时间戳(秒)、时间戳(微妙)、抓包长度和实际长度,依次各占4个字节。
 

读取各个数据包到单个pcap文件

c代码:
pcap_header.h
#pragma pack( push, 1)
// 为了保证在windows和linux下都能正常编译,放弃使用INT64或者_int_64
typedef short _Int16;
typedef	long  _Int32;
typedef char Byte;

// Pcap文件头
struct __file_header
{
	_Int32	iMagic;
	_Int16	iMaVersion;
	_Int16	iMiVersion;
	_Int32	iTimezone;
	_Int32	iSigFlags;
	_Int32	iSnapLen;
	_Int32	iLinkType;
};

// 数据包头
struct __pkthdr
{
	_Int32		iTimeSecond;
	_Int32		iTimeSS;
	_Int32		iPLength;
	_Int32		iLength;
};

#pragma pack( pop)

main.c
#include<stdio.h>
#include"pcap_header.h"
#include<memory.h>
#include<stdlib.h>
#include<math.h>

int main()
{
	struct __pkthdr data;
	struct __file_header	header;
	FILE* pFile = fopen( "iupsc.pcap", "rb");
    if( pFile == 0)
    {
        printf( "打开pcap文件失败");
        return 0;
    }

	fseek( pFile, 0, SEEK_END);
	long iFileLen = ftell( pFile);
	fseek( pFile, 0, SEEK_SET);

	Byte* pBuffer = (Byte*)malloc( iFileLen);
	fread( (void*)pBuffer, 1, iFileLen, pFile);
	fclose( pFile);

	memcpy( (void*)&header, (void*)(pBuffer)
			, sizeof(struct __file_header));

	int iIndex = sizeof(struct __file_header);
	int iNo = 1;
	while(iIndex <= iFileLen)
	{
		memcpy( (void*)&data, (void*)(pBuffer + iIndex)
			, sizeof(struct __pkthdr));

		char strPath[51];
		sprintf( strPath, "export/%d-%d.pcap", iNo++, (int)data.iTimeSecond);
		strPath[50] = '';

		FILE* pwFile = fopen( strPath, "wb");

		fwrite((void*)&header, 1, sizeof(struct __file_header), pwFile);
		fwrite( (void*)(pBuffer + iIndex), 1,
			sizeof(struct __pkthdr) + data.iPLength, pwFile);
		fclose( pwFile);


		iIndex += sizeof(struct __pkthdr) + data.iPLength;
	}

    free( pBuffer);
	printf( "成功导出%d个文件", iNo - 1);
	return 1;
}
原文地址:https://www.cnblogs.com/cxt-janson/p/9274084.html