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] = '\0';

		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;
}


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