您的位置:首页 > 其它

cap,pcap文件中的ipv4数据包转成ipv6数据包

2017-10-09 11:12 986 查看
cap , pcap文件结构(解析),网上多得是,这里就不写了。  写这个,主要是工作中正好需要大量的ipv6数据包,但是ipv6数据包不太好找,干脆就直接写个简单的工具,把ipv4转成对应的ipv6,可用于测试。 

cpp代码:

// Ipv4ToIpv6_pCap.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>

#define DLT_EN10MB 1

struct pcap_file_header {
UINT32 magic;
UINT16 version_major;
UINT16 version_minor;
UINT32 thiszone; /* gmt to local correction */
UINT32 sigfigs; /* accuracy of timestamps */
UINT32 snaplen; /* max length saved portion of each pkt */
UINT32 linktype; /* data link type (LINKTYPE_*) */
};

struct pcap_pkthdr {
struct timeval ts; /* time stamp */
UINT32 caplen; /* length of portion present */
UINT32 len; /* length this packet (off wire) */
};

struct EthernetPacket
{
char MacDst[6]; ///< 目的网卡物理地址
char MacSrc[6]; ///< 源网卡物理地址
unsigned short PacketType; ///< 包类型, ip或ARP等
};

struct PKT_IP
{
UINT8 uHeaderLen:4;
UINT8 uVersion:4;
UINT8 uServType;
UINT16 uTotalLen;
UINT16 uIdent;
UINT16 uFragOffset;
UINT8 uTTL;
UINT8 uProtocol;
UINT16 uCheckSum;
UINT32 addSrc;
UINT32 addDst;
};

struct PKT_IPV6
{
union
{
UINT32 Vfc;
struct
{
UINT8 uClass:4;
UINT8 uVersion:4;
};
};
UINT16 uPayloadLength;
UINT8 uNextHeader;
UINT8 uHopLimit;
UINT8 addrSrc[16];
UINT8 addrDst[16];
};

inline UINT16 NTOH16(const UINT16& nData)
{
return ((nData & 0xFF00) >> 8) | ((nData & 0x00FF) << 8);
}

inline UINT32 NTOH32(const UINT32& nData)
{
return ((nData & 0xFF000000) >> 24)
| ((nData & 0x00FF0000) >> 8)
| ((nData & 0x0000FF00) << 8)
| ((nData & 0x000000FF) << 24);
}

int _tmain(int argc, char* argv[])
{
if (argc != 3)
{
printf("arg: inputfile, outputfile! \n");
//getchar();
return -1;
}

FILE* pFileIn = fopen(argv[1], "rb");
FILE* pFileOut = fopen(argv[2], "wb");

bool bSucces = false;
do
{
if (NULL == pFileIn || NULL == pFileOut)
{
printf("open file fail \n");
break;
}

pcap_file_header fileheader;
memset(&fileheader, 0, sizeof(pcap_file_header));
fread(&fileheader, 1, sizeof(fileheader), pFileIn);

if (DLT_EN10MB != fileheader.linktype)
{
printf("only support enthernet catch packets! \n");
break;
}

fwrite(&fileheader, 1, sizeof(fileheader), pFileOut);

pcap_pkthdr pkHdr;
UINT32 packetTotalCount = 0;
UINT32 packetTran = 0;
UINT8 packetBuffer[5*1024] = {};
do
{

if (sizeof(pkHdr) == fread(&pkHdr, 1, sizeof(pkHdr), pFileIn))
{
if (pkHdr.caplen != pkHdr.len)
{
// add
//printf("pkHdr.caplen != pkHdr.len packetNum = %d \n", packetTotalCount+1);
}
if (pkHdr.caplen == fread(packetBuffer, 1, pkHdr.caplen, pFileIn) && pkHdr.caplen > sizeof(EthernetPacket))
{
EthernetPacket* pEPacket = (EthernetPacket*)packetBuffer;
if (0x08 == pEPacket->PacketType) // ipv4
{
//
PKT_IP* pIpHdr = (PKT_IP*)(packetBuffer + sizeof(EthernetPacket));

pIpHdr->uTotalLen = NTOH16(pIpHdr->uTotalLen);
if (pkHdr.caplen < pIpHdr->uTotalLen + sizeof(EthernetPacket)) // 后面有可能会有补的数据,所以caplen可以会大于后面的值
{
printf("len error! packetNum = %d \n", packetTotalCount+1);
break;
}

pEPacket->PacketType = 0xDD86;
PKT_IPV6 pktIpv6Hdr;
memset(&pktIpv6Hdr, 0, sizeof(pktIpv6Hdr));
pktIpv6Hdr.uVersion = 6;
//pktIpv6Hdr.Vfc = CSNTOH32(pktIpv6Hdr.Vfc);

UINT16 paylen = pIpHdr->uTotalLen - pIpHdr->uHeaderLen*4;
pktIpv6Hdr.uPayloadLength = NTOH16(paylen);

pktIpv6Hdr.uNextHeader = pIpHdr->uProtocol;

pktIpv6Hdr.uHopLimit = pIpHdr->uTTL;
memcpy(pktIpv6Hdr.addrSrc+12, &(pIpHdr->addSrc), 4);
memcpy(pktIpv6Hdr.addrDst+12, &(pIpHdr->addDst), 4);

pkHdr.caplen = sizeof(EthernetPacket) + sizeof(PKT_IPV6) + paylen;
pkHdr.len = pkHdr.caplen;
fwrite(&pkHdr, 1, sizeof(pkHdr), pFileOut); // 写pack header
fwrite(pEPacket, 1, sizeof(EthernetPacket), pFileOut); // 写ether
fwrite(&pktIpv6Hdr, 1, sizeof(PKT_IPV6), pFileOut); // 写ipv6头
UINT8* pOtherData = packetBuffer + sizeof(EthernetPacket) + pIpHdr->uHeaderLen*4;
fwrite(pOtherData, 1, paylen, pFileOut); // 写剩下的数据

packetTran++;
}
else
{
// 其他包,直接写入
fwrite(&pkHdr, 1, sizeof(pkHdr), pFileOut);
fwrite(packetBuffer, 1, pkHdr.caplen, pFileOut);
}
}
else
{
printf("read packet caplen less packetNum = %d \n", packetTotalCount+1);
break;
}

packetTotalCount++;
}
else
{
if (feof(pFileIn))
{
//printf("read end! \n");
bSucces = true;
}
else
{
printf("Read less data! packetTotalCount = %d \n", packetTotalCount);
}
break;
}

} while (true/*!feof(pFileIn)*/);

printf("totalPacket = %d, transPacket = %d\n", packetTotalCount, packetTran);

} while (false);

if (pFileIn)
{
fclose(pFileIn);
}

if (pFileOut)
{
fclose(pFileOut);
}

if (!bSucces)
{
printf("Process %s fail! \n", argv[1]);
DeleteFileA(argv[2]);
}

//getchar();
//pcap_file_header
return 0;
}


另外还有个批处理文件 .bat

@echo off
::cd %~dp0

set inputFolder=E:\work\vsproject\Ipv4ToIpv6_pCap\Debug
set outPutFolder=E:\work\vsproject\Ipv4ToIpv6_pCap\Debug\newFolder
set exepath=E:\work\vsproject\Ipv4ToIpv6_pCap\Debug\Ipv4ToIpv6_pCap.exe
set suffix=_ipv6.cap

for /f "delims=\" %%s in ('dir /b /a-d /o-d %inputFolder%\*.pcap,*.cap') do (
echo -------------handle filename = %%s ------------
%exepath% %inputFolder%\%%s %outPutFolder%\%%s%suffix%
)

pause

写得比较简单,但是用于测试,还是可以的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  cap pcap ipv4 ipv6